<?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>Forem: Nathanaël CHERRIER</title>
    <description>The latest articles on Forem by Nathanaël CHERRIER (@mindsers).</description>
    <link>https://forem.com/mindsers</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%2F13524%2F9c4f78e7-3aa0-4991-92ea-3187093a8752.png</url>
      <title>Forem: Nathanaël CHERRIER</title>
      <link>https://forem.com/mindsers</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mindsers"/>
    <language>en</language>
    <item>
      <title>Optimize your SwiftUI code: Two ways to avoid duplication</title>
      <dc:creator>Nathanaël CHERRIER</dc:creator>
      <pubDate>Sat, 24 Jun 2023 14:19:20 +0000</pubDate>
      <link>https://forem.com/mindsers/optimize-your-swiftui-code-two-ways-to-avoid-duplication-3okn</link>
      <guid>https://forem.com/mindsers/optimize-your-swiftui-code-two-ways-to-avoid-duplication-3okn</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nV3Uu74S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.unsplash.com/photo-1614741118887-7a4ee193a5fa%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DM3wxMTc3M3wwfDF8c2VhcmNofDF8fHN3aWZ0fGVufDB8fHx8MTY4NzYxMjA1OXww%26ixlib%3Drb-4.0.3%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nV3Uu74S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.unsplash.com/photo-1614741118887-7a4ee193a5fa%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DM3wxMTc3M3wwfDF8c2VhcmNofDF8fHN3aWZ0fGVufDB8fHx8MTY4NzYxMjA1OXww%26ixlib%3Drb-4.0.3%26q%3D80%26w%3D2000" alt="Optimize your SwiftUI code: Two ways to avoid duplication" width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code duplication&lt;/strong&gt; is a real problem in applications. Having a lot of &lt;strong&gt;duplicate code&lt;/strong&gt; means “complicated maintenance” but also a catastrophic experience.&lt;/p&gt;

&lt;p&gt;I have two methods to avoid this problem in my &lt;a href="https://steply-app.com"&gt;Swift applications&lt;/a&gt;. I'll tell you all about them in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom components for greater SwiftUI code modularity
&lt;/h2&gt;

&lt;p&gt;As you would with other frameworks, SwiftUI allows you to create views in a declarative/descriptive way.&lt;/p&gt;

&lt;p&gt;The views are composed of other views and the pattern can be repeated endlessly on several levels.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;SignInScreen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;VStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;leading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connect"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="kt"&gt;Spacer&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;In the example above, the &lt;code&gt;SignInScreen&lt;/code&gt; view is composed of a &lt;code&gt;VStack&lt;/code&gt; view, a Text view and a Spacer view. Same operation therefore as a web framework or the global component will be composed of several smaller components.&lt;/p&gt;

&lt;p&gt;Since views are just assemblies of views, we too can create our own views to bring together repeating elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;SignInScreen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;VStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;leading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Email address"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="kt"&gt;DividerCustom&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="kt"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connect"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// action&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="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;SignUpScreen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;VStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;leading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Email address"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="kt"&gt;DividerCustom&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="kt"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sign Up"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// action&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="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;DividerCustom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;HStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;VStack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kt"&gt;Divider&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;background&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;green&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"or"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="kt"&gt;VStack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kt"&gt;Divider&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;background&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;green&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;DividerCustom&lt;/code&gt; view combines three other views and thus forms a view that is called in the &lt;code&gt;SignInScreen&lt;/code&gt; and &lt;code&gt;SignUpScreen&lt;/code&gt; view.&lt;/p&gt;

&lt;p&gt;Modifying the &lt;code&gt;DividerCustom&lt;/code&gt; code will update the element in both components where it is used. This prevents the code from being duplicated several times in the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimization with modifiers and &lt;code&gt;ViewModifier&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Sometimes, what is duplicated is not a set of components but a set of modifications on a single view.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;Buttons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// action&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connect with Google"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"GoogleLogo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;infinity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;minWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;background&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;foregroundColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foregroundColor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cornerRadius&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;font&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Theme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;regular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="kt"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// action&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connect with Facebook"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"FacebookLogo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;infinity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;minWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;background&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;foregroundColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foregroundColor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cornerRadius&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;font&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Theme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;regular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="kt"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// action&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connect with GitHub"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"GitHubLogo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;infinity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;minWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;background&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;foregroundColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foregroundColor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cornerRadius&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;font&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Theme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;regular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, we want to display three login buttons for different services.&lt;/p&gt;

&lt;p&gt;We don't want to change the behavior of a classic button or even associate it with other views so that they work together. What we want here is to modify the design of the button so that all the buttons look the same.&lt;/p&gt;

&lt;p&gt;We will end up with 6 lines of modifications of a button which are duplicated each time a new button is created.&lt;/p&gt;

&lt;p&gt;If I ultimately want to change the button's maximum width, I'll have to apply the change manually for each button!&lt;/p&gt;

&lt;p&gt;One solution to avoid code duplication (and simplify application maintenance) in this situation is &lt;code&gt;ViewModifiers&lt;/code&gt;. This is a very simple way to apply modifiers to multiple views:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;BasicButton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;ViewModifier&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Color&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;foregroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Color&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;content&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;minWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;alignment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;background&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;foregroundColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foregroundColor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cornerRadius&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;font&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Theme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;regular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&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;A &lt;code&gt;ViewModifier&lt;/code&gt; is a struct with a body function. It is this function that will apply the styles to our views.&lt;br&gt;
To use it, we use the generic modifier &lt;code&gt;modifier()&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kt"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// action&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connect with GitHub"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"GitHubLogo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;infinity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;modifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;BasicButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;black&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;foregroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;white&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;BasicButton&lt;/code&gt; will apply the styles to our Button view with no more effort.&lt;/p&gt;

&lt;p&gt;To make the code a little more elegant, here is a little trick:&lt;br&gt;
And we call this function from our Button view like classic modifiers&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kt"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// action&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Connect with GitHub"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"GitHubLogo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;infinity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withSteplyDefaultStyle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We first add a function to the &lt;code&gt;View&lt;/code&gt; class that will call the modifier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;withSteplyDefaultStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;foregroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;white&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;modifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;BasicButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;foregroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;foregroundColor&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;Note also the use of optional parameters, so you don't have to mention them if they do not change.&lt;/p&gt;

&lt;p&gt;You can also limit the use of this modifier to the &lt;code&gt;Button&lt;/code&gt; view by extending the &lt;code&gt;Button&lt;/code&gt; class rather than View, as we have done here.&lt;/p&gt;

&lt;p&gt;The downside is that you will only be able to call the modifier directly on the view. It cannot be chained after other modifiers because this one returns an object of type View and not &lt;code&gt;Button&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;As already discussed, avoiding code duplication is not only a good practice to make your code look “pretty”. Rather, it's one of the easiest ways to optimize your code to reduce development time and application maintenance time.&lt;br&gt;
Do not hesitate to use the &lt;code&gt;ViewModifier&lt;/code&gt; or the creation of custom components to optimize your &lt;a href="https://mindsers.blog/topic/swift/"&gt;SwiftUI&lt;/a&gt; code.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>bestpractices</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>How to connect to a distant server using SSH</title>
      <dc:creator>Nathanaël CHERRIER</dc:creator>
      <pubDate>Mon, 20 Feb 2023 13:44:27 +0000</pubDate>
      <link>https://forem.com/mindsers/how-to-connect-to-a-distant-server-using-ssh-amf</link>
      <guid>https://forem.com/mindsers/how-to-connect-to-a-distant-server-using-ssh-amf</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S4phCZsa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2023/02/servers-in-a-tunnel.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S4phCZsa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2023/02/servers-in-a-tunnel.jpg" alt="How to connect to a distant server using SSH" width="600" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using SSH to connect to its servers seems like a basic thing, but for many, SSH remains an obscure software/protocol. We will clarify all this, and we will take the opportunity to go a bit further.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;⚠️ Read more of my blog posts about tech and business &lt;a href="https://mindsers.blog/"&gt;on my personal blog&lt;/a&gt;! ⚠️&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Here is the definition given by Wikipedia:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Secure Shell (SSH) is both a computer program and a secure communication protocol. [...] All TCP segments are authenticated and encrypted. It therefore becomes impossible to use a sniffer to see what the user is doing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Simply put, SSH is a secure “Shell” that allows us to take control of our remote servers.&lt;/p&gt;

&lt;p&gt;It also allows you to do a multitude of other things, but we won't see them here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing SSH
&lt;/h2&gt;

&lt;p&gt;To be able to use SSH, you will have to install it on the server machine and on the client machines.&lt;/p&gt;

&lt;p&gt;On most Unix machines (including Linux and Mac) SSH is a package installed by default. If however on your machine this is not the case, you can launch a command like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install ssh 

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

&lt;/div&gt;



&lt;p&gt;Change the package manager and its syntax to that of your distribution.&lt;/p&gt;

&lt;p&gt;For those who have a Windows client machine, you can install SSH clients like &lt;a href="http://www.putty.org"&gt;PuTTY&lt;/a&gt; or &lt;a href="http://www.openssh.com"&gt;OpenSSH&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Now that you have installed SSH, you will need to configure it.&lt;/p&gt;

&lt;p&gt;By default, all users on the server can initiate a remote connection with SSH. That means we can already use our machine remotely. On the other hand, we wouldn't want some smart guy to be able to log in as &lt;em&gt;root&lt;/em&gt; on our server.&lt;/p&gt;

&lt;p&gt;To prevent this, we will start by creating a new user on the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Serveur
adduser userName

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

&lt;/div&gt;



&lt;p&gt;Answer the questions posed by the utility, and your new user will be created and usable by SSH.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Serveur
adduser userName sudo

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

&lt;/div&gt;



&lt;p&gt;We add our new user to the list of users who have the right to perform certain tasks normally dedicated to the superuser without being one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connection using keys
&lt;/h2&gt;

&lt;p&gt;Many attacks using the SSH protocol use the “brute force” method. Because of this, password-based logins are less secure than key pair-based logins.&lt;/p&gt;

&lt;p&gt;Let's give our user the ability to login by keys.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Client
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

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

&lt;/div&gt;



&lt;p&gt;This command creates an RSA encryption key of 4096 bytes. &lt;code&gt;ssh-keygen&lt;/code&gt; generates a public key and a private key. &lt;strong&gt;The private key should never leave your machine and should never be shared with anyone.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Serveur
mkdir ~/.ssh

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

&lt;/div&gt;



&lt;p&gt;The public key we just created must be transferred to the remote server and added to the list of keys authorized to connect with the new user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Client
ssh-copy-id -i adresse/de/votre/clepublique.pub user@server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you do a test now (&lt;code&gt;ssh user@server&lt;/code&gt;) SSH should not ask you for a password to initiate the connection.&lt;/p&gt;

&lt;p&gt;If you are prompted for a password, it means something went wrong with the steps above. I advise you not to move on without having solved the problem.&lt;/p&gt;

&lt;p&gt;☝️&lt;/p&gt;

&lt;p&gt;If the connection fails for no apparent reason, verify that the key &lt;code&gt;PubkeyAuthentication&lt;/code&gt; is indicated as &lt;code&gt;yes&lt;/code&gt; in the file &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small additional security tweaks
&lt;/h2&gt;

&lt;p&gt;Now that our new user is ready, let's prevent &lt;code&gt;root&lt;/code&gt; from logging in and change a few things.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Serveur
vim /etc/ssh/sshd_config

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

&lt;/div&gt;



&lt;p&gt;Change &lt;code&gt;Port&lt;/code&gt; to any numeric value (retain it) above 1024, &lt;code&gt;PermitRootLogin&lt;/code&gt; and &lt;code&gt;PasswordAuthentication&lt;/code&gt; to &lt;code&gt;no&lt;/code&gt;. You should have :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Port 2923
PermitRootLogin no
PasswordAuthentication no

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

&lt;/div&gt;



&lt;p&gt;Thus, hackers who try to connect to your server on port 22 will fail. They also won't be able to log in directly to &lt;code&gt;root&lt;/code&gt; and have all rights too easily.&lt;/p&gt;

&lt;p&gt;The last line prevents password authentication. So, no more “brute force” attacks, attempts by clever little guys who think they have found your password. Anyone who wants to connect to your server must have their public key (or one of their keys) saved in your machine.&lt;/p&gt;

&lt;p&gt;To sum up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Client
ssh user@server.com -p 2923 # to log in 

ssh user@server.com # doesn't work
ssh root@server.com -p 2923 # doesn't work

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;.ssh/config&lt;/code&gt; : simplify your life
&lt;/h3&gt;

&lt;p&gt;Imagine that you have several servers to manage, that for each one you have a different pair of keys, a different user: it is easy to see the mess that can become. A solution exists, the file &lt;code&gt;~/.ssh/config&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Client
vim ~/.ssh/config


Host sous.domaine.com
  IdentityFile /home/user/.ssh/privatekey

Host domaine.org
  IdentityFile /home/user/.ssh/privatekey2

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

&lt;/div&gt;



&lt;p&gt;Thanks to the &lt;code&gt;IdentityFile&lt;/code&gt; key, SSH now knows which private key to use for &lt;code&gt;domain.org&lt;/code&gt; and &lt;code&gt;sub.domain.com&lt;/code&gt; hosts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Host sous.domaine.com
  IdentityFile /home/user/.ssh/privatekey

Host nomPersonnalisable
  HostName github.com
  IdentityFile /home/user/.ssh/privatekey3

Host nomPersonnalisable2
  HostName github.com
  IdentityFile /home/user/.ssh/privatekey2

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

&lt;/div&gt;



&lt;p&gt;If you have two accounts on GitHub (or two users on any server) and different key pairs for each account, you can add the &lt;code&gt;HostName&lt;/code&gt; key with the domain name value and change &lt;code&gt;Host&lt;/code&gt; to a customizable name. Thus, you can have two different SSH configurations for the same server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Host gitserver
  HostName git.com
  User userName
  Port 2923
  IdentityFile /home/user/.ssh/privatekey2

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

&lt;/div&gt;



&lt;p&gt;Two other interesting keys to know are the &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;Port&lt;/code&gt; keys. Their name couldn't be clearer, and the example speaks for itself.&lt;/p&gt;

&lt;p&gt;It's a simple config that allows us to connect to our server by typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh gitserver

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

&lt;/div&gt;



&lt;p&gt;You can compare both versions of the connection command, the last is obviously simpler.&lt;/p&gt;

</description>
      <category>ssh</category>
      <category>security</category>
      <category>server</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to secure a web server (VPS)</title>
      <dc:creator>Nathanaël CHERRIER</dc:creator>
      <pubDate>Thu, 12 Jan 2023 05:00:03 +0000</pubDate>
      <link>https://forem.com/mindsers/how-to-secure-a-web-server-vps-319d</link>
      <guid>https://forem.com/mindsers/how-to-secure-a-web-server-vps-319d</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9vwxdbb6ap7x7uuevtnr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9vwxdbb6ap7x7uuevtnr.png" alt="How to secure a web server (VPS)" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are several reasons why a developer would want to manage their own servers. Servers, especially VPS (Virtual Private Server), have become very affordable resources. They allow us to test, build, host our projects and do many other things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;⚠️ Read more of my blog posts about tech and business &lt;a href="https://mindsers.blog/" rel="noopener noreferrer"&gt;on my personal blog&lt;/a&gt;! ⚠️&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whatever use you make of a server, it must be protected, because an intrusion could have serious repercussions. In this article, I explain how to secure a VPS simply in 5 simple steps.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;☝️ I assume that you have just purchased your VPS and that you have never connected to it before. But, most of the steps are feasible on an already running server.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1/ Update your system
&lt;/h2&gt;

&lt;p&gt;This may sound basic to you, but one of the primary reasons for finding flaws in web servers is system obsolescence. Not updating your systems regularly is a real danger for your business.&lt;/p&gt;

&lt;p&gt;Even if you have just requested the installation of your VPS from your host, you will benefit from updating your system before moving on to the rest of this article. Indeed, hosts often use backups or snapshots to create new servers. So, there is a good chance that the packages on your system need updates.&lt;/p&gt;

&lt;p&gt;Run the following commands:&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2/ Change &lt;code&gt;root&lt;/code&gt; password
&lt;/h2&gt;

&lt;p&gt;I'm not sure it's worth explaining. Change your &lt;code&gt;root&lt;/code&gt; password.&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;su
&lt;span class="nv"&gt;$ &lt;/span&gt;passwd
New password: 
Retype new password: 
passwd: password updated successfully
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;root&lt;/code&gt; account is the “super-administrator” account. He has all the rights. If there is an account that we refuse to leave in the hands of hackers, it is this one.&lt;/p&gt;

&lt;p&gt;But changing the &lt;code&gt;root&lt;/code&gt; account password is not enough. You will see that a little further in the rest of the article.&lt;/p&gt;

&lt;h2&gt;
  
  
  3/ Create a new user
&lt;/h2&gt;

&lt;p&gt;Another tip to avoid problems on your server: don't use &lt;code&gt;root&lt;/code&gt;. I see at least two reasons for this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;everyone has a &lt;code&gt;root&lt;/code&gt; user on their machine by default. It's easy for a hacker to guess&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;root&lt;/code&gt; has all rights on the machine. If a person finds the root account password, he can do anything on the machine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;☝️ Some hosts, to limit this problem, change the name of the root account. Don't think you're protected, though! As explained above, because of the automation of their process, they often give the same names to all customers. It is therefore enough to know who your host is to know how it works, and therefore to know how to attack your machine.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The best solution to prevent this problem is to use a different account to manage your machine. To do this, use the following command:&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="nv"&gt;$ &lt;/span&gt;adduser nameOfTheUser
Adding user &lt;span class="sb"&gt;`&lt;/span&gt;nameOfTheUser&lt;span class="s1"&gt;' ...
Adding new group `nameOfTheUser'&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;1001&lt;span class="o"&gt;)&lt;/span&gt; ...
Adding new user &lt;span class="sb"&gt;`&lt;/span&gt;nameOfTheUser&lt;span class="s1"&gt;' (1001) with group `nameOfTheUser'&lt;/span&gt; ...
Creating home directory &lt;span class="sb"&gt;`&lt;/span&gt;/home/nameOfTheUser&lt;span class="s1"&gt;' ...
Copying files from `/etc/skel'&lt;/span&gt; ...
New password: 
Retype new password: 
passwd: password updated successfully
Changing the user information &lt;span class="k"&gt;for &lt;/span&gt;nameOfTheUser
Enter the new value, or press ENTER &lt;span class="k"&gt;for &lt;/span&gt;the default
        Full Name &lt;span class="o"&gt;[]&lt;/span&gt;:
        Room Number &lt;span class="o"&gt;[]&lt;/span&gt;: 
        Work Phone &lt;span class="o"&gt;[]&lt;/span&gt;: 
        Home Phone &lt;span class="o"&gt;[]&lt;/span&gt;: 
        Other &lt;span class="o"&gt;[]&lt;/span&gt;:
Is the information correct? &lt;span class="o"&gt;[&lt;/span&gt;Y/n]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After answering all the questions of the utility, let's tell the system that this new user will be able to perform actions usually dedicated to the superuser without being one.&lt;/p&gt;

&lt;p&gt;The idea is to be able to say “I'm not a superuser, give me no rights” but temporarily, when the situation requires it, tell the system “in fact, I'm the superuser, let me do this one-time action”.&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="nv"&gt;$ &lt;/span&gt;adduser nameOfTheUser &lt;span class="nb"&gt;sudo
sudo &lt;/span&gt;adduser nameOfTheUser &lt;span class="nb"&gt;sudo
&lt;/span&gt;Adding user &lt;span class="sb"&gt;`&lt;/span&gt;nameOfTheUser&lt;span class="s1"&gt;' to group `sudo'&lt;/span&gt; ...
Adding user nameOfTheUser to group &lt;span class="nb"&gt;sudo
&lt;/span&gt;Done.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you will be able to type the &lt;code&gt;sudo&lt;/code&gt; command from your new user account without receiving a system denial. You can also connect in SSH directly with this user.&lt;/p&gt;

&lt;h2&gt;
  
  
  4/ Change SSH access
&lt;/h2&gt;

&lt;p&gt;Now that only you know the password for the root account, and you no longer use it to connect to the server, it's time to go a little further.&lt;/p&gt;

&lt;p&gt;What are the problems we might encounter? Brute force attack. You no longer use the &lt;code&gt;root&lt;/code&gt; account, but it is still usable. Using randomly generated passwords until one works is a method that still works today.&lt;/p&gt;

&lt;p&gt;The method would also work on the second account that we created above.&lt;/p&gt;

&lt;p&gt;To remedy this, we'll modify the SSH configuration somewhat to log in using an RSA key rather than a password. To be able to log in with a key, you first need... a key.&lt;/p&gt;

&lt;p&gt;So let's generate ours on our local computer (not the server).&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="nv"&gt;$ &lt;/span&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-b&lt;/span&gt; 4096 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"your_email@example.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-t&lt;/code&gt; allows you to indicate the type of key you want to create. We want an RSA key.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-b&lt;/code&gt; specifies the size of the key. I usually put 4096 so that it is twice as long, complex and solid as the default 2048 bites. But, you can put the size you want. Just tell yourself that depending on the power of your computer, the more you ask for a long key, the longer it will take to generate (and use?) it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-C&lt;/code&gt; allows you to add a comment to facilitate your organization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The command will ask you for a &lt;em&gt;passphrase&lt;/em&gt;. It is a sentence that must be indicated to use the key. A kind of password to protect the key. You can leave it out, but &lt;strong&gt;it is strongly recommended that you do put one&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once the key is generated, you will find two new files on your local machine.&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ~/.ssh
id_rsa id_rsa.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id_rsa&lt;/code&gt; is your private key. Not to be communicated under any circumstances. It must not leave your machine and allows you to decrypt the data that is sent to you.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;id_rsa.pub&lt;/code&gt; is the public version of your key. To communicate to those with whom you wish to communicate. It does not make it possible to decrypt the data, but only to encrypt them. In other words, it allows people to write messages that only your private key can decrypt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As I just said, the private key will not move from your machine. However, to be able to communicate with the server, the server must have your public key. So, we have to send it to him.&lt;/p&gt;

&lt;p&gt;No need to open the file and copy-paste anything, there's a command for that:&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="nv"&gt;$ &lt;/span&gt;ssh-copy-id &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/id_rsa nameOfTheUser@ipOfTheServer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will create the &lt;code&gt;~/.ssh&lt;/code&gt; folder in your user's account on the server. Then, it will create the file &lt;code&gt;~/ssh/authorized_keys&lt;/code&gt; in which it will add the public key linked to the private key &lt;code&gt;id_rsa&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Normally, this command sends all public keys from your local machine to the server. To avoid this, we use &lt;code&gt;-i&lt;/code&gt; to tell it which key to send.&lt;/p&gt;

&lt;p&gt;You can now connect without passwords to the server by doing &lt;code&gt;ssh nameOfTheUser@ipOfTheServer&lt;/code&gt;. Only the passphrase will be requested if you have specified one.&lt;/p&gt;

&lt;p&gt;Since it is possible to log in without passwords, all we have to do is disable the login with passwords. Thus, the risk of brute force will be eliminated. To do this, on the server, edit the following lines in the &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; file to have these values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="err"&gt;PasswordAuthentication&lt;/span&gt; &lt;span class="err"&gt;no&lt;/span&gt;
&lt;span class="err"&gt;PubkeyAuthentication&lt;/span&gt; &lt;span class="err"&gt;yes&lt;/span&gt;
&lt;span class="err"&gt;PermitRootLogin&lt;/span&gt; &lt;span class="err"&gt;no&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these settings, it will be impossible to log in with the root account whether you know the password or not. All other accounts will be inaccessible with a password, but accessible if you have the correct RSA key.&lt;/p&gt;

&lt;p&gt;Last detail, the standard port used by SSH is 22. It means that everyone knows this port. To make the access a little more complicated, a good practice is to change this port to a value between 1024 and 6665.&lt;/p&gt;

&lt;p&gt;In the same &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; file, modify the following line with the value of your choice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="err"&gt;Port&lt;/span&gt; &lt;span class="err"&gt;5489&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To validate these changes, restart the SSH agent as follows:&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your server now looks a bit more like a fortress.  &lt;code&gt;ssh nameOfTheUser@ipOfTheServer&lt;/code&gt; will no longer work. You will need, in addition to the user and the IP, to indicate the port that you have chosen previously. The password will not be requested, you will need the RSA key to be able to connect.&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="nv"&gt;$ &lt;/span&gt;ssh nameOfTheUser@ipOfTheServer &lt;span class="nt"&gt;-p&lt;/span&gt; 2345 &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/id_rsa 
Enter passphrase &lt;span class="k"&gt;for &lt;/span&gt;key &lt;span class="s1"&gt;'~/.ssh/id_rsa'&lt;/span&gt;:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;☝️ I agree that for greater security, we have largely sacrificed the simplicity and usability of this command. But, &lt;a href="https://mindsers.blog/fr/post/utiliser-ssh-sur-votre-serveur-distant/#-ssh-config-simplifiez-vous-la-vie" rel="noopener noreferrer"&gt;it is possible to simplify it again thanks to the file ~/.ssh/config&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5/ Enable a firewall
&lt;/h2&gt;

&lt;p&gt;The firewall allows you to control who can connect to your server and how. The idea is to avoid leaving windows open in our fortress. We will therefore explicitly specify what we allow as a connection to our server.&lt;/p&gt;

&lt;p&gt;Most Linux distributions have &lt;code&gt;iptables&lt;/code&gt; and &lt;code&gt;ufw&lt;/code&gt; installed by default. I use UFW. I will therefore explain to you the basic rules that I apply for the security of my servers. &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-setup-a-firewall-with-ufw-on-an-ubuntu-and-debian-cloud-server" rel="noopener noreferrer"&gt;To learn more about how this tool works, I recommend this article from DigitalOcean&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We start by disabling the firewall while we make our changes:&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw disable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I change the default rules so that all incoming connections are denied, and all outgoing connections are allowed:&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw default deny incoming
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw default allow outgoing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll allow SSH connections. Otherwise, we will no longer have a way to connect to the server.&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow 2345/tcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change &lt;code&gt;2345&lt;/code&gt; to the port you chose for SSH in the previous step.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;⚠️ UFW knows the default ports for services and offers helpers like &lt;code&gt;ufw allow ssh&lt;/code&gt;. But don't use it for SSH precisely, because you no longer use the default port 22. You risk blocking all SSH connections since SSH no longer listens to port 22.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now we can activate the firewall.&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw &lt;span class="nb"&gt;enable
&lt;/span&gt;Command may disrupt existing ssh connections. Proceed with operation &lt;span class="o"&gt;(&lt;/span&gt;y|n&lt;span class="o"&gt;)&lt;/span&gt;? y
Firewall is active and enabled on system startup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we no longer use the default SSH port, if you still have connections using port 22 (on another terminal, for example), UFW warns you that you may lose your connection.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;☝️ You can verify that your rules are correct before activating the firewall using the &lt;code&gt;ufw status verbose&lt;/code&gt; command.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Now you have all the basics to secure your servers. There are of course many other things that one can implement to secure a server, but with the 5 steps in this article, you will have a server that is much less vulnerable to attacks.&lt;/p&gt;

&lt;p&gt;I have also prepared for those who wish it a print which includes all the commands of this article, a glossary and an explanation of the changes of the &lt;code&gt;sshd_config&lt;/code&gt; file. Nothing more than what is in this article, but the idea is to have a cheat sheet to quickly secure your server.&lt;/p&gt;

&lt;p&gt;If you are a premium member of the blog, download it below. Otherwise, you can find &lt;a href="https://mindsers.shop/products/vps-server-security-cheatsheet" rel="noopener noreferrer"&gt;“VPS/server security cheatsheet” on the store&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ssh</category>
      <category>security</category>
      <category>devops</category>
      <category>server</category>
    </item>
    <item>
      <title>How to code a basic HTTP server using NodeJS</title>
      <dc:creator>Nathanaël CHERRIER</dc:creator>
      <pubDate>Wed, 23 Nov 2022 17:28:00 +0000</pubDate>
      <link>https://forem.com/mindsers/how-to-code-a-basic-http-server-using-nodejs-5232</link>
      <guid>https://forem.com/mindsers/how-to-code-a-basic-http-server-using-nodejs-5232</guid>
      <description>&lt;p&gt;A good method to learn and progress in programming is to try to re-code existing projects. This is what I propose in this article to learn more about Node.js.&lt;/p&gt;

&lt;p&gt;This article is aimed at beginners without dwelling more than necessary on the basic notions of this environment. Feel free to visit the list of articles on &lt;a href="//Node.js"&gt;Node.js&lt;/a&gt; and &lt;a href="https://mindsers.blog/topic/javascript/"&gt;JavaScript&lt;/a&gt; to learn more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;⚠️ Read more of my blog posts about tech and business &lt;a href="https://mindsers.blog/"&gt;on my personal blog&lt;/a&gt;! ⚠️&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I started learning Node.js, the HTTP server was the typical example that was quoted in all articles, blogs and other courses. The goal was to show how easy it is to create a web server with Node.js.&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;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&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;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, World!&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;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;"Hello, World!" de NodeJS&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Well, we quickly realize that it takes a little more code to have a real website, thanks to Node.js. This is why backend frameworks for Node.js have multiplied rapidly. The best known of them is called Express.&lt;/p&gt;

&lt;p&gt;Express is easy to use, quick to set up and has a very large community.&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;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World!&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;"Hello, World!" by ExpressJS&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Without further complicating the code, the code above allows you to return a string for an HTTP method and a specific route. It is very simple to add routes in the same way as for &lt;code&gt;/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Express is very lightweight. It uses a &lt;em&gt;middleware&lt;/em&gt; system that increases the capabilities of the framework.&lt;/p&gt;

&lt;p&gt;For example, to allow Express to understand the JSON in the body of an HTTP request, you must use the &lt;code&gt;bodyParser&lt;/code&gt; middleware.&lt;/p&gt;

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

&lt;p&gt;For those who already knew Express before this article – and even those who are discovering it now – have you ever wondered how Express works?&lt;/p&gt;

&lt;p&gt;What if we code a small web framework to understand how our tools work? Don't misunderstand my intentions. The purpose of this article is not to code yet another framework in an ecosystem that is already saturated with them, and even less to produce production-ready code.&lt;/p&gt;

&lt;p&gt;Besides, I advise you in general not to “reinvent the wheel” in your projects. Node.js has a rich universe of open-source modules for all your needs, do not hesitate to dig into it.&lt;/p&gt;

&lt;p&gt;On the other hand, even if in everyday life it is better to use an existing backend framework, that does not prevent you from coding one for purely educational purposes!&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's code a backend framework in Node.js
&lt;/h2&gt;

&lt;p&gt;As I put the “Hello, World!” code of Node.js and Express, I will also put mine for you. This will serve as our goal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./lib/http/create-server.js&lt;/span&gt;&lt;span class="dl"&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;url&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="s1"&gt;./lib/http/middlewares/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&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;get&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./lib/http/methods/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Hello, World!`&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;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;"Hello World!" of our "from scratch" framework&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This code does exactly the same thing as the one in Express. The syntax differs a lot — it is &lt;a href="https://mindsers.blog/fr/post/decouverte-du-reactive-programming-reactivex/"&gt;greatly inspired by RxJS&lt;/a&gt;'s &lt;code&gt;.pipe()&lt;/code&gt; — but it's still about displaying “Hello, World!” when the user goes to &lt;code&gt;/&lt;/code&gt; and to return a &lt;code&gt;404&lt;/code&gt; if going to an unknown route.&lt;/p&gt;

&lt;p&gt;In the idea, we find the Express middlewares through which the request will pass to create a response to return to the client (the user's browser).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kacs5Fkb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/middleares-schema.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kacs5Fkb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/middleares-schema.png" alt="How to code a basic HTTP server using NodeJS" width="800" height="661"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's a very simplified diagram, but you get the idea.&lt;/p&gt;

&lt;p&gt;You may have understood it, thanks to the syntax (and the reference to RxJS), I would like us to manage to have a rather functional approach with this project. When done well, I find it produces much more expressive code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The HTTP server
&lt;/h2&gt;

&lt;p&gt;The first function to implement is &lt;code&gt;createServer&lt;/code&gt;. It is just a wrapper of the function of the same name in the &lt;code&gt;http&lt;/code&gt; module of Node.js.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createServer&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;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&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;serverResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;createServer&lt;/code&gt; creates the server and returns it. We can then use &lt;code&gt;.listen()&lt;/code&gt; to launch the server.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;http.createServer()&lt;/code&gt; callback function can take an &lt;code&gt;IncommingMessage&lt;/code&gt; (the request made by the client) and a &lt;code&gt;ServerResponse&lt;/code&gt; (the response that we want to return to it) as parameters.&lt;/p&gt;

&lt;p&gt;One of our goals is to have a middleware system that will each in turn modify the request to gradually build the response to be returned to the client. For this, we need a list of middlewares to which we will pass the request and the response each time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;middlewares&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&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;To retrieve the middlewares and have the same syntax as the &lt;code&gt;.pipe()&lt;/code&gt; of RxJS, I use the &lt;a href="https://mindsers.blog/fr/post/rest-parameter-et-spread-operator-en-javascript/"&gt;rest parameter&lt;/a&gt; that we saw in a previous article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;middlewares&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;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&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;Thus middleware such as &lt;code&gt;url&lt;/code&gt; and &lt;code&gt;router&lt;/code&gt; can modify &lt;code&gt;incommingMessage&lt;/code&gt; and/or &lt;code&gt;serverResponse&lt;/code&gt; by reference. At the end of our modification pipe, we trigger the &lt;code&gt;.end()&lt;/code&gt; event which will send the response to the client.&lt;/p&gt;

&lt;p&gt;A few things still bother me about this code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;incommingMessage&lt;/code&gt; and &lt;code&gt;serverResponse&lt;/code&gt; are directly modified. I would prefer that they were not to stay closer to the philosophy of functional programming.&lt;/li&gt;
&lt;li&gt;All middleware must be called in our implementation, but Express allows you to stop the “pipe” of modifications if necessary. This is useful for an authentication middleware, for example.&lt;/li&gt;
&lt;li&gt;Some middleware might need to block the execution of the modification “pipe” to perform slightly longer tasks. Currently, our code would not wait and the execution of certain middleware could overlap in time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let's fix all that. First, the last point. It's the easiest to set up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;middlewares&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;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&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;Thus, if the middleware is executed asynchronously, we will wait for the end of its execution to move on.&lt;/p&gt;

&lt;p&gt;To avoid the modification of &lt;code&gt;incommingMessage&lt;/code&gt; and &lt;code&gt;serverResponse&lt;/code&gt;, I think the easiest way is to use the return value of the middlewares. These are simple functions, let's use them as such: input values that must not be modified, but which are used to construct the return value. This return value is then used as the input value of the following (middleware) function. And so on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;middlewares&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;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;requestContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;requestContext&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;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&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;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseBody&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseBody&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&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;I created a &lt;code&gt;requestContext&lt;/code&gt; which is a working object for middlewares. It is passed as input value to all middleware alongside the request.&lt;/p&gt;

&lt;p&gt;The middlewares process these values and create a new context, which they then returns. We overwrite the old context with the new one which is more up to date.&lt;/p&gt;

&lt;p&gt;When we are done modifying the context by the middlewares, we use it to emit the response from the server.&lt;/p&gt;

&lt;p&gt;Finally, to be able to stop the pipe in the middle, I found nothing better than a small &lt;code&gt;boolean&lt;/code&gt;. We can add it to the context. If a middleware changes it to true, the pipe is broken and the response is sent directly with the current context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;middlewares&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;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;requestContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;closeConnection&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="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;middlewares&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;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closeConnection&lt;/span&gt; &lt;span class="o"&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="k"&gt;break&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nx"&gt;requestContext&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;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&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;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseBody&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseBody&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;serverResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Parse the request URL
&lt;/h2&gt;

&lt;p&gt;Let's move on to writing our first middleware: &lt;code&gt;url&lt;/code&gt;. Its purpose is to parse the URL of the request to provide us with information that other middlewares might need next.&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;function&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incomingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestContext&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="nx"&gt;requestContext&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The middleware API is simple in our framework.&lt;/p&gt;

&lt;p&gt;This is a function that can take as parameter everything it may need for its operation or to allow the user to modify its operation. Here &lt;code&gt;url&lt;/code&gt; does not take any parameters.&lt;/p&gt;

&lt;p&gt;This function will then return another function which will be executed later in the &lt;code&gt;for loop (const middleware of middlewares)&lt;/code&gt; of the &lt;code&gt;createServer&lt;/code&gt; callback. It is this function that takes &lt;code&gt;incommingMessage&lt;/code&gt; and &lt;code&gt;requestContext&lt;/code&gt; as parameters and then returns a new version of &lt;code&gt;requestContext&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incomingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestContext&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="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incomingMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`http://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;incomingMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;url&lt;/code&gt; middleware adds to the context of the request a &lt;code&gt;url&lt;/code&gt; attribute which contains a parsed &lt;a href="https://nodejs.org/docs/latest-v13.x/api/url.html"&gt;&lt;code&gt;URL&lt;/code&gt; object&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We can therefore make &lt;code&gt;requestContext.url.pathname&lt;/code&gt; and have access to the &lt;code&gt;pathname&lt;/code&gt; of the request.&lt;/p&gt;

&lt;h2&gt;
  
  
  The router of our framework
&lt;/h2&gt;

&lt;p&gt;The router of our framework will also be a middleware usable with &lt;code&gt;createServer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To make it simple, we will define a route as follows:&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;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestContext&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="s2"&gt;`Hello, World!`&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 object is made up of three essential pieces of information for our router:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the concerned &lt;code&gt;pathname&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;HTTP&lt;/code&gt; verb used&lt;/li&gt;
&lt;li&gt;the function capable of generating something to return to the client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As input to our &lt;code&gt;router&lt;/code&gt; middleware, we will take an array of routes.&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;function&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;routes&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;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&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;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&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;requestContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;responseBody&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;controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestContext&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each time a client makes a request to the server, the router will scroll down the list of routes and check which one matches the client's request. As soon as it finds one, it stops the loop and executes the controller function of the route.&lt;/p&gt;

&lt;p&gt;What the &lt;code&gt;controller&lt;/code&gt; returns can then be added to the context as a &lt;code&gt;responseBody&lt;/code&gt;. This is what the server returns to the client.&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;function&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;routes&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;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&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;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;responseBody&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;controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;closeConnection&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="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;requestContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;404&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;To make the client understand what happens when the router can't find the requested route, I added &lt;code&gt;404&lt;/code&gt; error code handling after the loop. The return in the loop stops the function completely, so if the function did not stop in the middle of the loop, it is necessarily that we did not find a match in the declared routes. We therefore return a context with the &lt;code&gt;statusCode&lt;/code&gt; at &lt;code&gt;404&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With this function, we can declare our routes as follows:&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;router&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;controller&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="s2"&gt;`Hello, World!`&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;Everything works fine and we could stop there, but we don't have exactly the same code as the one I showed you at the beginning of the article.&lt;/p&gt;

&lt;p&gt;All that's missing is syntactical sugar: code that will only serve to make our features easier and more enjoyable to use.&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;function&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pathname&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="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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;pathname&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="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 function is only used to return the “route” object needed by the &lt;code&gt;router&lt;/code&gt; function. Nothing complicated here.&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;function&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pathname&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="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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;function&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;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The get() HTTP method needs a controller to work as expected&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;if&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;pathname&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The get() HTTP method needs a pathname to work as expected&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;pathname&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;Another advantage of this function is that it allows us quite simply to test our data without complicating the code of our router.&lt;/p&gt;

&lt;p&gt;The router is now used as follows:&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;router&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Hello, World!`&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 very close to the result we want to achieve. The last changes are to be made in the implementation of &lt;code&gt;router&lt;/code&gt; itself.&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;function&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;routes&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="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;routes&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;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&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;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;responseBody&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;controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incommingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;closeConnection&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="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;requestContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;404&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;I only modified the &lt;code&gt;routes&lt;/code&gt; parameter so that it is no longer an array, but a rest parameter as for &lt;code&gt;createServer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Thus, we have achieved our goal and ended this article. Appreciate your hard work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./lib/http/create-server.js&lt;/span&gt;&lt;span class="dl"&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;url&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="s1"&gt;./lib/http/middlewares/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&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;get&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./lib/http/methods/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Hello, World!`&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;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to go a little deeper into the concepts seen quickly in this article or go further, I advise you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mindsers.blog/post/destructuring-javascript/"&gt;destructuring objects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mindsers.blog/fr/post/rest-parameter-et-spread-operator-en-javascript/"&gt;rest parameter and spread operator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mindsers.blog/fr/post/maitriser-les-tableaux-en-javascript-fp/"&gt;arrays&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mindsers.blog/fr/post/les-fat-arrow-function-en-javascript/"&gt;fat arrow functions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>http</category>
      <category>backend</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>What is the JAMstack and why should you use it?</title>
      <dc:creator>Nathanaël CHERRIER</dc:creator>
      <pubDate>Wed, 16 Nov 2022 05:00:12 +0000</pubDate>
      <link>https://forem.com/mindsers/what-is-the-jamstack-and-why-should-you-use-it-24od</link>
      <guid>https://forem.com/mindsers/what-is-the-jamstack-and-why-should-you-use-it-24od</guid>
      <description>&lt;p&gt;I still remember the first websites I sold. Simple static sites that no one would want today. However, the last few years have seen the emergence of a technology (or rather an approach to website development) that comes very close to it, but which claims to be much more powerful: the JAMstack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;⚠️ Read more of my blog posts about tech and business &lt;a href="https://mindsers.blog/"&gt;on my personal blog&lt;/a&gt;! ⚠️&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I tested it and adopted it. The JAMstack is also what I used to code the latest version of the &lt;a href="https://travel-and-food.com/"&gt;www.travel-and-food.com&lt;/a&gt; site. I explain here what the JAMstack is and why you should give it a try.&lt;/p&gt;

&lt;h2&gt;
  
  
  From static site to static site
&lt;/h2&gt;

&lt;p&gt;There have been great periods in the world of the web. The first of these is that of the static site. It wasn't called that at the time. It was a site made up entirely of static files: we wrote the structure in HTML, the design in CSS, we potentially added a little animation with JavaScript, and we stored all this on a server which was content to serve the files at the time requested by the visitor.&lt;/p&gt;

&lt;p&gt;Basic. Simple.&lt;/p&gt;

&lt;p&gt;But, very quickly, there were limits. It was finally quite complicated to maintain. &lt;strong&gt;To modify a site, it was necessary to touch the code.&lt;/strong&gt; And, annoyingly, the site never changed without developer intervention.&lt;/p&gt;

&lt;p&gt;In itself, the static site is fine for displaying documentation, but it is impossible to build something advanced with it.&lt;/p&gt;

&lt;p&gt;The world of the web has therefore moved on to a second period, that of the dynamic site. It was a big upheaval. Thanks to technologies like PHP, Java, etc., the server was no longer going to just serve the same page forever. These languages make it possible to &lt;strong&gt;generate a new page as soon as a visitor requests it&lt;/strong&gt; thanks to data stored in databases.&lt;/p&gt;

&lt;p&gt;It changed a lot of things. For the first time, people were starting to code smart and useful applications. From the blog to the e-commerce site, everything has been made possible thanks to dynamic sites. Once the site was coded and deployed, &lt;del&gt;Muggles&lt;/del&gt; non-developer could modify the content without help from the developers.&lt;/p&gt;

&lt;p&gt;Unfortunately, these sites have grown to be cumbersome and slow. Each time the visitor reloaded the page, it was completely rebuilt on the server before being sent. Servers having access to more and more content and services, and doing more and more processing, the increase in loading times could become exponential.&lt;/p&gt;

&lt;p&gt;We move on to the third great period of the web universe: dynamic interactive websites. The idea behind this barbaric name is to &lt;strong&gt;no longer be forced to generate a page entirely to obtain information,&lt;/strong&gt; and to no longer be forced to reload a page completely to update the information it contains.&lt;/p&gt;

&lt;p&gt;The JavaScript language can update the DOM, but it can also request information directly from the server. If we combine these two capabilities, we get AJAX technology.&lt;/p&gt;

&lt;p&gt;This technology has helped to relieve the heaviness of dynamic sites by allowing &lt;strong&gt;a web page to be partially updated without having to reload it&lt;/strong&gt;. Dynamic sites had become even more dynamic!&lt;/p&gt;

&lt;p&gt;This led to the different technologies we know today, such as the Single Page Application. Server technologies stay on the server (PHP, etc.) and are used to respond to client requests. The display of the client is done directly in the browser thanks to client technologies (JavaScript and its frameworks). The two parties discuss together through APIs.&lt;/p&gt;

&lt;p&gt;With interactive dynamic websites, other problems have arisen. In particular, referencing, because the site being generated on the fly by JavaScript, it is impossible for a search engine to retrieve the content.&lt;/p&gt;

&lt;p&gt;To sum up, we have:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The static site:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ SEO friendly&lt;/li&gt;
&lt;li&gt;✅ very little resource-intensive&lt;/li&gt;
&lt;li&gt;✅ fast loading time&lt;/li&gt;
&lt;li&gt;🚫 requires knowledge of development to update the site&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The dynamic site:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ SEO friendly&lt;/li&gt;
&lt;li&gt;🚫 slow loading time&lt;/li&gt;
&lt;li&gt;✅ no development skills needed to update the site&lt;/li&gt;
&lt;li&gt;🚫 resource intensive&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The interactive dynamic site:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🚫 not SEO friendly&lt;/li&gt;
&lt;li&gt;✅ loading time (average) faster than the dynamic site, but &lt;strong&gt;🚫 slower than a static site&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;✅ no development skills required to update the site&lt;/li&gt;
&lt;li&gt;✅ less resource intensive (average) than a dynamic site, but &lt;strong&gt;🚫 more than a static site&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is clear that the static site retains, despite its simplicity, many advantages for him. Of course, this summary is not true in all situations. It's oversimplified and generalized for the purposes of this article, but you get the idea.&lt;/p&gt;

&lt;p&gt;Still, the advantages of the static site have pushed part of the web community to find another solution to these disadvantages than going through dynamic sites. They chose to generate the web pages before deployment instead of doing it at request time like dynamic sites do.&lt;/p&gt;

&lt;p&gt;This technology is called the Static Site Generator. The idea is to decouple the data from the site code itself. The static site generator is therefore based on data (often Markdown, text files) to generate a site that will ultimately be entirely static. No need to know how to code to modify the content of a static site while enjoying all its advantages.&lt;/p&gt;

&lt;h2&gt;
  
  
  The patchwork of the best of the web
&lt;/h2&gt;

&lt;p&gt;Of course, the world didn't stand still while we focused on static and dynamic sites. Many things have happened. Technologies have emerged. They have evolved. And some died.&lt;/p&gt;

&lt;p&gt;Why are we talking about this? Because the JAMstack is actually a patchwork of many technologies working together. That's why “stack” in the name. Let's talk a bit about these technologies.&lt;/p&gt;

&lt;h3&gt;
  
  
  The elements that make up the JAMstack
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Web APIs.&lt;/strong&gt; We already talked about it a bit above. They became essential when we started to want to make machines to discuss between them and later separate the frontend from the backend. They are therefore used to communicate. Many standards exist. The most widely used today is REST, which is based on the operation of the HTTP protocol.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CMSs&lt;/strong&gt;. I am talking here about &lt;strong&gt;Content Management Systems&lt;/strong&gt; in the broadest sense. Just a system that allows you to manage content whether it's text, products or something else. They have the advantage of being specialized, of simplifying content management, of being known to their niche users and often of offering tools specific to their audience. For example, an e-commerce CMS will know how to manage a product and its variants, taxes on it, currency conversion, delivery conditions, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Continuous integration and deployment pipelines,&lt;/strong&gt; also known as CI/CD, have been making a lot of noise. They are part of the &lt;em&gt;Architecture as Code&lt;/em&gt; movement. They allow to describe build, test, and deployment processes of a project that can be played and replayed as much as necessary. They have many advantages and uses, but we won't dwell on them here. What should be remembered is that they allow you to automate the different steps that we have just listed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend frameworks&lt;/strong&gt; have simplified development by taking care of a lot of repetitive tasks for developers. They have helped make the development of more complex sites possible. These are also the frameworks that brought to the frontend a form of stability that already existed at the backend. They have improved website performance by optimizing rendering and display tasks. Last advantage, they make the site more dynamic since it runs directly in the user's browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Static site generators.&lt;/strong&gt; As we explained above, these are tools that will generate a complete static website from an external data source in one build step.&lt;/p&gt;

&lt;h3&gt;
  
  
  JAMstack: a CI/CD pipeline rather than a new technology
&lt;/h3&gt;

&lt;p&gt;I think you see where I'm coming from. People had the wonderful idea of putting all these technologies together to solve most of the problems listed at the beginning of the article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o7Mt0Rm5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2021/07/schema-jamstack.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o7Mt0Rm5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2021/07/schema-jamstack.png" alt="What is the JAMstack and why should you use it?" width="800" height="349"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Diagram of a JAMstack architecture&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are two ways to update our site:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;edit website code (for &lt;a href="https://travel-and-food.com/"&gt;travel-and-food.com&lt;/a&gt; everything is on GitHub)&lt;/li&gt;
&lt;li&gt;edit site data from the CMS (for &lt;a href="https://travel-and-food.com/"&gt;travel-and-food.com&lt;/a&gt;, I used the &lt;a href="https://ghost.org?via=gj8uj"&gt;Ghost&lt;/a&gt; CMS)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These two systems are linked to a continuous integration platform. All software forges have their own version these days (&lt;a href="https://github.com/features/actions"&gt;GitHub Actions&lt;/a&gt;, &lt;a href="https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/"&gt;GitLab CI&lt;/a&gt;, &lt;a href="https://bitbucket.org/product/features/pipelines"&gt;Bitbucket Pipelines&lt;/a&gt;, etc.) but there are independent ones like &lt;a href="https://www.netlify.com"&gt;Netlify&lt;/a&gt; or &lt;a href="https://www.jenkins.io/doc/book/pipeline/"&gt;Jenkins Pipeline&lt;/a&gt;. Travel &amp;amp; Food uses Netlify, which is also its host.&lt;/p&gt;

&lt;p&gt;It is the CI/CD platform that will then, as a conductor, take care of all the rest of the process. The CI/CD will therefore run the build of the static site generator. For Travel &amp;amp; Food, I decided to use &lt;a href="https://www.gatsbyjs.com"&gt;GatsbyJS&lt;/a&gt; as generator. Pendant son build, GatsbyJS connects to Ghost (the CMS) to retrieve the data and loop over it to generate each page of the website.&lt;/p&gt;

&lt;p&gt;The static site generator produces a folder containing an HTML file for each page of the site as well as JavaScript and styles. When the build is complete, the CI/CD sends this folder as is to the host.&lt;/p&gt;

&lt;p&gt;There is no longer any process that then runs at the host level. Since the site consists of static files, they are served as is when a visitor requests them. No modification or other processing is performed on the files. As a result, we have a huge gain in performance. This also affects SEO and the cost of the project.&lt;/p&gt;

&lt;p&gt;When the JavaScript is loaded on the user side, the site “comes to life”, the frontend frameworks take over. We don't have to have non-interactive pages just because it's a static site. Thanks to the JAMstack this is no longer the case.&lt;/p&gt;

&lt;p&gt;As frontend frameworks such as ReactJS or Angular support Server Side Rendering (SSR) techniques, &lt;strong&gt;a fully static first version of the JavaScript application is available in HTML even before the JavaScript is loaded&lt;/strong&gt;. Which means that the pure performance as well as the SEO of the site would be better compared to the same site without SSR.&lt;/p&gt;

&lt;h2&gt;
  
  
  The advantages of the JAMstack
&lt;/h2&gt;

&lt;p&gt;Let's go back to our pros/cons list for the JAMstack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ as SEO friendly as a static site&lt;/li&gt;
&lt;li&gt;✅ as fast as a static site&lt;/li&gt;
&lt;li&gt;✅ no development skills required to update the site since we use a CMS (or several CMS)&lt;/li&gt;
&lt;li&gt;✅ very little resource-intensive&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We fill in every point on our comparison list. The JAMstack can have yet another benefit – and we'll end on this – and that is to improve team cohesion!&lt;/p&gt;

&lt;p&gt;I'm barely kidding. If you think about it, the content creator is happy because he uses his favorite CMS, the developer is happy because he can use his favorite technology and the marketing manager is happy because the site has good SEO performance.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>continousintegration</category>
      <category>staticwebsite</category>
    </item>
    <item>
      <title>Trip to Lisbon for Web Summit 2022</title>
      <dc:creator>Nathanaël CHERRIER</dc:creator>
      <pubDate>Wed, 09 Nov 2022 05:00:31 +0000</pubDate>
      <link>https://forem.com/mindsers/trip-to-lisbon-for-web-summit-2022-55bo</link>
      <guid>https://forem.com/mindsers/trip-to-lisbon-for-web-summit-2022-55bo</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1h3OQrb5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.unsplash.com/photo-1605641532626-5ab1dab56350%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDV8fGxpc2JvYXxlbnwwfHx8fDE2NjcyMDAyNTA%26ixlib%3Drb-4.0.3%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1h3OQrb5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.unsplash.com/photo-1605641532626-5ab1dab56350%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDV8fGxpc2JvYXxlbnwwfHx8fDE2NjcyMDAyNTA%26ixlib%3Drb-4.0.3%26q%3D80%26w%3D2000" alt="Trip to Lisbon for Web Summit 2022" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is only the third event I attend since COVID-19. Still feels weird to meet so many other people at the same time. For the Web Summit 2022 it is around 71 000 people meeting to learn from awesome speakers. In this post, I'll make a full summary of my trip including thoughts about the talks and other useful information about the places, the city, the organization, etc. Will be similar from &lt;a href="https://mindsers.blog/post/first-conf-of-the-year-git-merge-2019/"&gt;what I did for the Git Merge in 2019&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Table of Content
&lt;/h4&gt;



&lt;p&gt;How was the event?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;From open source to Unicorn: How to build on a project&lt;/li&gt;
&lt;li&gt;How do we tackle software's crisis of trust?&lt;/li&gt;
&lt;li&gt;Bad data is eating your time&lt;/li&gt;
&lt;li&gt;Fundraising for developers: How are technical companies doing right now?&lt;/li&gt;
&lt;li&gt;The good, the bad and the automated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lisbon is a wonderful city&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where I stayed during the conference&lt;/li&gt;
&lt;li&gt;A grasp of the city&lt;/li&gt;
&lt;li&gt;
How was the venue for the Web Summit?
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;&lt;em&gt;⚠️ Read more of my blog posts about tech and business &lt;a href="https://mindsers.blog/"&gt;on my personal blog&lt;/a&gt;! ⚠️&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How was the event?
&lt;/h2&gt;

&lt;p&gt;This event, as expected, was really great. It is not surprising that so many people travelled there from so many countries. The organization was great, and I learned a lot from all talks I managed to watch.&lt;/p&gt;

&lt;p&gt;I'll tell you about all the other aspects of this event later in the post, but for now, I want to share with you my notes from the talks. Keep reading.&lt;/p&gt;

&lt;h3&gt;
  
  
  From open source to Unicorn: How to build on a project
&lt;/h3&gt;

&lt;p&gt;🧑‍🏫&lt;/p&gt;

&lt;p&gt;Speaker: Milin Desai (Sentry), Tim Crino (Inc. Magazine)&lt;/p&gt;

&lt;p&gt;As any other businesses, open source needs to make money. The goal of any companies is to make money. So, even if the company is based on an open-source project, it needs a strong business model to succeed.&lt;/p&gt;

&lt;p&gt;Most companies choose to have an open source core model. This means they provide the core software as open, but implement some features only for premium customers on their SaaS platform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sentry.io/"&gt;Sentry&lt;/a&gt; decided to go another way: they provide the complete software as open source. They make money by providing a no-brainer hosting service.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the customers see the value of your product they are gonna pay for it&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sentry did try to sell premium features like other companies, but they decided to move back on this decision because they felt that paid customer were biasing how they built their product.&lt;/p&gt;

&lt;p&gt;Sentry thinks that making the product open source has allowed a strong community to be built around it. That community has helped a lot to build Sentry in many ways. For the company to not feel fake in this community, Sentry is giving back a lot to the open source. They sponsor the best contributors and developers who build tools they use internally. They encourage their employees to contribute to the open source.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do we tackle software's crisis of trust?
&lt;/h3&gt;

&lt;p&gt;🧑‍🏫&lt;/p&gt;

&lt;p&gt;Speakers: Amanda Malko (G2), Tim Crino (Inc. Magazine)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7H9GHtmW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7882-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7H9GHtmW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7882-1.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Users do not trust software programs (and most likely the companies behind them) anymore. Studies show that users will trust more other customers reviews than marketing and information provided by the company via its website or a salesperson.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;60% of people say they will contact a salesperson only after asking their pairs some insight. They often already decided to buy when they call the salesperson.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Two great options to rebuild trust today are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building a community around the brand or the product. If people are looking for pairs' review before deciding to buy, why not facilitate that?&lt;/li&gt;
&lt;li&gt;Being transparent and clear about data privacy. Users need clear communication about what data need to be used and what they'll get in exchange for giving their data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Users want to know if they can trust what they see on a website. Twitter/Musk example is a good example of that it is hard to build trust, but is easy to lose trust.&lt;/p&gt;

&lt;p&gt;Two key learnings from Twitter/Musk example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Human moderation is still essential for the user to build trust&lt;/li&gt;
&lt;li&gt;UX is definitely part of the best practices to build trust. This includes feedback loops where users will give feedbacks to companies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bad data is eating your time
&lt;/h3&gt;

&lt;p&gt;🧑‍🏫&lt;/p&gt;

&lt;p&gt;Speakers: Barr Moses (Monte Carlo), Jennifer Strong (MIT Technology)&lt;/p&gt;

&lt;p&gt;Data is becoming unprecedentedly important for the companies and societies using them. We never saw companies investing that much money into data and data-driven organizations before now!&lt;/p&gt;

&lt;p&gt;But unfortunately, Barr Moses saw many data-driven companies failing because they couldn't really trust the data they were using. For instance, a big insurance company applied bad credit scores because of the data they used. This resulted in millions of people that lost access to mortgage, and other important contract in the life of an individual, etc. That's why Barr Moses founded &lt;a href="https://www.montecarlodata.com/"&gt;Monte Carlo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;She knows the developer/engineering ecosystem. For decades, we have had plenty of tools and automations to help us monitor that things are still working correctly in our systems.&lt;/p&gt;

&lt;p&gt;Data are created, updated and transit through those systems, but data analysts do not have the same tools as DevOps to monitor if the data are still correct at any point of time.&lt;/p&gt;

&lt;p&gt;The industry needs to understand that having tools to monitor the system that use the data is great, but we lack automated tools to monitor the data in themselves.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fundraising for developers: How are technical companies doing right now?
&lt;/h3&gt;

&lt;p&gt;🧑‍🏫&lt;/p&gt;

&lt;p&gt;Speakers: Max Howell (tea), Rashmi Gopinath (B Capital Group), Eamon Leonard (Broadstone)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PnB2iQiC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7881-2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PnB2iQiC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7881-2.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The talk used many examples of the open-source world, but most advice could be applied to any business model.&lt;/p&gt;

&lt;p&gt;Open source often drives better and more robust software. Plenty of people join forces to build something useful for the community. But it also empowers individuals:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're truly dedicated and really want to build something great, you'll find someone on the internet who will want to invest in it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's something the “tokenization and decentralization” world proved. No matter the project, you can find someone with whom it will resonate and who will want to put some penny in.&lt;/p&gt;

&lt;p&gt;Other pieces of advice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do not build a different product for users and for investors. You'll disappoint both.&lt;/li&gt;
&lt;li&gt;Do not try to take back your open-source features to make them a paid feature. The open-source community might be offended, and you'll lose users.&lt;/li&gt;
&lt;li&gt;Instead, think about enterprise feature like support, SSO, etc. that you can sell to companies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The good, the bad and the automated
&lt;/h3&gt;

&lt;p&gt;🧑‍🏫&lt;/p&gt;

&lt;p&gt;Speakers: Pam Murphy (Imperva), Adam Bluestein (Fast Company)&lt;/p&gt;

&lt;p&gt;There are not only human beings on the internet. There are also bots.&lt;/p&gt;

&lt;p&gt;Bots help us do a lot of different tasks that doesn't require human brain anymore. But there are good bots and bad bots. And the latter is a big issue of this decade.&lt;/p&gt;

&lt;p&gt;The talk tries to sensibilize us to the need to use bots management system to protect our software programs and websites.&lt;/p&gt;

&lt;p&gt;Two examples were used to help us understand how bad bots can impact businesses.&lt;/p&gt;

&lt;p&gt;First, the PS5 case: the demand for the console was so high that bad actors created scrapping bots to buy quickly most of the available stock on retailers' websites (before real customers). The goal for them was to sell overpriced console on other websites.&lt;/p&gt;

&lt;p&gt;Those bots created a lot of frustration for real customers. It ended up becoming a &lt;strong&gt;reputation issue&lt;/strong&gt; for Sony and the retailers, who didn't know how to differentiate human beings from bots.&lt;/p&gt;

&lt;p&gt;It also created a financial issue for the retailers. Since the price of the console is given by Sony, retailers do not make a lot of money if they sell a console. Most of their margins come from the additional sale of accessories. But bots don't buy accessories. So even though more PS5 were sold than other consoles, retailers made less money due to the lack of accessory sales.&lt;/p&gt;

&lt;p&gt;Second example: Twitter being bought by Elon Musk. Musk asked how many users of Twitter are actually bots. He asked for new investigation about this number of bots on the platform. Why was he that concerned by bots?&lt;/p&gt;

&lt;p&gt;Twitter doesn't make money by selling subscriptions, but by selling ads. What makes an advertiser choose Twitter instead of another social media is the amount of real users he can reach. In other words, the more there are bots on the platform, the fewer advertisers will spend money to show ads on Twitter.&lt;/p&gt;

&lt;p&gt;This leads to bad revenue or a decrease in the revenue stream. When you invest in a company, you want to make sure you'll be able to have the money back at some point. Hence, the Musk's questions and concerns.&lt;/p&gt;

&lt;p&gt;Long story short: bad bots are a real issue for companies and need to be fought.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lisbon is a wonderful city
&lt;/h2&gt;

&lt;p&gt;As I said, I never went to &lt;a href="https://fr.wikipedia.org/wiki/Lisbonne"&gt;Lisbon&lt;/a&gt; before. Everything was new to me, so I wanted to see the more I could. And that's what I did.&lt;/p&gt;

&lt;p&gt;I travelled with EasyJet (for the plane part) and SNCF (for the train part). I have to admit that this last-minute trip to the Web Summit 2022 was a bit hectic. I was so tired when I arrived in Lisbon… You can't imagine how happy I was to find my bed at the B&amp;amp;B!&lt;/p&gt;

&lt;p&gt;To summarize the trip, I did:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Châtellerault ⇒ Poitiers ⇒ Paris ⇒ Lisbonne&lt;/li&gt;
&lt;li&gt;Lisbonne ⇒ Paris ⇒ Châtellerault&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the airport I decided to use the shuttle service of my B&amp;amp;B hotel to avoid being too late for my check in (I landed at 22:45) but there is public transport service (subway and bus) that allow to commute directly from the airport to the city in approximately 45 mins. I used public transports the other days.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where I stayed during the conference
&lt;/h3&gt;

&lt;p&gt;I stayed at &lt;a href="https://www.booking.com/hotel/pt/lisbon-b-amp-b-lisboa.en.html?aid=7954669&amp;amp;checkin_monthday=2&amp;amp;checkin_month=11&amp;amp;checkin_year=2022&amp;amp;checkout_monthday=3&amp;amp;checkout_month=11&amp;amp;checkout_year=2022&amp;amp;no_rooms=1&amp;amp;group_adults=2"&gt;Asul B&amp;amp;B, a cozy Bed and Breakfast private room&lt;/a&gt;. It was perfect to rest before and after days of talks. The owners were very kind and welcoming.&lt;/p&gt;

&lt;p&gt;My plane landed late at night, so I used their shuttle service to commute from the airport to the B&amp;amp;B. Everything was great and well managed. Expensive if you compare to local transportation service, but you don't have to worry about ticket, directions, etc. Since it was late, I wanted things to be as simple as possible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.booking.com/hotel/pt/lisbon-b-amp-b-lisboa.en.html?aid=7954669&amp;amp;checkin_monthday=2&amp;amp;checkin_month=11&amp;amp;checkin_year=2022&amp;amp;checkout_monthday=3&amp;amp;checkout_month=11&amp;amp;checkout_year=2022&amp;amp;no_rooms=1&amp;amp;group_adults=2"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E-vMrz6---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/10/179089033.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;My private room at Asul B&amp;amp;B&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There was a shared kitchen in the B&amp;amp;B where everything was at the disposal of the customers. In the morning, someone was paid to prepare breakfast for everyone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.booking.com/hotel/pt/lisbon-b-amp-b-lisboa.en.html?aid=7954669&amp;amp;checkin_monthday=2&amp;amp;checkin_month=11&amp;amp;checkin_year=2022&amp;amp;checkout_monthday=3&amp;amp;checkout_month=11&amp;amp;checkout_year=2022&amp;amp;no_rooms=1&amp;amp;group_adults=2"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IQVbOH6z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/10/179089027.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The shared kitchen at Asul B&amp;amp;B&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As I said, it was a last-minute trip and the hotel's rooms prices were far too high and mostly fully booked. Looking at the other options available (not so many given the dates), I found this B&amp;amp;B. Even though I didn't have the full house for me, it was cheaper and comfy, clean and with everything I needed to have a good experience there.&lt;/p&gt;

&lt;p&gt;Unfortunately, I did not have a lot of time to visit the city. But on my way to and back from the venue, I took some pictures to give you a grasp of Lisbon.&lt;/p&gt;

&lt;h3&gt;
  
  
  A grasp of the city
&lt;/h3&gt;

&lt;p&gt;I would say it is definitely a beautiful city, but it was rainy during my trip. The weather doesn't give it justice on my pictures.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A2ijdh6x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7829-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A2ijdh6x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7829-1.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q7mRmDXH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7827-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q7mRmDXH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7827-1.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IWYpGpNn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7839-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IWYpGpNn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7839-1.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h_6kqtr2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7840.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h_6kqtr2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7840.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_5lJZicf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7837-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_5lJZicf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7837-1.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_4Rn-7fx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7835-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_4Rn-7fx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7835-1.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Saint Paul's place and some other places around&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It looks like a beautiful and old European city with some particularities: colors! You can see it on my pictures, most of the walls aren't only gray or white.&lt;/p&gt;

&lt;p&gt;One other specificity of the city (you can see it in Lisbon, but it is a Portugal thing) is the &lt;a href="https://en.wikipedia.org/wiki/Azulejo"&gt;Azulejos&lt;/a&gt;. It is like a terracotta tile covered with an opaque glazing. They used it a lot to cover and decorate walls.&lt;/p&gt;

&lt;p&gt;It is traditionally white and blue as you can see it on my first picture. But the modern Azulejos have more colors, like the one you can see below. It is exposed in Lisbon's subway station.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SF3hkwWL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7834.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SF3hkwWL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7834.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r4PX-Kpi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7892-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r4PX-Kpi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7892-1.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ru822zKq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7893-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ru822zKq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7893-1.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jYw5nmKt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7890-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jYw5nmKt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7890-1.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some of the things that must be seen in Lisbon are part of the public transport service of the city. They have the “carris”, which is a nice vintage tramway and many piece of art through the subway station.&lt;/p&gt;

&lt;h3&gt;
  
  
  How was the venue for the Web Summit?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://arena.altice.pt/en"&gt;The venue was one of the biggest&lt;/a&gt; I ever saw for a tech conference. It is impressive to see that many people at the same place and a place that can hold them all.&lt;/p&gt;

&lt;p&gt;Many actors of the tech industry were here, including some of the brand new “web3 side of the internet” actors like &lt;a href="https://polkadot.network"&gt;Polkadot&lt;/a&gt; or &lt;a href="https://filecoin.io"&gt;Filecoin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YJYmFlaL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7863.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YJYmFlaL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7863.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zVmztdaR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7888.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zVmztdaR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7888.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--29hMx9Fo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7887.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--29hMx9Fo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7887.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O0KQO9_K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7878.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O0KQO9_K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7878.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The web3 and the metaverse was really a strong topic based on the amount of stand and experience dedicated to that topic.&lt;/p&gt;

&lt;p&gt;There wasn't only web3 company represented, fortunately! Truth is there were so many stands and talk stages, lounges, etc. that it made navigation a bit complicated.&lt;/p&gt;

&lt;p&gt;👍&lt;/p&gt;

&lt;p&gt;I would also mention the good quality of the &lt;a href="https://websummit.com/app"&gt;Web Summit mobile application&lt;/a&gt;, which really helped me navigation through the 5 pavilions and 71k people… Usually, the conference's apps are awful, but this one is great, so I thought it was worth a mention here.&lt;/p&gt;

&lt;p&gt;Let's talk about food now. Food is always a big topic during conferences. There are always discussions about food quality, food quantity and the organization of the lunchtime. Bad organization of the lunch can ruin all the conference from an attendant perspective.&lt;/p&gt;

&lt;p&gt;On quantity, Web Summit couldn't make more. There were food trucks and stands everywhere: between each pavilion and around them. This made things easier for attendants to find something to eat without waiting hours in queue.&lt;/p&gt;

&lt;p&gt;Food quality was also great at Web Summit. I ate a delicious burger with good quality meat + a coke.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uGxZ2qc4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_6104.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uGxZ2qc4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_6104.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IX2nMmxb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7885-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IX2nMmxb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/11/IMG_7885-1.jpg" alt="Trip to Lisbon for Web Summit 2022" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My burger for lunch + the free snacks of the developer lounge&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One thing to note though, it is the first time for me that the lunch meal isn't included in the price of the conference (more than 900 euros per person). I went to countless conferences before, they were all way less expensive, but I never paid for my lunch meal during those.&lt;/p&gt;

&lt;p&gt;I'm not saying we should or not pay for lunch at conferences. I'm just stating facts here, so you know.&lt;/p&gt;

&lt;p&gt;That being said, in the developer lounge, local snacks and coffee were free. I guess it was the same in other lounges too.&lt;/p&gt;




&lt;p&gt;Now you know everything about the Web Summit 2022! I truly hope this post will help you if you plan to attend Web Summit in Lisbon in the coming years. Or maybe it already helped you decide whether you want to attend or not.&lt;/p&gt;

</description>
      <category>conferences</category>
      <category>devlife</category>
      <category>devtravel</category>
      <category>websummit</category>
    </item>
    <item>
      <title>How to unindex committed files</title>
      <dc:creator>Nathanaël CHERRIER</dc:creator>
      <pubDate>Wed, 02 Nov 2022 05:00:15 +0000</pubDate>
      <link>https://forem.com/mindsers/how-to-unindex-committed-files-3110</link>
      <guid>https://forem.com/mindsers/how-to-unindex-committed-files-3110</guid>
      <description>&lt;p&gt;Git is a powerful tool that can seem complicated if we know it badly. In this article, we will see the particular case of bad indexing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;⚠️ Read more of my blog posts about tech and business &lt;a href="https://mindsers.blog/"&gt;on my personal blog&lt;/a&gt;! ⚠️&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a case that can very easily occur when the tool is poorly mastered, but don't panic, there is nothing irreparable. You can make mistakes, correct yourself, start over and learn at your own pace with the trick in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid indexing bad files
&lt;/h2&gt;

&lt;p&gt;There are files we would rather not version with Git. For example, project dependencies (the &lt;code&gt;node_modules&lt;/code&gt; directory for a Node.js project), files containing environment variables, or other autogenerated/temporary files.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.gitignore&lt;/code&gt; file allows us to specify to Git the list of files that we do not want it to consider. Create it at the root of your project.&lt;/p&gt;

&lt;p&gt;You can specify files, folders or globs there like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.env
/node_modules
npm-debug.log*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once added to this list, the offending files will be invisible to Git. There will no longer be any way to add them accidentally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Delete file from index
&lt;/h2&gt;

&lt;p&gt;But sometimes we realize that a file should not be indexed only after committing it. An unfortunate &lt;code&gt;git add .&lt;/code&gt; or &lt;strong&gt;not&lt;/strong&gt;  &lt;strong&gt;using&lt;/strong&gt; &lt;code&gt;git status&lt;/code&gt; regularly enough can easily lead to this situation.&lt;/p&gt;

&lt;p&gt;If this happens, a simple command exists: &lt;code&gt;git rm&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git rm -r --cached name_of_your_file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you just have to commit the deletion of the index:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add name_of_your_file
git commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voilà. The unwanted folder or file should no longer bother you. On the other hand, remember to add it to your &lt;code&gt;.gitignore&lt;/code&gt; file so as not to commit it mistakenly again. I refer you to the first part of the article to know how to do it.&lt;/p&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>7 ways to make money as a developer</title>
      <dc:creator>Nathanaël CHERRIER</dc:creator>
      <pubDate>Wed, 26 Oct 2022 04:00:06 +0000</pubDate>
      <link>https://forem.com/mindsers/7-ways-to-make-money-as-a-developer-306h</link>
      <guid>https://forem.com/mindsers/7-ways-to-make-money-as-a-developer-306h</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KMNCFTv---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.unsplash.com/photo-1550565118-3a14e8d0386f%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDE5fHxtb25leXxlbnwwfHx8fDE2NjY1MzM0NDk%26ixlib%3Drb-4.0.3%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KMNCFTv---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.unsplash.com/photo-1550565118-3a14e8d0386f%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDE5fHxtb25leXxlbnwwfHx8fDE2NjY1MzM0NDk%26ixlib%3Drb-4.0.3%26q%3D80%26w%3D2000" alt="7 ways to make money as a developer" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Knowing how to code is a definite advantage in our modern life. Of course, one of the perks that most people care about when I talk about it is money. It's no secret that coding can pay off big. Let's talk about it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;⚠️ Read more of my blog posts about tech and business &lt;a href="https://mindsers.blog/"&gt;on my personal blog&lt;/a&gt;! ⚠️&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;How to make money when you know how to code? The easiest way is to get hired as a developer. It's easy because the market is in high demand for this type of profile. And, you know the law of supply and demand.&lt;/p&gt;

&lt;p&gt;So, if you want job security and don't mind working for a supervisor, go for the full-time employee option. It’s paying well right now (supply and demand still).&lt;/p&gt;

&lt;p&gt;But, since most of my readers are developers, they already know that you can earn money as a permanent developer. So, I imagine the question that I often receive must be understood: how to earn money other than by working a 9 a.m. to 5 p.m. for a boss when you are a developer? Or how to earn money in addition to your full-time job when you know how to code?&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Become a freelancer
&lt;/h2&gt;

&lt;p&gt;Becoming a freelance means setting up your own company and invoicing your clients directly, instead of letting a boss do it and take the bulk of the figure for him.&lt;/p&gt;

&lt;p&gt;Well, freelancing can take many forms for a developer. It can be very similar to the employee experience: working at the client's premises to reinforce a development team that the client has formed himself. Finally, only the contract changes (and potentially the salary too) but that changes little of the employee situation and this activity will require a full time. Impossible to do it while being an employee of another company.&lt;/p&gt;

&lt;p&gt;However, the freelancer can decide to break away from the employee model by not charging for hours, but for services. For example, coding and selling websites for companies that need them. And, instead of billing monthly for the hours you spent on the project, sell the project itself as a development service. This way the customer is not buying a person (or a person's time) but a service provided by a company, regardless of which human being provides that service, etc.&lt;/p&gt;

&lt;p&gt;A small showcase site that cost 5,000 euros can easily be coded on evenings and weekends. You can also get organized with other freelancers to take advantage of each other's strengths / expertise and form your own team of people you want to work with.&lt;/p&gt;

&lt;p&gt;It is also possible to step in for a specific functionality on a client's project. This is often called firefighter mode. In this case, the client typically wants you to work fast and well. It pays off.&lt;/p&gt;

&lt;p&gt;If, despite the similarities with salaried work, you want to start freelancing, look here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The marketplace for digital freelancers: &lt;a href="https://www.freelancer.com"&gt;www.freelancer.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The Ghost CMS Expert Catalog: &lt;a href="https://ghost.org/experts/?via=gj8uj"&gt;Ghost Experts&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Sell themes for CMS
&lt;/h2&gt;

&lt;p&gt;If you like the frontend development and want to go for the product approach rather than the service approach, you can develop and sell themes for WordPress, or for Ghost, or for any other CMS.&lt;/p&gt;

&lt;p&gt;The good thing about the product approach is that the sale is repeatable. Once the theme is developed, you can sell it to 10,000 people, it won't cost you more time or energy. On the other hand, a product generally sells for less than a service.&lt;/p&gt;

&lt;p&gt;Another advantage of themes for CMS: you can go at your own pace, there is no client deadline to respect. You occupy your evenings and weekends as you see fit.&lt;/p&gt;

&lt;p&gt;Some useful links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One of the best-known theme shops: &lt;a href="https://themeforest.net/"&gt;Themeforest&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://shopify.dev/themes"&gt;Shopify theme documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ghost.org/marketplace/?via=gj8uj"&gt;Ghost Theme Marketplace&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Sell plugins for CMS
&lt;/h2&gt;

&lt;p&gt;If you don't like the frontend development, CMS still has plenty to keep you busy. Instead of coding themes, why not code plugins that will improve the experience of users of these CMS. Most CMS / platform allow you to sell the plugins you develop in one-time or subscription.&lt;/p&gt;

&lt;p&gt;For example, many developers offer apps for the Shopify platform and live off the revenue generated!&lt;/p&gt;

&lt;p&gt;To know more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://shopify.dev/apps"&gt;Shopify Apps Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wordpress.com/plugins"&gt;WordPress Plugin Marketplace&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Code a SaaS application
&lt;/h2&gt;

&lt;p&gt;This option is a level above the creation of plugins for CMS. You remain in the creation of utility tools, but you are completely independent of a specific platform.&lt;/p&gt;

&lt;p&gt;A well-coded project can then bring you regular income without requiring a lot of time on your part. Even if there will be maintenance, it will not necessarily be useful to add a 1001 new features every four mornings.&lt;/p&gt;

&lt;p&gt;Another thing: creating a SaaS application is fun. It is a side project that you will surely have a lot of fun coding. Will you be the next Netflix or the next Stripe?&lt;/p&gt;

&lt;p&gt;I advise you to read &lt;a href="https://monicalent.com/"&gt;Monica Lent's blog&lt;/a&gt; to continue learning more about the subject. She lives from her SaaS tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Start a blog
&lt;/h2&gt;

&lt;p&gt;If you like to talk about your knowledge and share it, launch your blog! It's a great hobby, and you'll meet plenty of exciting people.&lt;/p&gt;

&lt;p&gt;There are many ways to monetize a blog:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;advertisement&lt;/li&gt;
&lt;li&gt;paid content&lt;/li&gt;
&lt;li&gt;affiliate marketing&lt;/li&gt;
&lt;li&gt;guest posting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Moreover, you will build an audience. And, an audience is the basis for launching many other businesses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sale of t-shirt for developers&lt;/li&gt;
&lt;li&gt;sale of courses and trainings&lt;/li&gt;
&lt;li&gt;influencer marketing (it started on blogs, not social media).&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, I'm not going to lie to you, blogging is a long-term investment. It will be almost impossible to make money from the first month of writing. But in the long run, a blog can pay off big and long.&lt;/p&gt;

&lt;p&gt;Last advantage for the blog: it allows you to be independent of other web players and to sustain the income streams that you have managed to put in place.&lt;/p&gt;

&lt;p&gt;To read to dig deeper into the subject:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An article I wrote for Welcome to the Jungle on this topic: &lt;a href="https://www.welcometothejungle.com/fr/collections/behind-the-code/career-hacking/articles/successful-personal-blog-developer"&gt;How to Create a Personal Blog as a Developer&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://ghost.org/resources/?via=gj8uj"&gt;blogging resource library&lt;/a&gt; from the Ghost team. These articles are excellent and very formative.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Sell courses
&lt;/h2&gt;

&lt;p&gt;We've already talked about it a bit, but a developer can also teach others to code. It is of course easier when we already have an audience that gives us credit. However, it is quite possible to sell courses online without having an audience beforehand.&lt;/p&gt;

&lt;p&gt;For this, think of platforms like Pluralsight, tuto.com, Khan Academy, Linkedin Learning, Udemy, etc. These are video training platforms that have allowed hundreds of trainers (including developers) to experience the training they created.&lt;/p&gt;

&lt;p&gt;The training can also take the form of an e-book or a book. And, even, a website that you would have created for the occasion.&lt;/p&gt;

&lt;p&gt;If you would rather not depend on one platform to sell your training/book, and you already have an audience, read on.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Launch an e-commerce site
&lt;/h2&gt;

&lt;p&gt;Why not actually sell products? You can create hundreds of objects about the world of code and development. Then you can sell them on your own online store.&lt;/p&gt;

&lt;p&gt;On your store, you can also sell books, cheat sheets, or other training materials.&lt;/p&gt;

&lt;p&gt;In fact, an e-commerce site potentially complements many of the options we discussed above. You can, for example, sell your WordPress themes directly on your own store!&lt;/p&gt;

&lt;p&gt;On the other hand, the shop will surely be the least technical option of all. If you like to be dirty, apart from coding your store yourself, launching an e-commerce site is not the best idea.&lt;/p&gt;

&lt;p&gt;Some tools to help you set up your e-commerce site:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.shopify.com"&gt;https://www.shopify.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://woocommerce.com"&gt;https://woocommerce.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.prestashop.com"&gt;https://www.prestashop.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;These are not all the ways to make money as a developer, there are surely many more. On the other hand, these are the first seven that have come to mind and which seem to me to be relatively easily achievable.&lt;/p&gt;

&lt;p&gt;I also noticed that I had already tested several of these activities and that I have good memories of them. In any case, I hope that you will find what you are looking for in this list, whether you want to increase, replace or diversify your sources of income. Good luck!&lt;/p&gt;

</description>
      <category>money</category>
      <category>business</category>
    </item>
    <item>
      <title>Understand recursive functions</title>
      <dc:creator>Nathanaël CHERRIER</dc:creator>
      <pubDate>Wed, 12 Oct 2022 04:00:57 +0000</pubDate>
      <link>https://forem.com/mindsers/understand-recursive-functions-3mjf</link>
      <guid>https://forem.com/mindsers/understand-recursive-functions-3mjf</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RdHKngT_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/10/IMG_1463-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RdHKngT_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/10/IMG_1463-1.jpg" alt="Understand recursive functions" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recursive functions are one of my favorite development techniques. It's not a complicated thing. On the contrary, they are only functions used differently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;⚠️ Read more of my blog posts about tech and business &lt;a href="https://mindsers.blog/"&gt;on my personal blog&lt;/a&gt;! ⚠️&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When we learn recursion, and more broadly, iteration in programming, we always stop at the classic iteration structures, loops. But they do not have a monopoly on iteration! In this article, I'll quickly tell you about another recursion structure.&lt;/p&gt;

&lt;p&gt;😅&lt;/p&gt;

&lt;p&gt;I thought for a long time that I wrote an article here on recursive functions. I discovered today that this is not the case, so I corrected that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recursion and loops
&lt;/h2&gt;

&lt;p&gt;When we talk about recursion or iteration, we are usually talking about repeating things. In computing, it is the ability to repeat a defined quantity of instructions.&lt;/p&gt;

&lt;p&gt;As we said, the classic way is to use loops for this. Programming languages generally offer several types of loops:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;while&lt;/code&gt; loops&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;do...while&lt;/code&gt; loops&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;for&lt;/code&gt; loops&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But, there are still others. In JavaScript, for example, we can add these to the list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;for...in&lt;/code&gt; loops&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;for...of&lt;/code&gt; loops&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Generally, the loops added by the languages, in addition to the first three, are ultimately only specific variations of the first three loops.&lt;/p&gt;

&lt;p&gt;I'm not going to explain loops to you here. They could be the subject of an article on their own. What must be remembered here is that loops are iterative structures offered by a language to allow a set of instructions to be repeated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const list = ['one', 'two', 'three']

for(const element of list) {
  // everything between the two braces 
  // will be repeated as many times as 
  // there are elements in list
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Example of loop in JavaScript&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Recursion and functions
&lt;/h2&gt;

&lt;p&gt;Unlike loops, functions are not iterative structures as such. They make it possible to separate a sequence of instructions from the rest of the code in order to be able to execute them again later, on demand.&lt;/p&gt;

&lt;p&gt;This last sentence looks a bit like an iterative structure, but here are the main differences that can be noted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A defined function may be called only once, or even never.&lt;/li&gt;
&lt;li&gt;If there is repetition (execution several times), it will be neither immediate nor linear unlike a loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A function is therefore not an iterative structure provided by the language. What will make a function recursive, and therefore allow iteration, is the use that the developer will make of it.&lt;/p&gt;

&lt;p&gt;Let's see how to make a function recursive.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function addOne(base, times = 1) {
    let result = base

    for (let i = 0; i &amp;lt; times; i++) {
        result += 1
    }

    return result
}

addOne(5, 3) // === 8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Function that uses iteration through a loop&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This function is not recursive. It adds &lt;code&gt;1&lt;/code&gt; to a number given as a parameter as many times as specified by the &lt;code&gt;times&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;How to do now, to have the same result without the loops?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function addOne(base, times = 1) {
    if (times &amp;lt;= 0) return base

    const result = base + 1
    return addOne(result, times - 1) // everything happens here
}

addOne(5, 3) // === 8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Function that uses iteration through recursion&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The recursive function does not change signature. It always takes the &lt;code&gt;base&lt;/code&gt; and &lt;code&gt;times&lt;/code&gt; variables as parameters. It always returns a number.&lt;/p&gt;

&lt;p&gt;What changes here: &lt;strong&gt;the function calls itself&lt;/strong&gt;. That's all.&lt;/p&gt;

&lt;p&gt;Let's go through the steps again with the parameters &lt;code&gt;base=5&lt;/code&gt; and &lt;code&gt;times=3&lt;/code&gt; to understand:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is &lt;code&gt;times&lt;/code&gt; less than or equal to &lt;code&gt;0&lt;/code&gt;? No, it is equal to &lt;code&gt;3&lt;/code&gt;, we continue.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;result&lt;/code&gt; is equal to &lt;code&gt;base&lt;/code&gt; plus &lt;code&gt;1&lt;/code&gt;, i.e. &lt;code&gt;5 + 1&lt;/code&gt;, i.e. &lt;code&gt;6&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We pass the &lt;code&gt;result&lt;/code&gt; and &lt;code&gt;times - 1&lt;/code&gt; to the &lt;code&gt;addOne&lt;/code&gt; function and we will directly return its return value when done.&lt;/li&gt;
&lt;li&gt;Is &lt;code&gt;times&lt;/code&gt; less than or equal to &lt;code&gt;0&lt;/code&gt;? No, it is equal to &lt;code&gt;2&lt;/code&gt;, we continue.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;result&lt;/code&gt; is equal to &lt;code&gt;base&lt;/code&gt; plus &lt;code&gt;1&lt;/code&gt;, i.e. &lt;code&gt;6 + 1&lt;/code&gt;, i.e. &lt;code&gt;7&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We pass the &lt;code&gt;result&lt;/code&gt; and &lt;code&gt;times - 1&lt;/code&gt; to the &lt;code&gt;addOne&lt;/code&gt; function and we will directly return its return value when done.&lt;/li&gt;
&lt;li&gt;Is &lt;code&gt;times&lt;/code&gt; less than or equal to &lt;code&gt;0&lt;/code&gt;? No, it is equal to &lt;code&gt;1&lt;/code&gt;, we continue.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;result&lt;/code&gt; is equal to &lt;code&gt;base&lt;/code&gt; plus &lt;code&gt;1&lt;/code&gt;, i.e. &lt;code&gt;7 + 1&lt;/code&gt;, i.e. &lt;code&gt;8&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We pass the &lt;code&gt;result&lt;/code&gt; and &lt;code&gt;times - 1&lt;/code&gt; to the &lt;code&gt;addOne&lt;/code&gt; function and we will directly return its return value when done.&lt;/li&gt;
&lt;li&gt;Is &lt;code&gt;times&lt;/code&gt; less than or equal to &lt;code&gt;0&lt;/code&gt;? Yes, we return &lt;code&gt;base&lt;/code&gt;, which is equal to &lt;code&gt;8&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By doing it step by step, we better understand how a recursive function can completely replace an iteration structure like the loop.&lt;/p&gt;

&lt;p&gt;☝️&lt;/p&gt;

&lt;p&gt;No solution is better between recursive function and loops. Everything depends on the situation. Think of it as an additional tool that you can use for some particular algorithms.&lt;/p&gt;

&lt;p&gt;The secret to mastering recursive functions is practice. Below you will find some exercises that I have prepared for you to progress on the topic 👇&lt;/p&gt;

&lt;p&gt;You can also get the &lt;a href="https://mindsers.shop/products/training-sheet-recursive-functions?utm_source=mindsers_blog&amp;amp;utm_medium=product-links&amp;amp;utm_content=web"&gt;Training Sheet: Recursive Functions&lt;/a&gt; as a one-time-purchase on the shop.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>javascript</category>
    </item>
    <item>
      <title>What is Ubiquitous Language?</title>
      <dc:creator>Nathanaël CHERRIER</dc:creator>
      <pubDate>Wed, 05 Oct 2022 04:00:56 +0000</pubDate>
      <link>https://forem.com/mindsers/what-is-ubiquitous-language-e86</link>
      <guid>https://forem.com/mindsers/what-is-ubiquitous-language-e86</guid>
      <description>&lt;p&gt;The &lt;em&gt;ubiquitous language&lt;/em&gt; is a concept that is based on the fact that the different actors of a project need a common language that allows them to understand the data model without ambiguity and approximation in order to be able to work &lt;em&gt;correctly&lt;/em&gt; together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;⚠️ Read more of my blog posts about tech and business &lt;a href="https://mindsers.blog/"&gt;on my personal blog&lt;/a&gt;! ⚠️&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In a project team as we understand it here, there are all the people likely to participate in the development of an application. We will therefore find developers and architects, but also users and business experts: as many technical and non-technical profiles. As a result, this often results in misunderstandings related to the terms used to designate the different elements of our model.&lt;/p&gt;

&lt;p&gt;The heart of my application is its data model. The data model is business-based. &lt;strong&gt;The business is not mastered by the developers or the architects&lt;/strong&gt; , but by the business experts, who are generally the customers.&lt;/p&gt;

&lt;p&gt;This is why it is critical to agree between the production team and the business team on the terms to be used in the model and the code. The best thing is to discuss, argue and define the terms belonging to the ubiquitous language at the beginning of the design phase in order to be able to apply it to the data model and to use it in the code of the application. &lt;strong&gt;The code produced will thus be much more expressive.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a developer talks about the data model and business rules, business experts and even users need to be able to understand exactly and unambiguously what is being said.&lt;/p&gt;

&lt;p&gt;Ideally, it should be possible to present the data model of the application to a person totally outside the project, with a non-technical profile: this person must understand how the application works.&lt;/p&gt;

</description>
      <category>bestpractices</category>
      <category>domaindrivendesign</category>
    </item>
    <item>
      <title>The advantages and disadvantages of working for a liberated company</title>
      <dc:creator>Nathanaël CHERRIER</dc:creator>
      <pubDate>Thu, 01 Sep 2022 04:00:00 +0000</pubDate>
      <link>https://forem.com/mindsers/the-advantages-and-disadvantages-of-working-for-a-liberated-company-59im</link>
      <guid>https://forem.com/mindsers/the-advantages-and-disadvantages-of-working-for-a-liberated-company-59im</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f7PbuEPD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.unsplash.com/photo-1558403194-611308249627%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDU0fHxjb21wYW55fGVufDB8fHx8MTY2MTk4MTU1MQ%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f7PbuEPD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.unsplash.com/photo-1558403194-611308249627%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDU0fHxjb21wYW55fGVufDB8fHx8MTY2MTk4MTU1MQ%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="The advantages and disadvantages of working for a liberated company" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today, more and more companies are liberating themselves. The rise of the knowledge society and new technologies has led to changes in the way businesses operate. As a result, employees began to demand a new type of working relationship, one that focused on performance and personal growth rather than restrictive hierarchies.&lt;/p&gt;

&lt;p&gt;This article will give you an overview of what a liberated company is, why it has become so prevalent today, and the pros and cons of working for it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;⚠️ Read more of my blog posts about tech and business &lt;a href="https://mindsers.blog/"&gt;on my personal blog&lt;/a&gt;! ⚠️&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a liberated company?
&lt;/h2&gt;

&lt;p&gt;A liberated enterprise is an organization that has embraced the principles of “free company” with an emphasis shifted from managing resources to managing the people who work there.&lt;/p&gt;

&lt;p&gt;The fundamental difference between a liberated company and a conventional company lies in the relationship between employees and management. Conventional organizations are run by the resources they possess, while a liberated business is run by the people who work there. A liberated company is driven by the well-being of its employees and not just by the assets it owns.&lt;/p&gt;

&lt;p&gt;The liberated enterprise is driven by relationships, not hierarchies. This shift in focus is what sets it apart from conventional business.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do companies free themselves?
&lt;/h2&gt;

&lt;p&gt;The business world has changed dramatically over the past decade, and the traditional workplace is no longer able to meet the challenges of the new competitive environment.&lt;/p&gt;

&lt;p&gt;In a world where work organizations are being transformed by the Internet, artificial intelligence and automation, management believes that controlling employees and their time is no longer effective.&lt;/p&gt;

&lt;p&gt;The concept of free enterprise is not new. It has been experimented with by hippie communities, tech companies like Google, and New York City taxi drivers since the 1970s. In the 1980s, Japan became the first country to adopt this business model in its entirety to compete with the West, where work structures are very hierarchical.&lt;/p&gt;

&lt;p&gt;With economies around the world becoming more service-oriented, the need for creative and collaborative work has increased. As a result, the traditional workplace, driven by the need for efficiency, has been replaced by a freer mode of organization, better able to cope with change.&lt;/p&gt;

&lt;h2&gt;
  
  
  The advantages of working for a liberated company
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Belonging feeling
&lt;/h3&gt;

&lt;p&gt;When you feel like you're part of something and your efforts are appreciated, you're more motivated to work harder. In these companies, you will have the feeling of belonging to a team. Even if you are an individual contributor, you will feel the support of your colleagues because they are there for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Personal development
&lt;/h3&gt;

&lt;p&gt;Working in a liberated company means you will have the opportunity to grow, both professionally and personally. There will be no barriers between you and your colleagues. You will have the opportunity to learn from them, and they will be there to help you whenever you need them.&lt;/p&gt;

&lt;p&gt;Also, liberated companies often make it possible to change roles and positions. So, it is possible to learn plenty of new skills. And this, even if they are completely unrelated to your core skills.&lt;/p&gt;

&lt;h3&gt;
  
  
  Increased innovation
&lt;/h3&gt;

&lt;p&gt;When you have the freedom to explore your ideas and share them with your colleagues, you will have the opportunity to innovate. You won't feel like your creativity is limited or that you have to go through hierarchical barriers. Your ideas will be heard and explored by other members of your team, and you can do the same.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better work-life balance
&lt;/h3&gt;

&lt;p&gt;As work in a liberated company is more organized around individuals, it is easy for the people who work there to achieve a better work-life balance. Since there are no set times or hierarchy, you can decide for yourself when you want to start and finish your work. You will have the opportunity to set your own goals and explore new ideas, as you can collaborate with your colleagues whenever you want.&lt;/p&gt;

&lt;p&gt;For example, I sometimes work on weekends or evenings. Not because I'm too busy or not working fast enough. But rather because sometimes I'm not in good shape or not motivated enough during normal working hours (9 a.m. to 5 p.m. Monday to Friday). Truth be told, I work when I'm most productive.&lt;/p&gt;

&lt;h2&gt;
  
  
  The disadvantages of working for a liberated company
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Hierarchy is replaced by bureaucracy
&lt;/h3&gt;

&lt;p&gt;A liberated company is a democratic workplace where there is no hierarchy. Unfortunately, bureaucracy is a natural side effect of this type of organization. To get things done, you will have to go through a bureaucratic process.&lt;/p&gt;

&lt;p&gt;By “bureaucracy”, I mean, for example, much more written and oral communication. Since there is no longer a manager who will centralize the information and ensure that it is transmitted to the right people, the information must exist somewhere where everyone can come and consult it.&lt;/p&gt;

&lt;h3&gt;
  
  
  No fixed hours
&lt;/h3&gt;

&lt;p&gt;While this may sound positive to some people, to others it may be a negative aspect of working in a liberated company. If you're a person who likes to have structure in your life, you might find it difficult to work in a company with no fixed hours.&lt;/p&gt;

&lt;p&gt;What allows the balance between work and private life, can also be what will remove this balance. Be careful that this is not the case. Put safeguards in place.&lt;/p&gt;

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

&lt;p&gt;Working for a liberated company can be a great experience, especially if you're someone who enjoys feeling valued and being challenged. If you are passionate about your work and want to feel like part of a team, a liberated company is the perfect place for you.&lt;/p&gt;

&lt;p&gt;There are many advantages to working for a liberated company, but there are also disadvantages that you should be aware of. Before accepting a job, make sure you understand the type of company you will be working for.&lt;/p&gt;

</description>
      <category>freeformcompany</category>
      <category>job</category>
      <category>company</category>
    </item>
    <item>
      <title>The best comments are the ones we don't write</title>
      <dc:creator>Nathanaël CHERRIER</dc:creator>
      <pubDate>Sun, 07 Aug 2022 09:34:10 +0000</pubDate>
      <link>https://forem.com/mindsers/the-best-comments-are-the-ones-we-dont-write-45k5</link>
      <guid>https://forem.com/mindsers/the-best-comments-are-the-ones-we-dont-write-45k5</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vCbqUOVm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/08/bestcomments_thumb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vCbqUOVm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://mindsers.blog/content/images/2022/08/bestcomments_thumb.png" alt="The best comments are the ones we don't write" width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've read several articles on “good comments”, I've &lt;a href="https://mindsers.blog/topic/comments/"&gt;written some&lt;/a&gt;, I've &lt;a href="https://mindsers.blog/readings/"&gt;read technical books&lt;/a&gt; about “good comments” and I work on a JavaScript project where everything must be commented (jsdoc). I changed my mind about that matter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;⚠️ Read more of my blog posts about tech and business &lt;a href="https://mindsers.blog/"&gt;on my personal blog&lt;/a&gt;! ⚠️&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Self documenting code
&lt;/h2&gt;

&lt;p&gt;What I've learned from my experiences and my reading can be summed up by the title of this post.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The best comments are the ones we don't write.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you feel the need to write a comment, it's usually because your code isn't as clear and clean as it should be.&lt;/p&gt;

&lt;p&gt;Compare this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function main() {
  let imageName = 'test.png'

  // Get the extension off the image filename  
  let pieces = imageName.split('.')
  let extension = pieces.pop()
}

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

&lt;/div&gt;



&lt;p&gt;The comment in itself isn't a bad thing. The developer may judge that we could need them later to understand the code better. He puts a comment, it's nice.&lt;/p&gt;

&lt;p&gt;But it kind of looks like an excuse : "My code is ugly/complicated but it's not that bad, I'll explain it in a comment" instead of cleaning it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function main() {
  let imageName = 'test.png'
  let extension = getFileExtension(imageName)
}

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

&lt;/div&gt;



&lt;p&gt;The name of a function is already supposed to answer the question of what a code part does. Why not use this possibility?&lt;/p&gt;

&lt;h2&gt;
  
  
  Too much comments suffocates the code
&lt;/h2&gt;

&lt;p&gt;As indicated above, on my current project we have to document everything. Everything must be commented with jsdoc.&lt;/p&gt;

&lt;p&gt;There's nothing bad about it. But in the end, most written comments are comments used solely to pass tests. They're redundant and useless.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * Get the extension of the file
 * 
 * @param {string} filename - The filename
 * @return {string} the extension of the file  
 */
function getFileExtension(filename) {
  let pieces = imageName.split('.')
  return pieces.pop()
}

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

&lt;/div&gt;



&lt;p&gt;Tell me there's an info in that comment you didn't get while reading the code?There's none.&lt;/p&gt;

&lt;p&gt;On the contrary, the fact that the function returns the extension of a file is repeated thrice : once in the name of the function, once in the function's description and once in the &lt;code&gt;@return&lt;/code&gt; tag.&lt;/p&gt;

&lt;p&gt;What is the added value of this comment? There's none.&lt;/p&gt;

&lt;p&gt;When you keep seeing useless comments, your brain learns to ignore them. You've probably experienced this before : on a project where there are many comments and a majority of comments like the one we've seen above, you end up not seeing or reading the comments anymore.&lt;/p&gt;

&lt;p&gt;Unfortunately, the few interesting comments get lost in the sea of useless ones and aren't as useful as they should.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code coverage by documentation
&lt;/h2&gt;

&lt;p&gt;As for unit tests, there are a bunch of tools that exist now to measure the code coverage for comments by documentation.&lt;/p&gt;

&lt;p&gt;And as for unit tests, you're quickly tempted to reach the 100% coverage.&lt;/p&gt;

&lt;p&gt;And as for unit tests, I'm not sure this is something worth doing. For unit tests, a high coverage isn't reliable and isn't a proof of quality ; for documentations, a high percentage of coverage isn't counter-productive and suffocates the code.&lt;/p&gt;

&lt;p&gt;By forcing developers to write documentation everywhere, we force them to write lame documentation.&lt;/p&gt;

&lt;p&gt;Where the code is clean, the comment will be useless, and your brain will soon ignore it. Where the code is messy, the developer will use the comment as an excuse to not upgrade its code.&lt;/p&gt;

&lt;h2&gt;
  
  
  I write less comments
&lt;/h2&gt;

&lt;p&gt;… and it's not a bad thing. The code is easier to read. It forces me to make my code as self-explanatory as possible : thus, the code is cleaner. Readers will pay more attention to the few comments I write.&lt;/p&gt;

&lt;p&gt;The only problem I'm facing today is in the context of a project with an auto-generated public documentation. How to avoid redundancy while making sure the documentation generated from my comment is complete.&lt;/p&gt;




&lt;p&gt;To dig deeper, here's a more recent post that goes deeper into explaining the concept/idea presented here. It follows the feedback and questions from readers :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mindsers.blog/fr/post/la-documentation-sera-toujours-utile/"&gt;La documentation sera toujours utile&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>comments</category>
      <category>bestpractices</category>
    </item>
  </channel>
</rss>
