<?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: Tomasz Buszewski</title>
    <description>The latest articles on DEV Community by Tomasz Buszewski (@tomekbuszewski).</description>
    <link>https://dev.to/tomekbuszewski</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%2F115206%2Fca84604c-581a-4caa-9828-bc0081e04e3c.jpg</url>
      <title>DEV Community: Tomasz Buszewski</title>
      <link>https://dev.to/tomekbuszewski</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tomekbuszewski"/>
    <language>en</language>
    <item>
      <title>Design Systems in React – Scaffolding and Setup (Part 0)</title>
      <dc:creator>Tomasz Buszewski</dc:creator>
      <pubDate>Wed, 14 Aug 2024 21:36:13 +0000</pubDate>
      <link>https://dev.to/tomekbuszewski/design-systems-in-react-scaffolding-and-setup-part-0-5c8o</link>
      <guid>https://dev.to/tomekbuszewski/design-systems-in-react-scaffolding-and-setup-part-0-5c8o</guid>
      <description>&lt;p&gt;Creating and maintaining UI library or an entire design system is complex.&lt;br&gt;
Building one from scratch can be a challenge, so let’s prepare the project to&lt;br&gt;
make it easier.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is taken &lt;a href="https://buszewski.com/writings/2024-08-13-design-systems-in-react-scaffolding-and-setup-part-0" rel="noopener noreferrer"&gt;from my blog&lt;/a&gt;. You can also view &lt;a href="https://youtu.be/VTiVsxkvG0Q" rel="noopener noreferrer"&gt;the video on YouTube&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before we start, let’s lay some ground rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is part zero of a larger series, in which we will explore the whole topic
of developing a design system, from development environment (we are here),
through tokens and grouping, to even testing the components.&lt;/li&gt;
&lt;li&gt;I picked React, but this architecture is viable for every other library. I am
not using any particular features that only React has.&lt;/li&gt;
&lt;li&gt;I am using Tailwind due to its great customization options paired with tons of
ready-made code, but this is entirely optional. Vanilla CSS or any other
framework works perfectly fine.&lt;/li&gt;
&lt;li&gt;In the upcoming parts, I will be using Atomic Design methodology by
&lt;a href="https://bradfrost.com/blog/post/atomic-web-design/" rel="noopener noreferrer"&gt;Brad Frost&lt;/a&gt;. I find it
the most scalable solution as of yet for mid to large systems.&lt;/li&gt;
&lt;li&gt;This is &lt;em&gt;not&lt;/em&gt; a design tutorial. I won’t go into details on how things should
&lt;strong&gt;look&lt;/strong&gt; with each other, but I will dive into how they should &lt;strong&gt;work&lt;/strong&gt; with
each other.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All right, let’s start writing some code!&lt;/p&gt;
&lt;h2&gt;
  
  
  Bootstrapping and Storybook
&lt;/h2&gt;

&lt;p&gt;We start by creating a new project using Vite:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ npm create vite@latest react-design-system &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; react-ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new directory called &lt;code&gt;react-design-system&lt;/code&gt; in which we will&lt;br&gt;
find all the required things to start. After the process is completed, we need&lt;br&gt;
to install the dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ &lt;span class="nb"&gt;cd &lt;/span&gt;react-design-system
~ npm i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just to be sure, let’s run the development command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Works! Great. Now let’s start with the actual environment.&lt;/p&gt;

&lt;p&gt;First off, Storybook. It’s the golden standard for developing UI, and supports&lt;br&gt;
many libraries out of the box, including React, Vue, Angular and Svelte. So, in&lt;br&gt;
our main directory:&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;Historically, Storybook was bundled by Webpack, and it is still supported. But&lt;br&gt;
it also support Vite, both out of the box. As you can see, the installer itself&lt;br&gt;
decided what to use, so that’s all we had to do!&lt;/p&gt;

&lt;p&gt;One thing is that Storybook collects some telemetry. If you’re fine with this,&lt;br&gt;
that’s completely fine, but if you want to opt out, go to &lt;code&gt;./.storybook/main.ts&lt;/code&gt;&lt;br&gt;
and add&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;disableTelemetry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to the &lt;code&gt;config&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Installing Storybook today is as seamless as can be. I still remember how&lt;br&gt;
problematic it could be back in the late 2010s, when Webpack came with tons of&lt;br&gt;
config and you had to adjust every bit of it for your app and Storybook’s just&lt;br&gt;
to make it render the same.&lt;/p&gt;
&lt;h2&gt;
  
  
  Adding Tailwind
&lt;/h2&gt;

&lt;p&gt;The next step is to add Tailwind. Tailwind is pretty seamless to add to the&lt;br&gt;
project, so let’s start.&lt;/p&gt;

&lt;p&gt;First, we need to install the library and its dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ npm i &lt;span class="nt"&gt;-D&lt;/span&gt; tailwindcss postcss autoprefixer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this ends, we can initialize it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ npx tailwindcss init &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By adding &lt;code&gt;-p&lt;/code&gt; flag, the wizard will also create PostCSS config that will then&lt;br&gt;
utilize &lt;code&gt;autoprefixer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Right, so let’s configure Tailwind to see our files. In the config file&lt;br&gt;
(&lt;code&gt;tailwind.config.js&lt;/code&gt;), set &lt;code&gt;config&lt;/code&gt; property to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/**/*.{ts,tsx}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will make Tailwind scan aforementioned files.&lt;/p&gt;

&lt;p&gt;Now create &lt;code&gt;style.css&lt;/code&gt; file in &lt;code&gt;./src&lt;/code&gt; and put the basics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And import the file in &lt;code&gt;main.tsx&lt;/code&gt;:&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="c1"&gt;// ./src/main.tsx&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StrictMode&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createRoot&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App.tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it for the app. We can run the dev mode and see if it works.&lt;/p&gt;

&lt;p&gt;But that’s not everything. Storybook doesn’t know we want to use Tailwind and&lt;br&gt;
won’t see it. Luckily, this is an easy fix. Go to &lt;code&gt;./storybook/preview.ts&lt;/code&gt; and&lt;br&gt;
import the CSS file we’ve made earlier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../src/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding linters
&lt;/h2&gt;

&lt;p&gt;One of the most crucial things in development is code style. I know it sounds&lt;br&gt;
funny and you might think I am overreacting, but fighting over spaces, quotes&lt;br&gt;
and line lengths can often balloon and become a real problem. A good way to&lt;br&gt;
solve the issue early is to throw Prettier and ESLint in. Let’s do it now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ npm i prettier &lt;span class="nt"&gt;-D&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will add the &lt;code&gt;prettier&lt;/code&gt; package to our project. We need to configure it, so&lt;br&gt;
let’s create the config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * @type {import("prettier").Config}
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;semi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;singleQuote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tabWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;trailingComma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I like to have this as a standard: always add semicolons, use double quotes, use&lt;br&gt;
two spaces and add trailing commas to all elements.&lt;/p&gt;

&lt;p&gt;While Prettier can work as a command line utility, I strongly suggest&lt;br&gt;
configuring your IDE to reformat the file on save. In IntelliJ this is done via&lt;br&gt;
Settings &amp;gt; Languages &amp;amp; Frameworks &amp;gt; JavaScript &amp;gt; Prettier, and in there, pick&lt;br&gt;
"Automatic Prettier Configuration" and check "Run on Save".&lt;/p&gt;

&lt;p&gt;To start fresh and have all the files formatted correctly, go into terminal and&lt;br&gt;
run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ prettier &lt;span class="nt"&gt;-w&lt;/span&gt; ./&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will reformat and write (hence the &lt;code&gt;-w&lt;/code&gt; flag) all files in the project.&lt;/p&gt;

&lt;p&gt;As for ESLint, Vite adds it automatically, and with decent settings to boot. For&lt;br&gt;
the sake of brevity, I will leave it as-is. You can, obviously, modify it to&lt;br&gt;
your needs and make it as lax or as strict as you want. One thing to remember&lt;br&gt;
here is that, by default, ESLint uses its new “flat” config, and some plugins&lt;br&gt;
aren’t compatible. There’s &lt;code&gt;FlatCompat&lt;/code&gt; class exposed by &lt;code&gt;@eslint/eslintrc&lt;/code&gt;, but&lt;br&gt;
I had mixed results with it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Defining our first component
&lt;/h2&gt;

&lt;p&gt;If all is configured, let’s get to work. There’s &lt;code&gt;stories&lt;/code&gt; directory created by&lt;br&gt;
Storybook which serves as an example repository. You can keep it, be we won’t be&lt;br&gt;
using it. We’ll create another “space” for the UI, named, well, &lt;code&gt;ui&lt;/code&gt;. From&lt;br&gt;
there, we will export all the public components to use across the app.&lt;/p&gt;

&lt;p&gt;I like to have a global export file in every space, and with that, a shortcut&lt;br&gt;
defined in &lt;code&gt;tsconfig.json&lt;/code&gt;. Something like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@path/* -&amp;gt; ./src/path/*
@path -&amp;gt; ./src/path/index.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I won’t dive into Atomic Design today to save time, so let’s just create a basic&lt;br&gt;
component in the UI space to get it going!&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="c1"&gt;// ./ui/Info/Info.tsx&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HTMLAttributes&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;HTMLAttributes&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLDivElement&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;variant&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;warning&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;variant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;Props&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;cls&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;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;warning&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bg-yellow-100 text-yellow-800 border-yellow-500&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bg-red-100 text-red-800 border-red-500&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bg-blue-100 text-blue-800 border-blue-500&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
      &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"alert"&lt;/span&gt;
      &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p-4 mb-4 text-sm text-blue-800 rounded-lg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could (and will, soon) add more to the directory, like styles and tests. But&lt;br&gt;
for now, just this file. And let’s export it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./ui/index.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Info&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;./Info/Info&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And let’s add the TypeScript paths.&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="nl"&gt;"compilerOptions"&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;"paths"&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;"@ui"&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="s2"&gt;"./src/ui/index.ts"&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;But, this won’t work just yet! We need to install &lt;code&gt;vite-tsconfig-paths&lt;/code&gt; to allow&lt;br&gt;
Vite to understand it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ npm i &lt;span class="nt"&gt;-D&lt;/span&gt; vite-tsconfig-paths
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And add it in the config. I suggest putting it first just to be safe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./vite.config.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&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;vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&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;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;tsconfigPaths&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;vite-tsconfig-paths&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// https://vitejs.dev/config/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;tsconfigPaths&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;react&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;Great, so we have our component, but how to see how it looks? Well, you might&lt;br&gt;
throw it in the main file, but there’s a better way.&lt;/p&gt;
&lt;h2&gt;
  
  
  Writing stories
&lt;/h2&gt;

&lt;p&gt;To create a story, first create its file: &lt;code&gt;Info.stories.tsx&lt;/code&gt;. The process is&lt;br&gt;
rather straightforward, and mostly consists of configuration.&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;StoryObj&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;@storybook/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Info&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;./Info&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Meta&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Info&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;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;UI/Info&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Info&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;const&lt;/span&gt; &lt;span class="nx"&gt;Primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StoryObj&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Info&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;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello from Storybook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Let’s go through the file. First, we import types and the component in question.&lt;br&gt;
Then we define the &lt;code&gt;meta&lt;/code&gt; where all the info that Storybook digest resides. Note&lt;br&gt;
the slash in the title – adding each creates a new “directory”, so right now we&lt;br&gt;
have UI → Info, but soon we’ll expand this.&lt;/p&gt;

&lt;p&gt;Last, but not least, is the definition of the story, named “Primary” as per&lt;br&gt;
standard. But the naming is unimportant, it can be whatever, as long as it’s a&lt;br&gt;
valid component (so, as long as it starts with a capital letter).&lt;/p&gt;

&lt;p&gt;Okay, we got this, so let’s try if it works!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ npm run storybook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see the Storybook page, and in the sidebar there’s an “UI” space, all&lt;br&gt;
works great!&lt;/p&gt;
&lt;h2&gt;
  
  
  Adding Plop to generate scaffolding
&lt;/h2&gt;

&lt;p&gt;This is all fine and well, but creating such components and stories will surely&lt;br&gt;
prove exhausting, right?&lt;/p&gt;

&lt;p&gt;Yes. You can trust me here, it will get old very, very fast.&lt;/p&gt;

&lt;p&gt;That’s why we can use a generator that will create empty components for us. Plop&lt;br&gt;
can do this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ npm i &lt;span class="nt"&gt;-D&lt;/span&gt; plop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And create the config file in the root, named &lt;code&gt;plopfile.mjs&lt;/code&gt;. In there, we can&lt;br&gt;
define what we want to generate. Let’s start by defining a UI component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./plopfile.mjs&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;plop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/** @type {import('plop').NodePlopAPI} */&lt;/span&gt; &lt;span class="nx"&gt;plop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;plop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&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;description&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 a new UI component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;prompts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Component name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Right now, it does nothing. Simply defines that such generator exists and asks&lt;br&gt;
for the name, but to actually write files, it needs an “action”.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./plopfile.mjs&lt;/span&gt;

&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;add&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/ui/{{pascalCase name}}/{{pascalCase name}}.tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;templateFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./plop-templates/Component.tsx.hbs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;add&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/ui/{{pascalCase name}}/{{pascalCase name}}.stories.tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;templateFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./plop-templates/Story.tsx.hbs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;append&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/ui/index.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;export { default as {{pascalCase name}} } from "./{{pascalCase name}}/{{pascalCase name}}";&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;Let’s go from the top. First, we &lt;em&gt;add&lt;/em&gt; a new file, with path being&lt;br&gt;
&lt;code&gt;src/ui/Name/Name name.tsx&lt;/code&gt;. If you look into the “prompts”, you’ll see that&lt;br&gt;
there’s &lt;code&gt;name&lt;/code&gt; property that is reflected in here. It also uses a template that&lt;br&gt;
we are yet to write.&lt;/p&gt;

&lt;p&gt;Second action is the same, it just has the story. And the third one is&lt;br&gt;
&lt;em&gt;appending&lt;/em&gt; the export to the main &lt;code&gt;index.ts&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Right, so let’s create the templates! It’s written in Handlebars and, frankly,&lt;br&gt;
it’s quite straightforward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight handlebars"&gt;&lt;code&gt;// ./plop-templates/Component.tsx.hbs

import type { ReactNode, HTMLAttributes } from "react";

interface Props extends HTMLAttributes&lt;span class="nt"&gt;&amp;lt;HTMLDivElement&amp;gt;&lt;/span&gt; {
  children: ReactNode;
}

export default function &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;pascalCase&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;(props: Props) {
  return (
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="err"&gt;{...&lt;/span&gt;&lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="err"&gt;}&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;As you see, it’s very barebones. That’s by design, because eventually we will&lt;br&gt;
expand component types and have different templates. For now, this will suffice.&lt;br&gt;
Same with the story:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight handlebars"&gt;&lt;code&gt;// ./plop-templates/Story.tsx.hbs

import type { Meta, StoryObj } from "@storybook/react";
import &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;pascalCase&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt; from "./&lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;pascalCase&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;";

const meta: Meta&lt;span class="nt"&gt;&amp;lt;typeof&lt;/span&gt; &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;pascalCase&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; = {
  title: "UI/&lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;pascalCase&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;",
  component: &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;pascalCase&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;,
};

export const Primary: StoryObj&lt;span class="nt"&gt;&amp;lt;typeof&lt;/span&gt; &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;pascalCase&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; = {
  args: {
    children: "Hello from Storybook",
  },
};

export default meta;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, let’s add the shortcut to npm scripts:&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="nl"&gt;"scripts"&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="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nl"&gt;"plop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plop"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There’s one thing I like to do, and it’s to have Prettier run through the files&lt;br&gt;
after we are done. It’s achievable with post-scripts:&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="nl"&gt;"scripts"&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="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nl"&gt;"plop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"postplop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier --write 'src/**/*.{ts,tsx}'"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Right, so let’s test!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ npm run plop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything worked, we should see a success report. All that’s left is to fire&lt;br&gt;
up Storybook and see if all is fine!&lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;p&gt;UI libraries are complex, and the devil is always in the details. Today we’ve&lt;br&gt;
managed to create a solid ground for development. Join me in the next videos&lt;br&gt;
from the series, where we will dive into tests, visual regressions and atomic&lt;br&gt;
design.&lt;/p&gt;

</description>
      <category>react</category>
      <category>designsystem</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>How to Run Technical Interviews</title>
      <dc:creator>Tomasz Buszewski</dc:creator>
      <pubDate>Fri, 09 Aug 2024 12:26:15 +0000</pubDate>
      <link>https://dev.to/tomekbuszewski/how-to-run-technical-interviews-h6o</link>
      <guid>https://dev.to/tomekbuszewski/how-to-run-technical-interviews-h6o</guid>
      <description>&lt;p&gt;Running a good interview is one of the most important skills as a developer. And yet, many of us struggle to get it right.&lt;/p&gt;

&lt;p&gt;This is a repost from &lt;a href="https://buszewski.com/writings/2024-08-08-how-to-run-technical-interviews/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also &lt;a href="https://www.youtube.com/watch?v=lq4x4uwPtug" rel="noopener noreferrer"&gt;watch the video on YouTube&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Describe the Interview Process
&lt;/h2&gt;

&lt;p&gt;That’s basically the step zero. Take a minute to tell the candidate what will happen during the interview. Tell them what stages are there. This will show them that you came prepared and you know what you are doing. &lt;/p&gt;

&lt;h2&gt;
  
  
  Bring Someone with You
&lt;/h2&gt;

&lt;p&gt;You are hiring for the team, not for yourself. Dynamic is very important, and seeing how candidate can talk and work with a potential colleague is extremely important. That’s why I always try to bring someone with me. &lt;/p&gt;

&lt;p&gt;If I can, I take someone with the opposite seniority. If candidate’s senior, I take a junior, and vice versa. Two seniors will get along quicker than a senior and a junior. &lt;/p&gt;

&lt;p&gt;Besides, it’s always a second pair of eyes, so they might notice whatever you’ve missed. Make sure to debrief after the call, when thoughts are still fresh. I suggest doing a quick five minutes sync right after the interview, and then writing it down after an hour or so. That way you’ll get what’s on your mind quickly, and then, after your mind structures it, you’ll write a formal feedback.&lt;/p&gt;

&lt;p&gt;Sometimes I left even more time for my mind to wander, and wrote the feedback in the next day. Especially if the interview was the last thing to do in a given day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don’t Get Technical at the Beginning
&lt;/h2&gt;

&lt;p&gt;This one I’ve seen way too many times. “Hi, my name is Xyz, let’s start, can you tell me all the array methods in JavaScript?” right off the bat, on a single breath. This is very bad, for both parties, because you lose the opportunity to sink into the meeting. A few minutes of chat won’t ruin your plan, but will give you the opportunity to get to know the person you’ll spend the next hour or so a bit better.&lt;/p&gt;

&lt;p&gt;I always start with a bit of a small talk, mostly basing on an interesting part of the CV (like interests, school I know of, side projects, you name it) or on some background detail, like a poster or a figurine (&lt;em&gt;Dark Souls&lt;/em&gt; merch = instant hire in my book, btw). I never rush this section, as candidate will take the time to tell a bit about themselves, but also to acclimatize to the situation. Once you find that the topic has run its course and is drying up, proceed onwards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make Proper Introduction of Yourself and the Company
&lt;/h2&gt;

&lt;p&gt;When I started going on interviews, the golden rule was to know at least a bit about the company. Now it’s not always the case. Chances are, you’re not hiring for Google, and candidates, especially those who are looking for “a job” rather than “the job in the company”, might not know about you guys. It’s up to you to tell them why it’s a good idea to join. Introduce yourself, tell them what are you doing in here and for how long you’ve been in your position. Describe what the company does, describe the service in more details than the job posting or “about” page. &lt;/p&gt;

&lt;p&gt;What’s important here is to underline that if they have questions, they are welcome to ask. Sometimes candidates will want to ask something, but you’ll be talking and talking for ten minutes, and once you’re done, the interviewee will forget what they wanted to know.&lt;/p&gt;

&lt;p&gt;It’s also a good thing to describe the project from technical perspective. All the things you think a developer should be aware of. Don’t overdo it though, don’t spend thirty minutes detailing the last test you wrote, just deliver the basics, such as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stack;&lt;/li&gt;
&lt;li&gt;high level architecture;&lt;/li&gt;
&lt;li&gt;team structure;&lt;/li&gt;
&lt;li&gt;project management (methodology, amount of work);&lt;/li&gt;
&lt;li&gt;deployment and testing flows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember to tell the truth here. Sugarcoating is a short-term game, and if they join and find out you lied to them, they might lose any trust they have for you and the company. If you don’t have tests  – tough luck, admit to that. If you’re deploying via FTP, okay, say it. They should know what they are signing for, even if it’s uncomfortable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ask About Real Life Problems
&lt;/h2&gt;

&lt;p&gt;Sometime ago there was a popular term in IT. “Grilling" meant that you take the candidate and throw questions at them to make them sweat, just like you would keep them over a grill. I find this practice extremely poor. Why would you make the person uncomfortable? Why would you stress them?&lt;/p&gt;

&lt;p&gt;Instead of asking hundred of small questions nitpicked from the documentation, ask about real life problems. “How do you know when to start optimizing your code? How do you do the optimizations?”, “How and why would you use dependency injection” or “How would you handle a situation when a colleague submits very poor pull request”. These are just a couple of examples. And they will tell you more than “What does &lt;code&gt;clamp()&lt;/code&gt; do in CSS” or “What’s the difference between &lt;code&gt;var&lt;/code&gt; and &lt;code&gt;let&lt;/code&gt;”.&lt;/p&gt;

&lt;p&gt;Such questions are also a good opportunity to see what’s the person’s stronger sides. If they dive deep into the answer, consider jumping in and following the thread, ask follow-up questions. With answers that aren’t going according to your expectations, don’t overdo it. If you push the person too hard, they might lock themselves and it will be super hard to get out of that hole.&lt;/p&gt;

&lt;p&gt;When asking, make sure to observe what the person is doing, though. Are they reading something? I had a situation when the interviewee asked Chat GPT all the questions, and read the answers. I knew something’s off, because it felt formulaic, like describing a painting you’ve only heard of. And how I know it for sure? Later on we did screen sharing and they forgot to close the chat tab, so we were able to see everything.&lt;/p&gt;

&lt;p&gt;And since we’re talking about screen sharing…&lt;/p&gt;

&lt;h2&gt;
  
  
  Have a Pair Programming Session…
&lt;/h2&gt;

&lt;p&gt;Seeing someone writing their own code is always a good thing. While people might not love it, I’d call it necessary evil. But, instead of asking the candidate to write you a binary tree and then reverse it while you sit muted, have a pair programming session.&lt;/p&gt;

&lt;p&gt;I tend to use this part when we talk to a senior, and I have a junior with me. Let them work together, let’s see how fast they will catch on. Senior should lead the pair, so it’s a good way to test how they handle such situations. How they can explain something to someone with less knowledge, how they paint their plans for the solution, how they execute it. &lt;/p&gt;

&lt;p&gt;In this section, it’s important to remember that delivering a working solution is not the case. After all, limited time and stress will hinder the interviewee’s skills, and you’re (hopefully) not hiring the fastest typist. What’s important is to see how they proceed, plan and execute the solution, as mentioned before. Ask your junior afterwards, was it all clear from the beginning? Were they able to follow along?&lt;/p&gt;

&lt;p&gt;One red flag I always look out for here is when the senior acts superior to the lesser-experienced colleague. Being condescending is something many seasoned developers are struggling with (ask me how I know, I dare you), often without knowing it. While sometimes it’s something you can work on with the said person, you must consider whether you have the time to invest, and will they be willing to make the effort.&lt;/p&gt;

&lt;h2&gt;
  
  
  …or a System Design Challenge
&lt;/h2&gt;

&lt;p&gt;If you need to hire someone that will be more self-reliant, consider doing a system design challenge. It requires you to play the Product Owner or Manager part for a bit though. &lt;/p&gt;

&lt;p&gt;Think of the problem before the interview. I like to go with auth flow, so my main prompt is “we have a public and private areas in our app and we want people to register and log in to see the latter.” It’s vague on purpose, because getting more details is a part of the challenge. If the candidate jumps straights into delivering a solution, that’s a red flag and almost always a poor solve.&lt;/p&gt;

&lt;p&gt;Ideally, the candidate should ask tons of questions, from the exact requirements, through stack, finally, to acceptance criteria. After all this, they should have something that is more similar to a user story rather than to one sentence they heard at the start.&lt;/p&gt;

&lt;p&gt;Form of the solution is completely up to them, though. If they don’t propose anything, I suggest &lt;a href="https://draw.io" rel="noopener noreferrer"&gt;draw.io&lt;/a&gt;, but most of the time, candidates have their own tools. Some will draw you full UML diagrams, some will just throw a couple of rectangles connected by arrows. The form is extremely unimportant. What matters is how the solution works, and how they react to critique and questions. &lt;/p&gt;

&lt;p&gt;Asking questions about the solution is super important. It will tell you whether the person can defend their vision and how they react to being challenged. You want to question their decisions, even if they seem fine to you. Try asking questions you know are fundamentally wrong, and see how they react. &lt;/p&gt;

&lt;h2&gt;
  
  
  Leave Them Time for Questions
&lt;/h2&gt;

&lt;p&gt;I always make sure to highlight the fact that the candidate can ask whenever they feel like. But sometimes they won’t want to, and will keep their doubts and comments until the end. Make sure you give them time to ask. And answer honestly. &lt;/p&gt;

&lt;p&gt;I like to say that interviews are a form of dance where both parties try to enchant one another. But that’s something I actively avoid during my meetings. Answering dishonestly, as mentioned early, will hinder their trust, and that’s a short way to quitting. &lt;/p&gt;

&lt;p&gt;This section can be lengthy, so make sure to have you have time to spare. If you notice you’re running out of planned time, ask whether they can stay for a few minutes so that you can answer all the questions. If they can’t, offer a follow-up email.&lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;p&gt;That’s it, that’s my recipe for conducting good technical interviews. No grilling, no whiteboard coding, no hoops to jump. Just a good talk with some tech challenges at the end. I hope you’ll find it helpful!&lt;/p&gt;

&lt;p&gt;Good luck interviewing!&lt;/p&gt;

</description>
      <category>interview</category>
      <category>hr</category>
      <category>hiring</category>
      <category>recruitment</category>
    </item>
    <item>
      <title>How to Add OpenAPI to your Express App?</title>
      <dc:creator>Tomasz Buszewski</dc:creator>
      <pubDate>Tue, 06 Aug 2024 09:02:27 +0000</pubDate>
      <link>https://dev.to/tomekbuszewski/how-to-add-openapi-to-your-express-app-24k4</link>
      <guid>https://dev.to/tomekbuszewski/how-to-add-openapi-to-your-express-app-24k4</guid>
      <description>&lt;p&gt;Proper documentation is the key for comfortable work with your code. And the&lt;br&gt;
best documentation is the one you generate, not write.&lt;/p&gt;

&lt;p&gt;This is a repost from &lt;a href="https://buszewski.com/writings/2024-08-05-how-to-add-openapi-to-your-express-app/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also &lt;a href="https://www.youtube.com/watch?v=AzAr4TpNbmI" rel="noopener noreferrer"&gt;watch the video on YouTube&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Structure and Preparations
&lt;/h3&gt;

&lt;p&gt;Let’s say we have a simple Express application written in TypeScript. It&lt;br&gt;
consists of only one area – “chores”. It’s glorified todo app, yes. It has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;main.ts&lt;/code&gt; as the app’s entry point;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app.ts&lt;/code&gt; for the app initialization;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chore/&lt;/code&gt; as the actual business unit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the logic, it’s not really that important. What matters is that we have&lt;br&gt;
controller as classes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./chore/controller.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ChoreService&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;./service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BaseChore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Chore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ChoreUpdate&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;./types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ChoreController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ChoreService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;ChoreService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ChoreService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;service&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;getAllChores&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Chore&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllChores&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;createChore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BaseChore&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Chore&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createChore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chore&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;updateChore&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="nx"&gt;chore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ChoreUpdate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Chore&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateChore&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="nx"&gt;chore&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;deleteChore&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="nx"&gt;Chore&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteChore&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="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;It uses a service, but that’s really beyond the point. We could (we shouldn’t,&lt;br&gt;
but we could) dump all the logic in the controller and it wouldn’t matter for&lt;br&gt;
this example.&lt;/p&gt;

&lt;p&gt;There’s also &lt;code&gt;routes.ts&lt;/code&gt; file that basically takes URLs and payloads and pushes&lt;br&gt;
it further:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./chore/routes.ts&lt;/span&gt;

&lt;span class="k"&gt;import&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;Request&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;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Router&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;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ChoreController&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;./controller&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ChoreService&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;./service&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BaseChore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ChoreRequest&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;./types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Router&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;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ChoreController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ChoreService&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllChores&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BaseChore&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;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid chore&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;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createChore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/:id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChoreRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BaseChore&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;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&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="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid chore&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateChore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/:id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChoreRequest&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;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteChore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it is exported and thrown into the express app in &lt;code&gt;app.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Express&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;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;chores&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;./chore&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;chores&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…which in return is taken by &lt;code&gt;main.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&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;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;app&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;./app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it for preparations. This is a fully working app that accepts GET, POST,&lt;br&gt;
PUT and DELETE. But to know it, you have to go through the code. This is where&lt;br&gt;
OpenAPI comes in.&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding TSOA for generating docs
&lt;/h3&gt;

&lt;p&gt;In order to enhance the controller with OpenAPI markers, we will use&lt;br&gt;
&lt;a href="https://github.com/lukeautry/tsoa" rel="noopener noreferrer"&gt;TSOA&lt;/a&gt;. It’s battle-tested library built&lt;br&gt;
exactly for this purpose. If you’ve worked with NestJS or TsED, you might’ve&lt;br&gt;
seen decorators like &lt;code&gt;Get()&lt;/code&gt; or &lt;code&gt;Post()&lt;/code&gt; for controllers. That’s TSOA.&lt;/p&gt;

&lt;p&gt;Let’s start by adding the library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ npm &lt;span class="nb"&gt;install &lt;/span&gt;tsoa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It comes fully typed, so there’s no need to add anything more.&lt;/p&gt;

&lt;p&gt;After it is installed, let’s create &lt;code&gt;tsoa.json&lt;/code&gt; file in the root of our project.&lt;br&gt;
It’s the config file for the generator, it tells it where to look for&lt;br&gt;
controllers and where to save the docs. It looks like this:&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;"entryFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/main.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"controllerPathGlobs"&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="s2"&gt;"./src/**/controller.ts"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"spec"&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;"outputDirectory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"specVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"spec"&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;"servers"&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:3000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Local server"&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="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;Going from the top,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;entryFile&lt;/code&gt; is for which file is the main one;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;controllerPathGlobs&lt;/code&gt; is a
&lt;a href="https://en.wikipedia.org/wiki/Glob_(programming)" rel="noopener noreferrer"&gt;glob&lt;/a&gt; for where to look
for controllers;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;spec&lt;/code&gt; is the config for documentation that will be generated, with
&lt;code&gt;outputDirectory&lt;/code&gt; pointing at where we want to have &lt;code&gt;swagger.json&lt;/code&gt;.
&lt;code&gt;specVersion&lt;/code&gt; defined whether we want OpenAPI standard (3) or Swagger (2). I
highly recommend the former.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Expanding the Controller
&lt;/h3&gt;

&lt;p&gt;As mentioned earlier, TSOA works with controllers. So we need to enhance what we&lt;br&gt;
currently have to make it readable.&lt;/p&gt;

&lt;p&gt;Let’s start with marking the controller as &lt;code&gt;Route&lt;/code&gt;, tag it and make it extend&lt;br&gt;
the &lt;code&gt;Controller&lt;/code&gt; class from TSOA:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./chore/controller.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Controller&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;tsoa&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="nd"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Chore&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ChoreController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;ChoreService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ChoreService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;service&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the top, &lt;code&gt;Route&lt;/code&gt; allows the library to detect that it’s actually a&lt;br&gt;
controller that takes care of traffic. &lt;code&gt;Tags&lt;/code&gt; serves as the name (otherwise it&lt;br&gt;
defaults to &lt;code&gt;"default"&lt;/code&gt;) and &lt;code&gt;Controller&lt;/code&gt; is a thin class giving us few&lt;br&gt;
additional methods, like setting status codes and headers.&lt;/p&gt;

&lt;p&gt;All right, let’s start adding some routes! First, we have &lt;code&gt;getAllChores&lt;/code&gt;, which&lt;br&gt;
is the easiest. Just add &lt;code&gt;Get()&lt;/code&gt; and you’re golden:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./chore/controller.ts&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ChoreController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;getAllChores&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Chore&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllChores&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay, we’ve been doing this for a while, but does it even work? Let’s try!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ tsoa spec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we have a new directory – &lt;code&gt;./docs&lt;/code&gt; – created, with a &lt;code&gt;swagger.json&lt;/code&gt; inside.&lt;br&gt;
Okay, let’s keep the momentum going!&lt;/p&gt;

&lt;p&gt;The most complex is definitely the POST verb, because it requires defining the&lt;br&gt;
body. Let’s try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./chore/controller.ts&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Chore&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ChoreController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;SuccessResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;201&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Created&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="nd"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;createChore&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;chore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BaseChore&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Chore&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createChore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chore&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay, it wasn’t that hard, right? The biggest thing is &lt;code&gt;this.setStatus&lt;/code&gt; method,&lt;br&gt;
coming from the TSOA &lt;code&gt;Controller&lt;/code&gt; class. Without this, we’d get &lt;code&gt;200&lt;/code&gt;, default&lt;br&gt;
success status. It’s not a mistake, but good status codes just nice and makes&lt;br&gt;
the work easier. What’s left are the PUT and DELETE ones, with path params.&lt;br&gt;
Let’s go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./chore/controller.ts&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Chore&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ChoreController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{id}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;updateChore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;chore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ChoreUpdate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Chore&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateChore&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="nx"&gt;chore&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="nd"&gt;Delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{id}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;deleteChore&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;Chore&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteChore&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="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;Important thing is to match the param names, so if we have &lt;code&gt;Put("{id}")&lt;/code&gt;, we&lt;br&gt;
want to retain this &lt;code&gt;id&lt;/code&gt; everywhere in the method.&lt;/p&gt;

&lt;p&gt;Right, so it seems we’re done? Let’s try.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ tsoa spec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we’re golden. Docs are generated, so we can now have certainty that&lt;br&gt;
everything we say in the Swagger matches the reality.&lt;/p&gt;
&lt;h3&gt;
  
  
  Bonus #1: Exposing the Swagger docs
&lt;/h3&gt;

&lt;p&gt;Having docs as the JSON file is the most important, but can we also present it&lt;br&gt;
somehow? Sure we can. Enter Swagger UI! And I am not talking about the&lt;br&gt;
&lt;a href="https://editor.swagger.io/" rel="noopener noreferrer"&gt;Swagger Editor&lt;/a&gt;, but our very own instance!&lt;/p&gt;

&lt;p&gt;First, let’s install the dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ npm i swagger-ui-express&lt;span class="p"&gt;;&lt;/span&gt;
~ npm i &lt;span class="nt"&gt;-D&lt;/span&gt; @types/swagger-ui-express&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we need to enable JSON imports in our TypeScript config:&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;"compilerOptions"&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;"resolveJsonModule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="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;Having this will allow TS to import JSON files just like any other modules.&lt;/p&gt;

&lt;p&gt;Now let’s import the dependencies in our main file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&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;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Swagger&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;swagger-ui-express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;app&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;./app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;swaggerDocument&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;../docs/swagger.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/docs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Swagger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Swagger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;swaggerDocument&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it! Now, after we start out server and access&lt;br&gt;
&lt;a href="http://localhost:3000/docs" rel="noopener noreferrer"&gt;http://localhost:3000/docs&lt;/a&gt;, we should have our&lt;br&gt;
docs ready!&lt;/p&gt;
&lt;h3&gt;
  
  
  Bonus #2: Generated Routing and Validation
&lt;/h3&gt;

&lt;p&gt;But wait, there’s more!&lt;/p&gt;

&lt;p&gt;No, really, there’s a bit more TSOA can do.&lt;/p&gt;

&lt;p&gt;As you can see, there’s no validation to be found, and all the routes are made&lt;br&gt;
by hand. That's a bit of a problem, because we define routes in &lt;code&gt;routes.ts&lt;/code&gt;&lt;br&gt;
file, and then in TSOA annotations in the controller. And all the validation&lt;br&gt;
requires us to jump in and write it manually. These two issues can be solved in&lt;br&gt;
one fell swoop.&lt;/p&gt;

&lt;p&gt;First, let’s go back to the config file and add &lt;code&gt;routes&lt;/code&gt; entry:&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;"entryFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/main.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"controllerPathGlobs"&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="s2"&gt;"./src/**/controller.ts"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"spec"&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;"outputDirectory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"specVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"spec"&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;"servers"&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:3000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Local server"&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;"routes"&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;"routesDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/api"&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;&lt;code&gt;routesDir&lt;/code&gt; defines where the routes should be written. I put it in a general&lt;br&gt;
location, because TSOA will take all controllers and combine them into one file.&lt;br&gt;
Right, so let’s try to generate this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ tsoa routes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All right! We have &lt;code&gt;routes.ts&lt;/code&gt; file created, which… frankly, looks messy. But&lt;br&gt;
all generated code does, so don’t worry. If we dive a bit deeper, there’s&lt;br&gt;
validation added, basing on our routes as well! For example, &lt;code&gt;app.delete&lt;/code&gt; checks&lt;br&gt;
for the &lt;code&gt;id&lt;/code&gt; in path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./src/api/routes.ts&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TsoaRoute&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ParameterSchema&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="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;in&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dataType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;validatedArgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;templateService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getValidatedArgs&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s great, but what if we want to have more strict validation? Like, input&lt;br&gt;
lengths?&lt;/p&gt;

&lt;p&gt;No problem!&lt;/p&gt;

&lt;p&gt;Let’s say we want to make sure that, when we add a chore, &lt;code&gt;name&lt;/code&gt; is at least 3&lt;br&gt;
characters long. To do so, we need to modify our type a bit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./src/chore/types.ts&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;BaseChore&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/**
   * @minLength 3
   */&lt;/span&gt;
  &lt;span class="nl"&gt;name&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="cm"&gt;/**
   * @minLength 3
   */&lt;/span&gt;
  &lt;span class="nl"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, I know these aren't the most appealing, but adding these comments will&lt;br&gt;
allow the generator to create validation clauses. Let’s try!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~ tsoa routes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the routes, we have our models updated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./src/api/routes.ts&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TsoaRoute&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Chore&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dataType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;refObject&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;properties&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dataType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;validators&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;minLength&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}}},&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dataType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;validators&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;minLength&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}}},&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dataType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dataType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;boolean&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;additionalProperties&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great!&lt;/p&gt;

&lt;p&gt;Now all there’s left is to register these routes.&lt;/p&gt;

&lt;p&gt;The generated &lt;code&gt;routes.ts&lt;/code&gt; exposes &lt;code&gt;RegisterRoutes&lt;/code&gt; function, which accepts the&lt;br&gt;
Express app, so it’s just a formality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Express&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;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RegisterRoutes&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;./api/routes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nc"&gt;RegisterRoutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it!&lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;p&gt;We now have a fully working application that generated its documentation and&lt;br&gt;
routes. In the future, I’ll show you how to utilize the Swagger file to generate&lt;br&gt;
a fully typed API client for the frontend.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/tomekbuszewski/openapi-demo" rel="noopener noreferrer"&gt;Code in the repo&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/lukeautry/tsoa/tree/master" rel="noopener noreferrer"&gt;TSOA official repo&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>node</category>
      <category>express</category>
      <category>openapi</category>
      <category>swagger</category>
    </item>
    <item>
      <title>5 Things to do First as a Team Leader</title>
      <dc:creator>Tomasz Buszewski</dc:creator>
      <pubDate>Thu, 01 Aug 2024 09:06:18 +0000</pubDate>
      <link>https://dev.to/tomekbuszewski/5-things-to-do-first-as-a-team-leader-4e2k</link>
      <guid>https://dev.to/tomekbuszewski/5-things-to-do-first-as-a-team-leader-4e2k</guid>
      <description>&lt;p&gt;You've made a team lead, congrats! What now?&lt;/p&gt;

&lt;p&gt;In a perfect world, your manager would have a series of meetings with you to guide you into your new role. But that's not always the case. Most of us are thrown in the deep end and expect to perform. So here's five things I always make sure to do when taking over a team as a lead.&lt;/p&gt;

&lt;p&gt;This post is &lt;a href="https://buszewski.com/writings/2024-07-28-5-things-to-do-first-as-a-team-leader/" rel="noopener noreferrer"&gt;cross-published from my blog&lt;/a&gt;. You can also &lt;a href="https://www.youtube.com/watch?v=6d93v5UUpb0" rel="noopener noreferrer"&gt;view on YouTube&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Meet with your team members
&lt;/h3&gt;

&lt;p&gt;The first you should do is talk to your colleagues. These are the people you will work with on a daily basis. Team makes or breaks the lead, so having good relationships within is crucial.&lt;/p&gt;

&lt;p&gt;Before you start sending invitations to your Zooms and Google Meets though, make sure you know what you want to communicate. Going in without preparations sure gives this "laid back" vibe, but it also can raise questions of whether you actually know why you’re here. &lt;/p&gt;

&lt;p&gt;So, what should you say? Some must-haves are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A good introduction with some background. How did you get here, what experience you have under your belt, what makes you the person for the job? Highlight your strengths and try to lean into your interlocutor’s experience to connect with them;&lt;/li&gt;
&lt;li&gt;Brief vision of how you envision working together. What you would like to introduce? What worked in your previous companies and why?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This meeting should also help you to know your new team members. It’s a good place to ask some questions, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What’s their background, past experiences, hobbies;&lt;/li&gt;
&lt;li&gt;What do they think is missing in the team or in the company;&lt;/li&gt;
&lt;li&gt;What works and what not. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don’t expect five hours conversation though – they will most likely be reserved. Don’t take it against you – it’s completely normal. What’s important is not to push anyone. Some open sooner, some later – but it’s on you to see when they are getting pressured. If you see someone’s getting less comfortable, don’t push any further. Remember, you’re for a long ride together, and pressing people will never work out, it will just alienate everyone.&lt;/p&gt;

&lt;p&gt;Okay, if you know what to say and what to ask, send invitations. I make it 30 minutes (with 15-20 minutes to spare in my calendar, just in case), as there’s no point to keep people for too long. I like to write them a heads-up on Slack, something like “Hey, I’ve sent an invitation for an intro call, nothing fancy, just a chat to know each other”. I found out it takes a bit of the edge and costs virtually nothing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Meet with your stakeholders
&lt;/h3&gt;

&lt;p&gt;The next thing you should do is to meet with the stakeholders. Product owners, marketing and design leads, other team leaders. This shouldn’t be that different from meeting your team, after all this is – again – the intro call. When introducing yourself, try to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Highlight your experiences with working with people in a role similar to theirs (for example, how you improved design/development handover or estimations);&lt;/li&gt;
&lt;li&gt;Offer your support, but underline that you’re still onboarding and most likely will require their help.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also make sure to prepare questions you want to ask, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What are their expectations towards you? &lt;/li&gt;
&lt;li&gt;What are their expectations towards your team?&lt;/li&gt;
&lt;li&gt;What strong sides they see when working with the team so far?&lt;/li&gt;
&lt;li&gt;What weak sides they see?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After having answers to your questions, you will be able to start formulating a game plan for the team. It’s not a job for now, but something you should keep in your mind. &lt;/p&gt;

&lt;h3&gt;
  
  
  Go Through the Codebase
&lt;/h3&gt;

&lt;p&gt;Once you talked with the devs, you’ve most likely heard at least something about the code. But nothing beats going through it alone. Clone the repo and read the docs attached. Note all the observations, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can it be installed easily? Will newcomers have hard time getting it up?&lt;/li&gt;
&lt;li&gt;Does it require any internal knowledge to get it running?&lt;/li&gt;
&lt;li&gt;Does the pipeline looks understandable? Can it be modified by someone who isn’t a senior?&lt;/li&gt;
&lt;li&gt;Which parts are changed often, which are dormant for months or years? &lt;/li&gt;
&lt;li&gt;What are observability options? Which parts of the applications are measured, can you see bottlenecks?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note these findings and address them with your team. There’s nothing wrong in showing that you don’t know everything. It is certainly better than pretending that you do, and make a laughing stock out of yourself. &lt;/p&gt;

&lt;h3&gt;
  
  
  Take a Step Back
&lt;/h3&gt;

&lt;p&gt;You’ve analysed all the things your colleagues and co-workers told you. You made some notes, jotted some ideas for what’s to come. You have an idea of what people like and what they don’t in the team. You know how the team is perceived by the other stakeholders. Great, now what?&lt;/p&gt;

&lt;p&gt;Now, take a step back. Put these things on the back burner for a few days and just be present in the team. Join meetings, listen how the team works together, just feel the pulse of it. Don’t jump into any conclusions, don’t assume anything. Just listen.&lt;/p&gt;

&lt;p&gt;I always try to take at least three days, possibly a week or more, to see how the team really behaves. What people say is very important, but keep in mind that they don’t always perceive things as they are. We are all biased, and you, coming from the outside, have a unique perspective that folks working in the team for months or years lack. During this time, try to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What pain points the team has? Maybe too many or too long meetings? Or too much tasks in the sprint? Too much pressure? Or the other way around – too little to do?&lt;/li&gt;
&lt;li&gt;How is the communication within and outside the team? Are people on the same page? Are things getting agreed on during private conversations and then introduced?&lt;/li&gt;
&lt;li&gt;Who works well with who. Are there are “pairs” that perform well together? How can you utilize this further?&lt;/li&gt;
&lt;li&gt;Who is the natural leader of the pack? Who’s the “go-to” person? Who mentors others? &lt;/li&gt;
&lt;li&gt;Are things reported as problematic during the intro calls happen often? How do they look from the outside?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After having these things out, you will not only know what people think, but also will have your own observations of how the team works. It will help you formulate any and all further steps. But do note that these might change and for sure does not paint the entire picture. Take it with a grain of salt, even if you are certain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start Formulating the Game Plan
&lt;/h3&gt;

&lt;p&gt;Armed with all the knowledge you’ve accumulated throughout last weeks, it’s time to be the leader. One of the most important qualities of a team lead is the ability to play the long game. &lt;/p&gt;

&lt;p&gt;This step is the hardest one, because it requires analyzing all the findings and condense them into actionable items. You most likely find two types of action points:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short-term goals&lt;/strong&gt;, or &lt;strong&gt;low-hanging fruits&lt;/strong&gt;, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minor code problems, like flaky unit tests or pipelines;&lt;/li&gt;
&lt;li&gt;Too long and/or numerous meetings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Things like these can be addressed rather quickly, as they require little actual work. Too many meetings? See which one are the least beneficial or which don’t require every team member. Flaky tests can be at least investigated during one sprint, with a bit of luck, this problem can be taken care of by simply assigning someone on it full-time. &lt;/p&gt;

&lt;p&gt;But there will, most likely, be more complex issues that you will need to spread and plan in time, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lack of stakeholder communication with the team;&lt;/li&gt;
&lt;li&gt;Constant sprint overloading;&lt;/li&gt;
&lt;li&gt;Internal conflicts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Such things require your attention the most. You need to dive deep into this and analyze why they occur. For example, lack of stakeholder communication may be caused by chaos in the management, or by ignoring engineers and treating them as tools. It’s your job to build conscious recognition of your team. If sprints are overplanned, that’s an issue with either management, or the team, or both. Who forces these tasks into sprint? Why the team doesn’t fight back, and if they had, why it didn’t work? Are there conflicts? People don’t have to like each other, but they should at least stay professional to be able to work together. Not everybody is capable of that though, and it’s your job to make sure this conflict doesn’t spill on the entire team.&lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;p&gt;Doing these five steps should not only give you ideas of what the team really looks and works like, but also how the company works with the team. From there on out, you should formulate both short- and long-term plans to mitigate the issues and embolden the strengths. &lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

</description>
      <category>management</category>
      <category>leadership</category>
      <category>teamculture</category>
      <category>career</category>
    </item>
    <item>
      <title>Welcome, New Member *sigh*</title>
      <dc:creator>Tomasz Buszewski</dc:creator>
      <pubDate>Fri, 27 Mar 2020 08:07:41 +0000</pubDate>
      <link>https://dev.to/tomekbuszewski/welcome-new-member-sigh-jl8</link>
      <guid>https://dev.to/tomekbuszewski/welcome-new-member-sigh-jl8</guid>
      <description>&lt;p&gt;Taken from my blog: &lt;a href="https://www.buszewski.com/writings/2020-03-27-welcome-new-member/" rel="noopener noreferrer"&gt;https://www.buszewski.com/writings/2020-03-27-welcome-new-member/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In IT, it is very common to have new team members. And yet, welcoming them is hardly something we’re good at.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before then even come
&lt;/h2&gt;

&lt;p&gt;There is a checklist I like to have &lt;em&gt;before&lt;/em&gt; the new person will come. Simple points that make sure they feel good.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;make sure their desk and chair is there and is clean (yes, I have cleaned a desk for someone, nothing wrong with it);&lt;/li&gt;
&lt;li&gt;make sure their hardware is there, is working and set up properly;&lt;/li&gt;
&lt;li&gt;make sure your team mates know that they are coming;&lt;/li&gt;
&lt;li&gt;make sure all the accounts and accesses are granted (if this is impossible due to some restrictions, make them know beforehand);&lt;/li&gt;
&lt;li&gt;make sure the access card is ready (this is important, it’s like you’re having a new family member but „you don’t get the keys yet”);&lt;/li&gt;
&lt;li&gt;designate a buddy (more on that later);&lt;/li&gt;
&lt;li&gt;prepare an issue (also, more on that later).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When I know that someone will come, let’s say, on Monday, I make sure to have this day clean of all meetings that are unnecessary. &lt;/p&gt;

&lt;h2&gt;
  
  
  Do a tour, thorough one
&lt;/h2&gt;

&lt;p&gt;New environment is always stressful. For almost everyone. So make sure you make a tour across the office. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don’t run across the entire floor asking to shake hands&lt;/strong&gt;. Come on, how many pairs of name/face can you store in your head in one minute? &lt;strong&gt;Try doing it in batches&lt;/strong&gt;, first meet the closest team mates, then spin away with other departments. Maybe even split this into more days, 30 minutes each, if your company is big.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don’t show kitchen, toilets etc. when returning from somewhere&lt;/strong&gt;. &lt;strong&gt;Go from your room&lt;/strong&gt;, it will be easier to memorize the route this way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Show where are cups and mugs are&lt;/strong&gt; and how to use coffee machine. This is also a good moment to take a breather and drink something and have some small-talk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Show where are office supplies&lt;/strong&gt;. Something as trivial as getting a pen without the necessity to ask people about it will really boost your new team mate adoption.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don’t let them go alone
&lt;/h2&gt;

&lt;p&gt;Sitting people in front of their desks and walking away on the first day is the worst thing you can do. I got this treatment more than once, „here’s your seat and desk, settle in” and he walks away. What the fuck I am supposed to do? Where is… anything?&lt;/p&gt;

&lt;p&gt;Instead, sit with them. Ask, do they need some time to set up their computer, or would they like you to tell them, what they’ll be needing.&lt;/p&gt;

&lt;p&gt;If they’ll say they need some time alone, no problem, but don’t forget about them. Be back in an hour or two, just see how it’s going. Don’t hover, don’t be a helicopter. Just pop in, „you okay there, need anything” and that’s it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spend time with them
&lt;/h2&gt;

&lt;p&gt;After the workstation is set up, there is time to set up the actual project. &lt;strong&gt;Don’t send the wiki link and be off&lt;/strong&gt;. Such documents are often&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;outdated;&lt;/li&gt;
&lt;li&gt;too long;&lt;/li&gt;
&lt;li&gt;too technical;&lt;/li&gt;
&lt;li&gt;assuming that whoever reads them have some domain knowledge.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is something I call a &lt;strong&gt;dick move&lt;/strong&gt;. &lt;em&gt;But what if I don’t remember the process&lt;/em&gt;, you may ask. Well, that’s okay, open that goddamn Confluence and go through it &lt;strong&gt;together&lt;/strong&gt;. Or even better, get someone who might know, and work together. This will also help the new one meet other members. Just make sure you don’t call in someone who’s harsh.&lt;/p&gt;

&lt;p&gt;After that, make sure that someone will sit next to that person. Maybe you, maybe someone you designate to do this. &lt;strong&gt;Make sure this is a knowledgeable, communicative person&lt;/strong&gt;. No point in sitting a guy with headphones from 9 to 5. This is often called a &lt;strong&gt;buddy system&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to prep a buddy
&lt;/h3&gt;

&lt;p&gt;Asking „who want’s to be a buddy for Anon here” is a bad move. There won’t be „me, me!” people yelling. There will be silence, and someone with a sense of responsibility will come forward only to regret it afterwards.&lt;/p&gt;

&lt;p&gt;Instead, pick someone you know in your team &lt;strong&gt;early&lt;/strong&gt;. This doesn’t have to be the best developer. It has to be the most communicative, friendly person. A few days before the new person arrives, get that someone on a one-on-one and ask, „could you be a buddy for Anon?” If you are a good lead, they won’t be afraid to say „no”, if they can justify it. If they’ll refuse, try the next person. Don’t push it. Forcing people into such interactions never goes well.&lt;/p&gt;

&lt;p&gt;But let’s assume they are fine with it. So, what does a buddy do? Buddy simply is there for this person. Buddy is a go-to, when something breaks, something is not clear, something needs clarification. &lt;/p&gt;

&lt;p&gt;And, once again, &lt;strong&gt;you can be that buddy&lt;/strong&gt;, if you decide so.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don’t let their questions go unanswered (or answered vaguely)
&lt;/h2&gt;

&lt;p&gt;New people in the organization will have questions. They can be like a kid, asking all the time. &lt;strong&gt;And this is totally fine&lt;/strong&gt;. It’s a sign they really are interested in this place. Make sure you answer them, and answer thoroughly. Sure, there’s no need to  dive deep in the technical aspects on the first day, because they’ll won’t digest it all. But don’t answer with „we’ll get to that later” or „you don’t need this right now”. Even if they really don’t need it, there’s no harm in telling it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get them to lunch
&lt;/h2&gt;

&lt;p&gt;„Hey, what time do you eat?” is a great question to ask during the day. „You want to grab something?” On the first day, there is so much going on, people may either forget, or be too shy to walk away from their station for lunch. Make sure that this is not the case. You can go together or in larger group, but make sure you don’t scare the new person. You can feel if this is someone comfortable with a crowd or not. Don’t try to „break their comfort zone”, you’re not a dickheaded coach. &lt;/p&gt;

&lt;h2&gt;
  
  
  Treat them as part of the team from day one
&lt;/h2&gt;

&lt;p&gt;Great things may happen, if you treat new people like the old ones. Like they have always been here. Let’s say you team goes for lunch every day at the same time. Take them with you. You have a problem with your code, ask them, maybe they’ll help. Even if not, they will feel validated and needed. Look for such opportunities. Even the slightest gesture may prove beneficial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try having day-one commit
&lt;/h2&gt;

&lt;p&gt;Nothing says „we need you, mate” more than allowing them to work right off the bat. After they set up, have coffee and lunch, give them a small task. Nothing fancy, nothing groundbreaking, just something small to stretch their legs. A small „atom” component, or a tiny test that was missing for a long time.&lt;/p&gt;

&lt;p&gt;A lot of people will get something serious to do weeks after the first day. And this is horrible, both business-wise and company-wise. The former – you are paying this person. The latter – you will look like lazy slobs. &lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;p&gt;Caring for new people on board is often neglected. This is wrong and causes detachment. If you don’t care for me, why should I care for you, Company Name?&lt;/p&gt;

</description>
      <category>hr</category>
      <category>leadership</category>
      <category>career</category>
    </item>
    <item>
      <title>Checkboxes and radios – proper form design</title>
      <dc:creator>Tomasz Buszewski</dc:creator>
      <pubDate>Wed, 18 Mar 2020 17:15:20 +0000</pubDate>
      <link>https://dev.to/tomekbuszewski/checkboxes-and-radios-proper-form-design-15e7</link>
      <guid>https://dev.to/tomekbuszewski/checkboxes-and-radios-proper-form-design-15e7</guid>
      <description>&lt;p&gt;Crosspost from my blog: &lt;a href="https://www.buszewski.com/writings/2020-03-18-proper-form-design-checkboxes-and-radios/" rel="noopener noreferrer"&gt;https://www.buszewski.com/writings/2020-03-18-proper-form-design-checkboxes-and-radios/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When building a form – and expecting a user to fill it – the most important thing is ease of use and recognizability. &lt;/p&gt;

&lt;p&gt;Some time ago, in mid 2000s, Internet Explorer 6 and 7 were serious players. And I mean serious, every product had to be compatible with those guys. The Microsoft boys were really hustlin’, and every front-end developer knew that. &lt;/p&gt;

&lt;p&gt;There was this one thing no &lt;code&gt;/9&lt;/code&gt; or &lt;code&gt;!important&lt;/code&gt; couldn’t fix. It was the &lt;code&gt;input[radio]&lt;/code&gt; and &lt;code&gt;input[checkbox]&lt;/code&gt; fields. Styling those was practically impossible, as they never allowed any tinkering in properties other than border. &lt;/p&gt;

&lt;p&gt;Of course, aesthetic-hungry &lt;em&gt;webmasters&lt;/em&gt; developed a lot of JavaScript (most of the time in a form of jQuery plugin) that allowed to style the input however we wanted. But there were tradeoffs. Hard, often limited, development. Lack of accessibility. Requiring JavaScript (and back then, it wasn’t so obvious.) So the forms remained mostly untouched, and it was good.&lt;/p&gt;

&lt;p&gt;And then, standardization came. Internet Explorer lost its significance. Suddenly, styling &lt;code&gt;input[radio]&lt;/code&gt; wasn’t that impossible. We all used the &lt;em&gt;&lt;code&gt;:before&lt;/code&gt; trick&lt;/em&gt;. It allowed us to do something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TC_44z2O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.buszewski.com/static/474e91e536eca46f57a0bd38efe7a372/692d4/form-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TC_44z2O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.buszewski.com/static/474e91e536eca46f57a0bd38efe7a372/692d4/form-1.png" alt="Properly styled form" width="398" height="125"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not fancy enough? So, why don’t we break it?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--obSVD59R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.buszewski.com/static/1684bb2ea4aa4805bdb930c4e18aa7f0/692d4/form-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--obSVD59R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.buszewski.com/static/1684bb2ea4aa4805bdb930c4e18aa7f0/692d4/form-2.png" alt="Not properly styled form" width="398" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(&lt;a href="https://codepen.io/tomekbuszewski/pen/ExjRRjP?editors=0110" rel="noopener noreferrer"&gt;See it live&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;You see where I am going with this overlong exposure?&lt;/p&gt;

&lt;p&gt;Such examples were very common back then. Round checkboxes and square radios. But I thought this was all left in the past, where poor interfaces prevailed.&lt;/p&gt;

&lt;p&gt;But they are still here.&lt;/p&gt;

&lt;p&gt;I got the munchies recently and decided to order a pizza via Internet. There is one I particularly like, it allows picking own ingredients. So I basically make the „Greek” pizza I ate when I was a kid. Form, more or less, looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KgXs-oF6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.buszewski.com/static/0e2413865386e796dd14dfbbd76654ea/01267/form-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KgXs-oF6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.buszewski.com/static/0e2413865386e796dd14dfbbd76654ea/01267/form-3.png" alt="Single column selection of ingredients" width="713" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See the problem? If yes, congratulations, if no, let me play in Sketch some more:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T9nHn6qr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.buszewski.com/static/76b79cae87e4ce10a2e52fe9bb9287f5/f7616/form-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T9nHn6qr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.buszewski.com/static/76b79cae87e4ce10a2e52fe9bb9287f5/f7616/form-4.png" alt="Multi-column selection of ingredients" width="766" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you see? All of this items look like &lt;code&gt;radio&lt;/code&gt; buttons, while in reality, those are &lt;code&gt;checkbox&lt;/code&gt; types.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UF-oNoM9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media1.tenor.com/images/f750bb9b61798f26049906e81aee7752/tenor.gif%3Fitemid%3D4371282" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UF-oNoM9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media1.tenor.com/images/f750bb9b61798f26049906e81aee7752/tenor.gif%3Fitemid%3D4371282" alt="Homer seeing this crap" width="430" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is not a &lt;em&gt;design&lt;/em&gt; choice. No, design is making it more appealing while keeping the usability intact. This is a mistake. Done perhaps by someone with less experience in the field, but nevertheless, a mistake. Know better. Don’t commit such mistakes.&lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;p&gt;Rounded &lt;code&gt;input[radio]&lt;/code&gt; and square &lt;code&gt;input[checkbox]&lt;/code&gt; is something all users know for a long time. Those were the first „tick” fields we saw, probably somewhere in Windows settings panel. They were there, when first web pages that allowed actually doing something other than reading, hit the ‚net. And now they are here, and please, make them stay.&lt;/p&gt;

</description>
      <category>ux</category>
      <category>design</category>
    </item>
    <item>
      <title>Lessons learnt from new buszewski.com</title>
      <dc:creator>Tomasz Buszewski</dc:creator>
      <pubDate>Fri, 13 Mar 2020 15:40:42 +0000</pubDate>
      <link>https://dev.to/tomekbuszewski/lessons-learnt-from-new-buszewski-com-1pg4</link>
      <guid>https://dev.to/tomekbuszewski/lessons-learnt-from-new-buszewski-com-1pg4</guid>
      <description>&lt;p&gt;Originally from my blog: &lt;a href="https://www.buszewski.com/writings/2020-03-13-lessons-learnt-from-new-buszewski.com/" rel="noopener noreferrer"&gt;https://www.buszewski.com/writings/2020-03-13-lessons-learnt-from-new-buszewski.com/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I’ve been building my new portfolio for four years, with different designs and technology stacks. And I’ve learnt quite a few things from it.&lt;/p&gt;

&lt;p&gt;For starters, I’ll say that this iteration stands on Gatsby (so, React) and Styled Components, written in TypeScript. Data is sourced from local files in Markdown.&lt;/p&gt;

&lt;p&gt;Before I’ll tell you, what did I learn, I will tell you, why did I choose to do things this way.&lt;/p&gt;

&lt;p&gt;I’ve been fan of &lt;strong&gt;React&lt;/strong&gt; for quite some time. More than four years, in current front-end world this seems like forever. I’ve started experimenting in 2015, using in 2016 and this is my go-to framework for UI ever since.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gatsby&lt;/strong&gt; was a natural choice for a React fan, so I didn’t even spent much time on alternatives. Perhaps I should. But since it had all that I like, including GraphQL and Markdown sourcing almost out of the box, I was bought.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Styled Components&lt;/strong&gt;. The standard for styling next-gen web app, isn’t it? All the CSS-in-JS glory, ease of props handling, editor support. Everything is here.&lt;/p&gt;

&lt;p&gt;And &lt;strong&gt;TypeScript&lt;/strong&gt;. Actual standard for any serious JavaScript development, plus it really saved my ass more than couple of times in the past. It was a no-brainer.&lt;/p&gt;

&lt;p&gt;So, why am I not fully satisfied?&lt;/p&gt;

&lt;p&gt;Because it’s overengineered. Holy fuck, &lt;strong&gt;it is so overengineered&lt;/strong&gt;, I am angry at myself for doing such a rookie mistake.&lt;/p&gt;

&lt;p&gt;Let’s start from the beginning. I wanted to build views from components, so naturally, I’ve created a design system (with atomic design methodology) in Storybook.&lt;/p&gt;

&lt;p&gt;Now, Storybook is really a great tool. And using it does help to have isolated components. But it also requires writing stories for every piece of code. Let’s take a look at a very simple &lt;code&gt;blockquote&lt;/code&gt; element.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For reminder, it looks like this&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First, code:&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="cm"&gt;/**
 * @author tomek
 * @since 2020-02-26 10:27:24
 */&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StyledComponentBase&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;styled-components&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;theme&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;@ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ColorContext&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;@ui/Atoms/Section/Section&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Paragraph&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;@ui/Atoms&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;BlockquoteType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;
  &lt;span class="nx"&gt;StyledComponentBase&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blockquote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nx"&gt;never&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;Blockquote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BlockquoteType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blockquote&lt;/span&gt;&lt;span class="s2"&gt;`
  opacity: 0.65;
  margin-bottom: 3rem;
  margin-left: 1rem;
  padding: 0 1rem;
  border-left: 1rem solid
    &lt;/span&gt;&lt;span class="p"&gt;${()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`var(--section-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ColorContext&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;-highlight)`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;

  &amp;amp; &amp;gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Paragraph&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:first-of-type {
    font-size: 2rem;
  }

  &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;breakpoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;desktop&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; {
    grid-column-start: 3;
    grid-column-end: 7;
    margin-left: 1.5rem;
  }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Blockquote&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And story:&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@storybook/addon-knobs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;storiesOf&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;@storybook/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Blockquote&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;./&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;storiesOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Atoms/Blockquote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Normal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Blockquote&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Example text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Blockquote&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While I know, this is super short, please note that this is basically &lt;strong&gt;styling an element&lt;/strong&gt; in React and Styled Components way. Everything is a component, right? Looks kinda tedious, doing this for, like, ten elements? Or more? Yeah, it is tedious and in a long way, boring. &lt;/p&gt;

&lt;p&gt;Don’t get me wrong, while building a big, really big application, like we did in 4Finance or Batmaid, this totally makes sense. But here? It’s way overblown. Unfortunately, it came to me a bit too late, so there was no point of going back. &lt;/p&gt;

&lt;p&gt;Next thing that really slowed me down was, in fact, TypeScript. Why? Because everything has to be typed.&lt;/p&gt;

&lt;p&gt;For those who are familiar with GraphQL, the problem may be well known. If you want to use queries as data source, you have to write the entire interface for it. It may look like this:&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;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IBlogEntry&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;title&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;pubdate&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;slugPubdate&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;summary&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;slug&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;featuredImage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;any&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IBlogNode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;entry&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IBlogEntry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="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;As you can see, I’ve succumbed and used &lt;code&gt;any&lt;/code&gt;. It wasn’t like this from the beginning, I actually had it typed, but as I changed the goddamn &lt;code&gt;featuredImage&lt;/code&gt; query, I had to keep track in the interface. And it was so fucking tiresome, one evening I decided to just &lt;code&gt;any&lt;/code&gt; it and be done.&lt;/p&gt;

&lt;p&gt;Again, having typed such things is great. When you use it more than once. Here, it was just more work that wasn’t beneficial at all. Perhaps there is a magical tool that creates interfaces from GraphQL schema (if you know it, tell me, &lt;strong&gt;please&lt;/strong&gt;). But for now, it’ll be like that, until I’ll have the time and willpower to change it. (So, like, never).&lt;/p&gt;

&lt;p&gt;Last, but not least, is Gatsby. I know you can clone a starter and roll with it within seconds. Yes, but as I like to have control over what I do, I prefer to actually build the stack. So, &lt;code&gt;gatsby new spastic&lt;/code&gt; (yes, I named it after a &lt;a href="https://en.wikipedia.org/wiki/Go_Plastic" rel="noopener noreferrer"&gt;Squarepusher song&lt;/a&gt;) and then, well, plugins. I want TypeScript – plugin. I want Styled Components – plugin. I want PrismJS – plugin. I need to catch inner links – plugin. Google fonts – plugin. There is plugin for everything. Why this is bad? Because sometimes it would be easier just to do it manually. But, given how fragile can Gatsby be, it’s safer to stick to community-developed addons. Especially, when there is tempering with Webpack involved.&lt;/p&gt;

&lt;p&gt;There is one extra thing that I’ve decided not to do at the beginning. Tests. Yes, the guy that talks about testing, coverage and TDD all the time didn’t do tests. Why? It is very simple – there is nothing to test, really. There is no logic in here, apart from a couple of &lt;code&gt;if&lt;/code&gt; statements. Only actual tests that could be used here are E2E or visual regressions, but, again, given the size of this project, I chose to discard them.&lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;p&gt;Given all these, there was actually one thing that spawned the entire complain. File sizes. I know that current front-end is resource-heavy. But, for crying out loud, I’ve used only couple of additional plugins, namely Styled Components and React Markdown. And it’s goddamn gigantic. In total, it pulls over 350 KB of just JavaScript.&lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;p&gt;So, all that being said, what this actually fun? Yes, yes it was. After I configured everything, set up Storybook alongside TypeScript and Gatsby, added a plugin to resolve paths and spent a lot of time on configuration, it was really nice to work on this project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I would do differently&lt;/strong&gt;? I would use a different framework for this, maybe Jekyll or Hugo. I would refrain from using React and Styled Components in favor of pure JavaScript (or VUE) with SCSS. Turning off the entire JS doesn’t really trip the page of anything. Header doesn’t hide, and links not SPA-like, without a nice animation. But apart from it? Works normally. &lt;/p&gt;

&lt;p&gt;Perhaps, when I’ll be really bored, I will rewrite this using a simpler stack.&lt;/p&gt;

</description>
      <category>gatsby</category>
      <category>react</category>
    </item>
    <item>
      <title>A note on naming colors</title>
      <dc:creator>Tomasz Buszewski</dc:creator>
      <pubDate>Thu, 05 Mar 2020 13:28:25 +0000</pubDate>
      <link>https://dev.to/tomekbuszewski/a-note-on-naming-colors-113j</link>
      <guid>https://dev.to/tomekbuszewski/a-note-on-naming-colors-113j</guid>
      <description>&lt;p&gt;Posted earlier on &lt;a href="https://www.buszewski.com/writings/2020-02-27-a-note-on-naming-colors/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Remember that text saying "in IT, naming thing is hard"? This is even harder when it comes to colors.&lt;/p&gt;

&lt;p&gt;Most of the time, a color is already named. Red. Blue. &lt;a href="http://www.colors.commutercreative.com/rebeccapurple/" rel="noopener noreferrer"&gt;Rebecca Purple&lt;/a&gt;. But those names bare no context. Anything can be &lt;em&gt;blue&lt;/em&gt;. So, what to do, when we want to know, what we are dealing with?&lt;/p&gt;

&lt;h2&gt;
  
  
  Even more abstraction
&lt;/h2&gt;

&lt;p&gt;One thing that I've used is to generate color names at random. With &lt;a href="http://chir.ag/projects/name-that-color/#6195ED" rel="noopener noreferrer"&gt;Name That Color&lt;/a&gt;, I was able to tell the difference between one &lt;a href="https://www.colourlovers.com/color/74E5EF/Flowering_Flow" rel="noopener noreferrer"&gt;shade of teal&lt;/a&gt; from &lt;a href="https://www.colourlovers.com/color/24C7C0/buy_tramadol_online" rel="noopener noreferrer"&gt;the other&lt;/a&gt;. Even though they are visually different, in the code they are just different strings. Take a look at this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--color-spray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#74E5EF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--color-java&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#24C7C0&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;Seems pretty obvious and easy. Or does it?&lt;/p&gt;

&lt;p&gt;Try to wait a bit. &lt;a href="https://dev.to/writings/2020-02-10-dont-forget-to-forget-your-code"&gt;Forget some stuff&lt;/a&gt;. And suddenly, &lt;em&gt;what is that "java" color?&lt;/em&gt; pops in your head.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use contextual names
&lt;/h2&gt;

&lt;p&gt;When you are getting your colors, they are for &lt;em&gt;something&lt;/em&gt;. This is for the header text. That's for links. And that one's for the background. Why not name them as such?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--color-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fafafa&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--color-text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#222&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--color-links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffaa&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;This is the most readable thing you can do when naming colors. That way you won't have to care whether this color is "red" or "blue". It will be "background". &lt;/p&gt;

&lt;p&gt;Seems obvious, but much too often I found people reinventing the wheel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus: theming
&lt;/h3&gt;

&lt;p&gt;During the design phase, colors are carefully picked. But sometimes a need arises. &lt;em&gt;Let's have a dark mode!&lt;/em&gt; Or &lt;em&gt;let's have a colorblind mode!&lt;/em&gt; Using contextual names allowed to define themes with ease:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--color-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fafafa&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--color-text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#222&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--color-links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffaa&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-color-scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--color-bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--color-text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#666&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--color-links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fcfcfc&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;There you have it. Simply overwriting values basing on some external factors is very simple using such notation.&lt;/p&gt;




&lt;p&gt;Naming things is hard. But using meaningful names will always be the way to go.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Don’t forget to forget your code</title>
      <dc:creator>Tomasz Buszewski</dc:creator>
      <pubDate>Mon, 10 Feb 2020 21:23:14 +0000</pubDate>
      <link>https://dev.to/tomekbuszewski/don-t-forget-to-forget-your-code-3ldo</link>
      <guid>https://dev.to/tomekbuszewski/don-t-forget-to-forget-your-code-3ldo</guid>
      <description>&lt;p&gt;How often do you find yourself coming back to the code you’ve written a few months ago?&lt;/p&gt;

&lt;p&gt;I am a very forgetful person. I remember the basics, like David Bowie’s discography, &lt;em&gt;At Seventeen&lt;/em&gt; lyrics and my wife’s phone number…-ish. But apart from that – nothing. Forgetfulness is my second nature and, even though I struggled at first, I have accepted and embraced it.&lt;/p&gt;

&lt;p&gt;Forgetting to buy flour is one thing. Forgetting why did I write this particular code is something completely different. And while groceries have lists, I couldn’t find anything similar for my work. Until I had an epiphany.&lt;/p&gt;

&lt;p&gt;Back at 2016, I was working on &lt;a href="https://parkiet.com" rel="noopener noreferrer"&gt;parkiet.com&lt;/a&gt;. As a senior developer, I have written hundreds of lines of code for the project. Some more important than others, but all required for &lt;em&gt;something&lt;/em&gt;. And that &lt;em&gt;something&lt;/em&gt; had escaped me more than I’d like to remember (which I don’t, duh).&lt;/p&gt;

&lt;p&gt;I knew that something has to be done. But what?&lt;/p&gt;

&lt;h2&gt;
  
  
  Write documentation?
&lt;/h2&gt;

&lt;p&gt;Great idea. And I wrote long paragraphs of JSDoc, quite often longer that it required. But problem with this was very evident – I really had to write additional lines, which were a) expensive, and b) boring. Plus, if I didn’t do this right after (or even before) writing the actual body of function, I might have had a problem of recollecting all the caveats such code had.&lt;/p&gt;

&lt;p&gt;After couple of tried, I’ve decided to strip the docs from all the descriptions that were either vague or simply unnecessary. Basically, only type notes left.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write thoughtful documentation!
&lt;/h2&gt;

&lt;p&gt;I never like the expression „my code is my documentation”. No, your code is &lt;em&gt;your code&lt;/em&gt;, your documentation is &lt;em&gt;your documentation&lt;/em&gt;. With languages that lacks real types (in that example, JavaScript), thinking that something that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;acp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&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;acp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;acp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;r&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will document itself is just reckless. So, how to turn this code into something more decent? A simple JSDoc would help:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Function that sums current entities or increases the counter by 1;
 *
 * @param {Object} acp - object holding incoming value data;
 * @param {number} [acp.size] - value of current entity;
 * @param {r} r - current value
 * @returns {number}
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;acp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&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;acp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;acp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;r&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding these comments is making this code looks cleaner – even though I didn’t change a single line!&lt;/p&gt;

&lt;p&gt;What’s also cool, JSDoc can be then extracted into a static documentation! And may look, for example, &lt;a href="https://softwarebrothers.github.io/admin-bro-dev/Column.html" rel="noopener noreferrer"&gt;like this&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write tests
&lt;/h2&gt;

&lt;p&gt;Importance of writing tests is something I can’t stress enough. But, apart from the evident gain, it also helps to understand the code we are writing. &lt;/p&gt;

&lt;p&gt;Let me take that simple function I have written before (&lt;code&gt;counter&lt;/code&gt;) and test it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Counter tests&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should sum the values from entites with current one&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should increase the current value by 1 if no apc is given&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;counter&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="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These two simple tests are basically giving all the functionality away. And it’s super-simple to understand, thanks to great syntax provided by Jest (and by a lot of other test tools). In general, testing frameworks aim to make writing tests easy (that’s why they stay on the market) and tests themselves readable. A good test will always be easy to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use typed language
&lt;/h2&gt;

&lt;p&gt;I remember being very anti TypeScript or Flow. I thought that they only make me write more code to have the same result. And this actually is true – these „types” are being removed upon transpilation, so they do not pose any additional value to the client. &lt;/p&gt;

&lt;p&gt;But! They pose a huge addition to the developers! While properly used JSDoc can solve a lot of problems, TypeScript and Flow have the advantage of editors support. Let me write &lt;code&gt;counter&lt;/code&gt; function in TypeScript, really quick:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IEntityConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;size&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;acp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IEntityConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;r&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="kr"&gt;number&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;acp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;acp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;r&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not much have changed, but it seems clearer. Now I know, what may come inside &lt;code&gt;acp&lt;/code&gt;, what &lt;code&gt;r&lt;/code&gt; is and what the function will return. Of course, this simple example doesn’t show a lot, but it is still illustrational.&lt;/p&gt;

&lt;h2&gt;
  
  
  Name your code properly
&lt;/h2&gt;

&lt;p&gt;I’ve wanted to make this the last point. Because this is the most important thing. Naming functions and variables is hard, but it pays. Watch me change that crappy &lt;code&gt;counter&lt;/code&gt; into a proper piece of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;increaseEntitiesCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&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;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;currentState&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;currentSize&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See? No TypeScript, no JSDoc, no tests even. And yet, this is readable and clear.&lt;/p&gt;

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

&lt;p&gt;Remembering is hard. That’s why I prefer to make things so obvious, I don’t have to &lt;em&gt;remember&lt;/em&gt; what they do or what they even are. I will know this, when I read what I’ve written.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>What is Redux, really? – Part 3</title>
      <dc:creator>Tomasz Buszewski</dc:creator>
      <pubDate>Tue, 14 Jan 2020 10:12:46 +0000</pubDate>
      <link>https://dev.to/tomekbuszewski/what-is-redux-really-part-3-3ijb</link>
      <guid>https://dev.to/tomekbuszewski/what-is-redux-really-part-3-3ijb</guid>
      <description>&lt;p&gt;Last time I've talked about Redux as a state manager. Now I want to talk about Redux as the state manager in a React application.&lt;/p&gt;

&lt;h2&gt;
  
  
  A need for state management in React applications
&lt;/h2&gt;

&lt;p&gt;More often than not, Redux is being coupled with React, as it makes it feel more like a working application rather than just a collection of linked views. There is a trend of abstracting every possible action away from React's own state to Redux's store. But this is rarely a good decision, as this data is stored away and rarely accessed by more than one component. &lt;/p&gt;

&lt;p&gt;Moving state up, making it accessible to more elements should be a decision made on an actual need rather than anything else. For example, if your application renders comments, what is the point in storing these anywhere else than in the context of their parent post?&lt;/p&gt;

&lt;p&gt;But, sooner or later, it all comes to a point where it actually makes sense to abstract the state and make it global. &lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting Redux to React
&lt;/h2&gt;

&lt;p&gt;Redux itself is framework-agnostic. It means that it can be used with whatever other tooling there is. In the last article, I made a vanilla JS Redux implementation and it works just fine.&lt;/p&gt;

&lt;p&gt;For React, there is a special binding called &lt;code&gt;react-redux&lt;/code&gt; that provides useful functions to wrap existing components with Redux.&lt;/p&gt;

&lt;p&gt;What is important to note here, is that even though this is a specific binding for a specific framework, implementation of Redux itself remains the same across all platforms. For this examples, I am using the code I've created the last time.&lt;/p&gt;

&lt;p&gt;First thing is, to wrap the app with &lt;code&gt;Provider&lt;/code&gt; component. It will make that all of its children will be able to access the store. It is as simple as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&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="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ProductList&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Provider&lt;/span&gt;&lt;span class="err"&gt;&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;Now every component that resides inside &lt;code&gt;ProductList&lt;/code&gt; can subscribe itself to Redux store.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting components
&lt;/h2&gt;

&lt;p&gt;This is slightly more complex, as Redux leaves a lot of decisions up to the developer.&lt;/p&gt;

&lt;p&gt;Every component can do two things – read state and dispatch actions. Not everyone has to do both, though.&lt;/p&gt;

&lt;p&gt;Passing data from Redux to the React components is done by a higher-order component called &lt;code&gt;connect&lt;/code&gt;. It decorates our instance with what we need.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Higher-order components (or HOCs) are functions that return a new component enhanced with some logic or data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's assume that we need to pass the state of one of reducer – &lt;code&gt;orders&lt;/code&gt;. To do this, we'll use a mapper function. It will accept an argument – our store – and return &lt;strong&gt;an object&lt;/strong&gt; consisting of what we want.&lt;/p&gt;

&lt;p&gt;A state mapper function – commonly known as &lt;code&gt;mapStateToProps&lt;/code&gt; or simply &lt;code&gt;mapState&lt;/code&gt; – is the first parameter of &lt;code&gt;connect&lt;/code&gt;. It accepts two parameters, with mandatory &lt;code&gt;state&lt;/code&gt; and optional &lt;code&gt;ownProps&lt;/code&gt;. I will omit the latter for brevity. Please note that those parameters will be injected automatically, there is no need to do this manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mapState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&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="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;getOrders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Selectors
&lt;/h3&gt;

&lt;p&gt;You can see here the &lt;code&gt;getOrders&lt;/code&gt; function. This is a &lt;strong&gt;selector&lt;/strong&gt;. It is creating a facade to access the store without forcing the developers to know the details of implementation. This way, you can change the store and only replace the business logic without affecting the usage in components.&lt;/p&gt;

&lt;p&gt;A simple selector can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getOrders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All it does is simply exposing (parts of) our state to the consumer. It can have more logic, filter or sort things. For example, we could have a selector called &lt;code&gt;getShippedOrders&lt;/code&gt; which would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getShippedOrders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SHIPPED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Accessing passed properties
&lt;/h3&gt;

&lt;p&gt;As I've said before, &lt;code&gt;connect&lt;/code&gt; is a higher-order component. Which means, it has to accept our base component and then enhance it. To do it, we simply create a new variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProductListComponent&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hello&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProductList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mapState&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;ProductListComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can use it in a regular view, just like a normal component.&lt;/p&gt;

&lt;p&gt;But, how to access these new properties that we've injected? Well, those are exposed as props! All we have to do is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProductListComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// items: [{...}, {...}]&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hello&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProductList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mapState&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;ProductListComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This data can be used within our view or passed down. A simple view utilizing this can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProductListContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;List&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListItem&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&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="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ListItem&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/List&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dispatching actions
&lt;/h3&gt;

&lt;p&gt;Great, so now we have some data retrieved from the Redux store. But, as I said previously, state management is not only reading, but also writing. In order to write to state, an action has to be dispatched.&lt;/p&gt;

&lt;p&gt;Dispatching is handled in a similar fashion to reading. &lt;code&gt;connect&lt;/code&gt; accepts second parameter – an object commonly known as &lt;code&gt;mapDispatchToProps&lt;/code&gt; or &lt;code&gt;mapDispatch&lt;/code&gt;. It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mapDispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;ship&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;setShipped&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;This is the simplest example, simply assigning a function to a key in object. Now our connected component, &lt;code&gt;ProductList&lt;/code&gt;, looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProductList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mapState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mapDispatch&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;ProductListComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now function &lt;code&gt;ship&lt;/code&gt; is passed as a prop and can be executed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProductListContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;List&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListItem&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&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="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ship&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;Ship&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ListItem&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/List&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;As you can see, Redux blends very good in a React application, as it strongly leverages composition.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://codesandbox.io/s/redux-pt3-9jiuf" rel="noopener noreferrer"&gt;Code sample on CodeSandbox&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>redux</category>
      <category>javascript</category>
    </item>
    <item>
      <title>What is Redux, really? – Part 2</title>
      <dc:creator>Tomasz Buszewski</dc:creator>
      <pubDate>Sun, 01 Dec 2019 16:50:24 +0000</pubDate>
      <link>https://dev.to/tomekbuszewski/what-is-redux-part-2-321n</link>
      <guid>https://dev.to/tomekbuszewski/what-is-redux-part-2-321n</guid>
      <description>&lt;h1&gt;
  
  
  What is Redux, really? – Part 2
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://dev.to/tomekbuszewski/what-is-redux-really-part-1-54ea"&gt;Last time&lt;/a&gt; I talked about state management in general. Now let's see what Redux – the state manager for React – is all about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;To take full advantage of this article, it's important to remember what is a state manager. &lt;strong&gt;It's a tool that allows to both read and write information about the application&lt;/strong&gt;. You can use it to inform one module about changes in the other one without making too much fuss.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two fundaments of Redux – Actions and Reducers
&lt;/h2&gt;

&lt;p&gt;Redux operates with many terms, such as store, state, dispatchers, selectors etc. But the most important are actions and reducers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Action – request the change
&lt;/h3&gt;

&lt;p&gt;Actions are the building blocks of an interactive state. &lt;strong&gt;They are responsible for "telling" the state how to change&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here's an exemplary action that will change an order state from "awaiting" to "shipped":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SET_ORDER_SHIPPED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SET_ORDER_SHIPPED&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;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SET_ORDER_SHIPPED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's explain what is happening here. &lt;code&gt;type&lt;/code&gt; is the name of action that is being executed, and &lt;code&gt;payload&lt;/code&gt; is the required information. Here, our &lt;code&gt;type&lt;/code&gt; is &lt;code&gt;SET_ORDER_SHIPPED&lt;/code&gt; and &lt;code&gt;payload&lt;/code&gt; is &lt;code&gt;123&lt;/code&gt; – our product's ID. In human terms, it would sound like "Change order 123 status to Shipped".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why defining types as variables rather than strings?&lt;/strong&gt;\&lt;br&gt;
It's tempting to create action types as text, but this can generate problems in reducers. You have to be sure that there's no typos anywhere. Defining a constant name once and then using it in both action and reducer prevents such problems.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Dynamic actions – or, created actions
&lt;/h4&gt;

&lt;p&gt;It's very easy to dispatch an action that has all the fields defined. But it's very cumbersome to create an action for every item, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SET_ORDER_1_SHIPPED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SET_ORDER_SHIPPED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SET_ORDER_2_SHIPPED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SET_ORDER_SHIPPED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What we need here is an &lt;strong&gt;action creator&lt;/strong&gt;. Something that will generate the action basing on some terms. &lt;/p&gt;

&lt;p&gt;What is important about action creators is that they need to be pure functions. Meaning, every time an action is created, the result (and the reducer result) has to be exactly the same. They cannot interfere with anything from the outside.&lt;/p&gt;

&lt;p&gt;So, let's create an action creator for our shipping:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setShipped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SET_ORDER_SHIPPED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;payload&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="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;Now, running &lt;code&gt;setShipped(123)&lt;/code&gt; will create an action that we want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ type: SET_ORDER_SHIPPED, payload: 123 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  What happens after an action is fired?
&lt;/h4&gt;

&lt;p&gt;In Redux, actions aren't really "fired". They are being &lt;em&gt;dispatched&lt;/em&gt;. Actually, you have to dispatch them. Basically, it looks like this: you click a button &lt;code&gt;Mark the order as Shipped&lt;/code&gt;. Action &lt;code&gt;SET_ORDER_SHIPPED&lt;/code&gt; is being &lt;strong&gt;dispatched&lt;/strong&gt; and reducer receives it. After processing, the change is reflected in the store.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reducer – make the change
&lt;/h3&gt;

&lt;p&gt;Action alone is nothing. Who knows what &lt;code&gt;SET_ORDER_SHIPPED&lt;/code&gt; means? Well, we should know. And our reducer should as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reducer is responsible for receiving that action call and applying the change&lt;/strong&gt;. Most of the time, it's in a form of &lt;code&gt;switch&lt;/code&gt; statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&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="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;SET_ORDER_SHIPPED&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SHIPPED&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="nx"&gt;order&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="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&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;What's important for reducers it that they always have to return the state. The whole application relies on it, and if something goes wrong, it will crash.&lt;/p&gt;

&lt;h2&gt;
  
  
  States and store – what's the difference?
&lt;/h2&gt;

&lt;p&gt;Redux operates on two very important concepts – states and store. &lt;strong&gt;They are not, by any means, interchangeable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There are multiple states&lt;/strong&gt;. Every module can have its own state. They are responsible for housing all the information and make it available to the app. Example of states:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;234&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SHIPPED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;214&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AWAITING_PAYMENT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;345&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AWAITING_PAYMENT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clients&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Frank&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ocean&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;addresses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Marky&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;addresses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;234&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;addresses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lamp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Desk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bulb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;States can be very good information storages. If you need to display items in various places in your store, a single source of data is a good idea.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There is always a single store&lt;/strong&gt;. It's built with states, with every state being a separate entity. Example of store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;clients&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;Since there is only one store, it houses all the states and has an API that allows the app to interact with them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You never modify the state directly&lt;/strong&gt;. It always has to done via the store.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single-state store
&lt;/h3&gt;

&lt;p&gt;There is an option to have only one state, for example, housing only &lt;code&gt;orders&lt;/code&gt;. While perfectly fine, it will probably result in two things – either growing to the point where it will be very hard to maintain, or being a very small collection of information that would work stored someplace else.&lt;/p&gt;

&lt;p&gt;In my opinion, creating a single-state store is pointless. If you need to store very little information, keep it someplace else. If you don't know, how much data you'll store, create a multi-state store. It will scale much better, and refactoring single-state to multi-state can be tedious.&lt;/p&gt;

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

&lt;p&gt;I hope this clears out Redux in general a bit. I know this is a lot of information, so I've prepared a code sample for this part. In there you'll find a working examples of an action, a reducer, state and store.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://codesandbox.io/s/redux-pt2-dotee" rel="noopener noreferrer"&gt;Code sample on CodeSandBox&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the next part I'll explain how this all blends in React ecosystem.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>redux</category>
    </item>
    <item>
      <title>The three states of data-driven UI</title>
      <dc:creator>Tomasz Buszewski</dc:creator>
      <pubDate>Wed, 20 Nov 2019 16:39:13 +0000</pubDate>
      <link>https://dev.to/tomekbuszewski/the-three-states-of-data-driven-ui-24go</link>
      <guid>https://dev.to/tomekbuszewski/the-three-states-of-data-driven-ui-24go</guid>
      <description>&lt;p&gt;How should our UI behave, when our logic doesn't really know, whether there will be any actual data?&lt;/p&gt;

&lt;p&gt;I remember the times, when there was no such issue as "not knowing" about the data in the UI. We knew, and if it was there – we imported the template. If not – we didn't even display the section responsible. It was all server rendered and handled by a simple &lt;code&gt;if&lt;/code&gt; condition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight twig"&gt;&lt;code&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;comments&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
  &lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;include&lt;/span&gt; &lt;span class="s2"&gt;"comments.html"&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;comments&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that was it, really. &lt;/p&gt;

&lt;p&gt;We can have similar approach today. Why not? In our React app, it would be as easy as to write&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;comments&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Comments&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a &lt;strong&gt;binary state&lt;/strong&gt;. True or false, 1 or 0. Nothing more to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The third state
&lt;/h2&gt;

&lt;p&gt;As clarified before, two states are &lt;code&gt;true&lt;/code&gt; – there is some data, or &lt;code&gt;false&lt;/code&gt; – there is not. &lt;strong&gt;But we can expand it, have an ambiguous in-the-middle&lt;/strong&gt; one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;STATE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OK&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;FETCHING&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FETCHING&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;NO_DATA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;NO_DATA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will allow us to have more complex rendering and provide user with the actual information about what is happening.&lt;/p&gt;

&lt;p&gt;Assuming the backend returns a JSON array, code can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Comments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fetchState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setFetchState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;STATE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FETCHING&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;comments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setComments&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="nx"&gt;React&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="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchComments&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="nx"&gt;props&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="nf"&gt;setFetchState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})();&lt;/span&gt;
  &lt;span class="p"&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;fetchState&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;STATE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Comment&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;comment&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="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="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;fetchState&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;STATE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NO_DATA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;NoData&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No comments for this post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are using very extensive render fragment – two &lt;code&gt;if&lt;/code&gt;s and one default &lt;code&gt;return&lt;/code&gt;. This is mostly for clarity, as this could be written in a shorter way. It now demonstrates purely, what will be displayed when. And, we could have more states, for example, when fetching will not be successful. &lt;/p&gt;

&lt;p&gt;This approach is far better than basing on state derived from data. We could check &lt;code&gt;comments&lt;/code&gt; array for length, and even turn it into &lt;code&gt;null&lt;/code&gt; when fetch returns no result. But this introduces a risky type change – we'd transform an array into a &lt;code&gt;null&lt;/code&gt;. We'd have to check this type every time we would like to do an operation on this value. This is far too error prone.&lt;/p&gt;

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

&lt;p&gt;This is very basic and very simple example of how UI should be treated with async data. Displaying endless spinners when there's nothing fetched is very bad practice and should be avoided. With this approach, you can have cleaner and more intuitive UI and UX.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
