<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jérémy Basso</title>
    <description>The latest articles on DEV Community by Jérémy Basso (@lokosama).</description>
    <link>https://dev.to/lokosama</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%2F367980%2F90e8c2fb-ba68-48cc-83e1-ef377386626b.jpeg</url>
      <title>DEV Community: Jérémy Basso</title>
      <link>https://dev.to/lokosama</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lokosama"/>
    <language>en</language>
    <item>
      <title>StopCovid app: overview of the backend server code</title>
      <dc:creator>Jérémy Basso</dc:creator>
      <pubDate>Wed, 10 Jun 2020 10:32:51 +0000</pubDate>
      <link>https://dev.to/lokosama/stopcovid-app-overview-of-the-backend-server-code-f1d</link>
      <guid>https://dev.to/lokosama/stopcovid-app-overview-of-the-backend-server-code-f1d</guid>
      <description>&lt;p&gt;StopCovid is a mobile application launched by the french government in order to perform contact tracing of COVID-19 infections and inform potential new infected.&lt;br&gt;
The codebase of the application is released publicly &lt;a href="https://gitlab.inria.fr/stopcovid19"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I was quite interested in seeing how they have done things because the app has a lot of expectations, and the press about it is quite harsh. One of the questions was the lack of time to implement the app because of the situation.&lt;/p&gt;

&lt;p&gt;I decided to perform a quick overview of the backend part, source code can be found &lt;a href="https://gitlab.inria.fr/stopcovid19/robert-server"&gt;here&lt;/a&gt;, and share it with you.&lt;/p&gt;

&lt;p&gt;I am not an backend development expert (yet), so expect not to agree with me on some of points ! Also, this article is not an audit of the code, but reflects my personal opinion on what I checked.&lt;/p&gt;
&lt;h2&gt;
  
  
  Tech choices
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Language : Java 1.8
&lt;/h3&gt;


&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt; &lt;span class="nt"&gt;&amp;lt;java.version&amp;gt;&lt;/span&gt;1.8&lt;span class="nt"&gt;&amp;lt;/java.version&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The language used is Java in 1.8 version, which is a logical choice for an application of this size. We could expect PHP, Javascript on Node.js as well.&lt;br&gt;
 The use of Java 8 can be discussed, since Oracle stopped updating in 2016, and Java 13 has a good adoption so far. Java 8 still works perfectly fine, but my choice would go to a newer version.&lt;br&gt;
Kotlin (still on JVM) was an option as well, but still has less adoption than Java.&lt;/p&gt;
&lt;h3&gt;
  
  
  Dependencies management: Maven over Gradle
&lt;/h3&gt;

&lt;p&gt;The dependencies management is handled by Maven. When working with Java projects, the two main possibilities for this subject are Maven and Gradle, and both are totally fine.&lt;/p&gt;

&lt;p&gt;While Maven was the first to go out, I personally prefer Gradle because of its API thats seems easier to use. Yet, Maven is a valid choice.&lt;/p&gt;
&lt;h3&gt;
  
  
  RPC framework : gRPC and REST
&lt;/h3&gt;


&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;grpc.version&amp;gt;&lt;/span&gt;1.29.0&lt;span class="nt"&gt;&amp;lt;/grpc.version&amp;gt;&lt;/span&gt;  
&lt;span class="nt"&gt;&amp;lt;protobuf.version&amp;gt;&lt;/span&gt;3.11.0&lt;span class="nt"&gt;&amp;lt;/protobuf.version&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I totally expected a classic REST or even SOAP API in this backend, and was very surprised to notice the presence of &lt;a href="//grpc.io"&gt;gRPC&lt;/a&gt;. &lt;br&gt;
This framework allows to exchange requests between servers and clients, based on HTTP/2 protocol and Protocol Buffers. One of its strength is the ability to develop backend services, generate gRPC "interface" contract, and then generate connectors to this interface for any platform or language.&lt;/p&gt;

&lt;p&gt;For the record, StopCovid frontend's is native Android and native iOS, so gRPC makes total sense. Indeed, you will only have to develop interface once on the backend-side, and the frontend will only need to generate interfaces from this. This is when gRPC shines : avoid duplicate development and mistakes when dealing with multiple performances. &lt;/p&gt;

&lt;p&gt;Otherwise, gRPC is as well is centered on high-performance, so another good point here.&lt;/p&gt;

&lt;p&gt;When diving into code, I found out REST was used. REST is the most used and most standard protocol out there, so nothing to note here.&lt;/p&gt;

&lt;p&gt;To sum up, they used gRPC for all the crypto operations around the app, and REST for "classic" API calls.&lt;/p&gt;
&lt;h3&gt;
  
  
  Database: PostgreSQL and MongoDB
&lt;/h3&gt;


&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;postgresql.version&amp;gt;&lt;/span&gt;42.2.12&lt;span class="nt"&gt;&amp;lt;/postgresql.version&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I expected that kind of database, which is an industry standard. There are a lot of well known databases out there, my guess would have been PostgreSQL or MariaDB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;  
 &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.mongodb&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;  
 &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;bson&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;  
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There seems to be some MongoDB as well, and it is a bit surprising to find multiple databases in the same project, but why not.&lt;/p&gt;

&lt;p&gt;Diving into code, MongoDB seems to be the most used database in this project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spring Boot
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;parent&amp;gt;&lt;/span&gt;  
 &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;  
 &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-starter-parent&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;  
 &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;2.2.6.RELEASE&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;  
 &lt;span class="nt"&gt;&amp;lt;relativePath&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/parent&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;They choose the Spring Boot framework that is very popular, and it is always a good choice. The version is one of the latest, which is good.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Architecture
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Modules
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;modules&amp;gt;&lt;/span&gt;  
 &lt;span class="nt"&gt;&amp;lt;module&amp;gt;&lt;/span&gt;robert-server-ws-rest&lt;span class="nt"&gt;&amp;lt;/module&amp;gt;&lt;/span&gt;  
 &lt;span class="nt"&gt;&amp;lt;module&amp;gt;&lt;/span&gt;robert-server-batch&lt;span class="nt"&gt;&amp;lt;/module&amp;gt;&lt;/span&gt;  
 &lt;span class="nt"&gt;&amp;lt;module&amp;gt;&lt;/span&gt;robert-server-database&lt;span class="nt"&gt;&amp;lt;/module&amp;gt;&lt;/span&gt;  
 &lt;span class="nt"&gt;&amp;lt;module&amp;gt;&lt;/span&gt;robert-server-crypto&lt;span class="nt"&gt;&amp;lt;/module&amp;gt;&lt;/span&gt;  
 &lt;span class="nt"&gt;&amp;lt;module&amp;gt;&lt;/span&gt;robert-server-common&lt;span class="nt"&gt;&amp;lt;/module&amp;gt;&lt;/span&gt;  
 &lt;span class="nt"&gt;&amp;lt;module&amp;gt;&lt;/span&gt;robert-crypto-grpc-server&lt;span class="nt"&gt;&amp;lt;/module&amp;gt;&lt;/span&gt;  
 &lt;span class="nt"&gt;&amp;lt;module&amp;gt;&lt;/span&gt;robert-crypto-grpc-server-messaging&lt;span class="nt"&gt;&amp;lt;/module&amp;gt;&lt;/span&gt;  
 &lt;span class="nt"&gt;&amp;lt;module&amp;gt;&lt;/span&gt;robert-crypto-grpc-server-storage&lt;span class="nt"&gt;&amp;lt;/module&amp;gt;&lt;/span&gt;  
&lt;span class="nt"&gt;&amp;lt;/modules&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The application is divided in 8 modules , which is understandable. Each module has its own dependencies, which is a bit harder to maintain, but a tradeoff for more separation and readability.&lt;/p&gt;

&lt;p&gt;As a result, each module has minimal logic implemented.&lt;/p&gt;

&lt;h4&gt;
  
  
  Module structure
&lt;/h4&gt;

&lt;p&gt;Every module share the same core package structure, even though some packages are not needed sometimes. &lt;br&gt;
The most complete module I based my reflexion on is &lt;code&gt;robert-server-ws-rest&lt;/code&gt;. Here are the packages and how I understand them :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;service&lt;/code&gt; and &lt;code&gt;service.impl&lt;/code&gt;:  business logic (interfaces and implementation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;utils&lt;/code&gt;: utils classes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;exception&lt;/code&gt;: exceptions and handlers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vo&lt;/code&gt; and &lt;code&gt;vo.mapper&lt;/code&gt;: entities for web services and mapping from and to business entities&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dto&lt;/code&gt;: entities for data transfer (as you can guess from the name)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;controller&lt;/code&gt;and &lt;code&gt;controller.impl&lt;/code&gt;: controller for API (REST or gRPC)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;database&lt;/code&gt;: database functions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;models&lt;/code&gt;: business entities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This structure is pretty simple and does the job. In that kind of structure you do not split into few layers (like Data/Domain/API), but you just split every different type of file by its role, which leads to more packages.&lt;/p&gt;
&lt;h3&gt;
  
  
  Code quality
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Testing
&lt;/h4&gt;

&lt;p&gt;A lot of tests follow the pattern Given/When/Then, which provides a good readability. Yet, the tests seems a bit simple and test only a unit of code. &lt;/p&gt;

&lt;p&gt;I did not find workflow test of the applications (like end-to-end tests), which I personally like since it helps to understand code, and check that the full workflow is working, not only the different parts separately.&lt;/p&gt;

&lt;p&gt;It would be interesting to know the test coverage of the backend, my guess is above 90%, since every important function seems to have one test tied.&lt;/p&gt;
&lt;h4&gt;
  
  
  Comments and javadoc
&lt;/h4&gt;

&lt;p&gt;My  general opinion is that sometimes this code lacks of comments. &lt;br&gt;
There are good comments when something weird is implemented, but there are missing comments about standard stuff, like fields description. Some fields have name like "ebid" or "ecc", and without any comment it is impossible to know what those fields are about.&lt;/p&gt;

&lt;p&gt;The project contains 11 TODO's, which is surprising for a released product. Most of them are tied with commented code.&lt;/p&gt;

&lt;p&gt;The javadoc around the code is very inequal, it depends on the modules. Some modules contains javadoc on all functions (robert-server-crypto for instance), when other zero (robert-server-database for instance).&lt;/p&gt;

&lt;p&gt;When browsing around the code, I was surprised to notice huge amount of commented code.&lt;/p&gt;

&lt;p&gt;This if of course bad practice, and I was very surprised to find that in production version of the code. This kind of mistakes is easy to check and remove, I guess time was the missing resource here.&lt;/p&gt;
&lt;h4&gt;
  
  
  Magic Numbers
&lt;/h4&gt;

&lt;p&gt;The code contains &lt;strong&gt;a lot&lt;/strong&gt; of magic numbers. Magic numbers are variables that contain numbers, initialized in the code instead of stored in a constant elsewhere, as an example :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@NotNull&lt;/span&gt;  
&lt;span class="nd"&gt;@Size&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  
&lt;span class="nd"&gt;@ToString&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Exclude&lt;/span&gt;  
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Those numbers 6 and 36 should be stored elsewhere and accessed trough constants. &lt;br&gt;
Imagine you want to change the size of the token max from 36 to 40. If you change the number below, you could break your code elsewhere because the size 36 would be hard coded somewhere else. By storing it to a constant, you could modify it in one place and the change would be effective everywhere else.&lt;/p&gt;

&lt;h4&gt;
  
  
  General quality
&lt;/h4&gt;

&lt;p&gt;From my point of view, the overall quality of code is good. Most of the logic is related to crypto functions, and it is difficult to find any issue with those functions without testing it. &lt;/p&gt;

&lt;p&gt;I think what is missing is a tool for quality of code that would help detect bad practices from the start and fix most of the mistakes quoted before (Sonarqube as an example), and probably some time to work with it.&lt;/p&gt;

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

&lt;p&gt;First of all, it was very interesting to gain access to the code base of the application, and I hope this will become a standard for government projects. It was a great experience for me to check how things are done for a backend of this importance, and I learned a lot.&lt;br&gt;
I find out it is really difficult to properly evaluate a code like this without spending lot of time on it. While it is easy to find basic mistakes, it is very hard to assess how logic is implemented without a complete understanding of the business rules.&lt;/p&gt;

&lt;p&gt;To conclude about StopCovid backend, I think most of the choices technology-wise are good. The overall quality of the code is good, but you can notice the lack of time they had to implement it with some bad practices.&lt;/p&gt;

&lt;p&gt;My point here is not to cast disgrace on the backend development team, I think they did their best with what they had and they can be proud of the result. The issue is more about releasing an app when time is running out and development seems not totally finished.&lt;/p&gt;

&lt;p&gt;It seems dangerous to release the StopCovid at this state, because when someone with bad intentions want to break the app, they will manage to, and they did during the bug bounty.&lt;/p&gt;

&lt;p&gt;Also, it is interesting to note that the app got released on June 2nd, few days only after opening the code source and the related bug bounty.&lt;/p&gt;

&lt;p&gt;At the moment I write (June 10th), the StopCovid app has more than one million downloads, which is huge, even though the interesting metric would be the daily users.&lt;/p&gt;

&lt;p&gt;Since this app had a lot of discussions in France, here is some interesting content about other sides of StopCovid :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nadim.computer/posts/2020-05-27-stopcovid.html"&gt;Why StopCovid fails as Privacy-Preserving Design by Nadim Kobeissi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@paula_forteza/stopcovid-une-efficacit%C3%A9-incertaine-pour-des-risques-r%C3%A9els-7e12b3747cfc"&gt;French article about the risks around StopCovid by Paula Forteza&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/juliendubois/status/1267928958491910146?s=20"&gt;Twitter thread about StopCovid server hosting by Julien Dubois&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Thanks for reading !&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>covid19</category>
      <category>backend</category>
      <category>springboot</category>
    </item>
    <item>
      <title>Node.js : Upload binary image "on-the-fly" with Fastify and Cloudinary</title>
      <dc:creator>Jérémy Basso</dc:creator>
      <pubDate>Thu, 07 May 2020 16:17:30 +0000</pubDate>
      <link>https://dev.to/lokosama/node-js-upload-binary-image-on-the-fly-with-fastify-and-cloudinary-5c1h</link>
      <guid>https://dev.to/lokosama/node-js-upload-binary-image-on-the-fly-with-fastify-and-cloudinary-5c1h</guid>
      <description>&lt;p&gt;In this article I will describe "on-the-fly" upload of a binary image, using Fastify and Cloudinary in an Node.js environnement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://fastify.io"&gt;Fastify&lt;/a&gt; is a high performance web framework built for Node.js. In my opinion it is the best web framework nowadays (as I like to call it "Express 2.0") for backend purposes.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://cloudinary.com"&gt;Cloudinary&lt;/a&gt; is a Content Delivery Network, which allow us to perform file upload and storage in a very efficient way. I like it a lot because of all the features around pictures manipulations, and because it provide very good package for free users.&lt;/p&gt;

&lt;p&gt;The whole reason when using a CDN is to &lt;strong&gt;avoid storing files in your backend storage&lt;/strong&gt; (wether it is database or file system), because it can lead to performance issues or storage overflow. This is the reason why I implemented a quick way to Upload image from a distant device to a CDN &lt;strong&gt;without storing any file&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;My use case is written in Typescript, but the equivalent can be done with standard Javascript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;First, you will need to install some packages&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install fastify fastify-multer cloudinary
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You will also need to create an account on &lt;a href="http://cloudinary.com"&gt;Cloudinary&lt;/a&gt;, you can do it for free.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core logic
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Getting the data from outside
&lt;/h3&gt;

&lt;p&gt;We need to initialize the &lt;code&gt;fastify&lt;/code&gt; router, and bind it &lt;code&gt;fastify-multer&lt;/code&gt; plugin :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fastify&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;fastify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;multer&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;fastify-multer&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;fastify&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;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentParser&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;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&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;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server listening at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;address&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then, we add a new POST route, &lt;code&gt;/api/profilePicture&lt;/code&gt; with a specific &lt;code&gt;preHandler&lt;/code&gt; from &lt;code&gt;multer&lt;/code&gt; package :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fastify&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;fastify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;multer&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;fastify-multer&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;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memoryStorage&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;upload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="c1"&gt;// See above&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;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/profilePicture&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;preHandler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;single&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;  
 &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uploadProfilePicture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;uploadProfilePicture&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;binaryData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;
   &lt;span class="c1"&gt;// TODO : do stuff&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We just set the storage mode for &lt;code&gt;multer&lt;/code&gt; to memory storage, so it does not store the file in the file system, but as a &lt;code&gt;Buffer&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;To send a picture, we consume a content of type multipart/form-data, that provides key-value couples.&lt;br&gt;
With the &lt;code&gt;preHandler&lt;/code&gt; option, we specify which key provides the data to read from the form data, in our case then name of the key is &lt;code&gt;file&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, what does &lt;code&gt;multer&lt;/code&gt; does with the uploaded data ? &lt;br&gt;
This is when the magic happens, &lt;code&gt;multer&lt;/code&gt;stores the file data into &lt;code&gt;req.file&lt;/code&gt;. We can access the content of this file with the &lt;code&gt;buffer&lt;/code&gt; field. &lt;/p&gt;

&lt;p&gt;There is nothing more to do for this part, we already have our file ready to upload on &lt;code&gt;binaryDate&lt;/code&gt; variable !&lt;/p&gt;
&lt;h3&gt;
  
  
  Uploading the data to Cloudinary
&lt;/h3&gt;

&lt;p&gt;First of all, you will need to setup your Cloudinary client using 3 credentials you can find on your account's dashboard : cloud name, api key, api secret.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cloudinary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
  &lt;span class="na"&gt;cloud_name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CDN_CLOUD_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CDN_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;api_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CDN_API_SECRET&lt;/span&gt;  
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then, you can use your client to upload the data to Cloudinary, and retrieve the result. To do so, I like to "promisify" the function in order to ease the potential logic around. &lt;/p&gt;

&lt;p&gt;In my example, I perform an eager transformation on my picture, allowing to have a version of the picture cropped and centered in the face of the person (for a profile picture as an example) built by Cloudinary.&lt;br&gt;
 Cloudinary provides tons of options to deal with pictures and it is likely that you find happiness among them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;uploadPicture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&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;cloudinary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uploader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upload_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
            &lt;span class="p"&gt;{&lt;/span&gt;  
                &lt;span class="na"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;profile_pictures&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
                &lt;span class="na"&gt;eager&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;crop&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;gravity&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;face&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;  
            &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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="nx"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Upload failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                    &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
                 &lt;span class="p"&gt;}&lt;/span&gt;  
            &lt;span class="p"&gt;}&lt;/span&gt;  
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="p"&gt;})&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Wrapping everything up
&lt;/h3&gt;

&lt;p&gt;The final route code looks like this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fastify&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;fastify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;multer&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;fastify-multer&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;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memoryStorage&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;upload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;storage&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;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memoryStorage&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;upload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;storage&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;fastify&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;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentParser&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;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;address&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;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server listening at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;address&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="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/profilePicture&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;preHandler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;single&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)},&lt;/span&gt;  
 &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uploadProfilePicture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;uploadProfilePicture&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;binaryData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&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;uploadPicture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;binaryData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Watch below for details&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this example I only return the URL of the uploaded picture, but in a more real life use, I would store it in my database, in order to send to frontend the URL of the picture when needed.&lt;/p&gt;

&lt;p&gt;I really liked this way of working with file uploads, and I highly recommend you to use that kind of strategy for your projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thanks for reading !&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>node</category>
      <category>fastify</category>
      <category>cloudinary</category>
    </item>
    <item>
      <title>Kotlin Spring Boot use-case: dependency injection of a list of services</title>
      <dc:creator>Jérémy Basso</dc:creator>
      <pubDate>Tue, 28 Apr 2020 16:40:26 +0000</pubDate>
      <link>https://dev.to/lokosama/kotlin-spring-boot-use-case-dependency-injection-of-a-list-of-services-1fcg</link>
      <guid>https://dev.to/lokosama/kotlin-spring-boot-use-case-dependency-injection-of-a-list-of-services-1fcg</guid>
      <description>&lt;h1&gt;
  
  
  Context
&lt;/h1&gt;

&lt;p&gt;With Spring boot framework, it is possible to inject a list of beans as a dependency. I always found the use of this feature useful and elegant, so I am sharing my take on this subject.&lt;br&gt;
My example will be using Kotlin, but we can assume that it works in Java just as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hRy-dXn9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/riwfqh4ljlxskemngc06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hRy-dXn9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/riwfqh4ljlxskemngc06.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our example will solve the problem of authentication with multiple providers : standard auth, Facebook,  Google or anything else. To keep it simple, we will focus only on the login feature.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up the providers
&lt;/h2&gt;

&lt;p&gt;When injecting dependencies, we will create an interface that will define the beans to inject. Here, we will call this interface &lt;strong&gt;ILoginProvider&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ILoginProvider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AuthRequest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt; 

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;supports&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AuthRequest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Boolean&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;login&lt;/code&gt; function is where the login logic happens, the &lt;code&gt;supports&lt;/code&gt; function is in charge of returning if the AuthRequest object is supported by each provider or not.&lt;br&gt;
We pass an object &lt;strong&gt;AuthRequest&lt;/strong&gt; as an argument for &lt;code&gt;login&lt;/code&gt; and &lt;code&gt;supports&lt;/code&gt;function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;AuthRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AuthType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AuthType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;OTHER&lt;/span&gt; &lt;span class="c1"&gt;// enum : [EMAIL,FACEBOOK,OTHER]&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="c1"&gt;// only filled with email/password&lt;/span&gt;

    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;socialToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="c1"&gt;// only filled with FB&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This interface will be implemented by a new class for each source. For our example we will create &lt;strong&gt;EmailLoginProvider&lt;/strong&gt; and &lt;strong&gt;FacebookLoginProvider&lt;/strong&gt; (example below), that will both implement &lt;strong&gt;ILoginProvider&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;  
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FacebookLoginProvider&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ILoginProvider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AuthRequest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// TODO : implement login function&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;supports&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AuthRequest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;AuthType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FACEBOOK&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;
  
  
  Setting up the service
&lt;/h2&gt;

&lt;p&gt;Now it is time to inject those providers, and it is definitely the cool part. When using Spring Boot, you can use the magical &lt;code&gt;@Autowired&lt;/code&gt;annotation to perform injection. In our case we want to inject all beans implementing &lt;strong&gt;ILoginProvider&lt;/strong&gt; in our LoginService :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt; 
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoginService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="nd"&gt;@Autowired&lt;/span&gt;
&lt;span class="k"&gt;lateinit&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;loginProviders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ILoginProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

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



&lt;p&gt;The last thing to do is to make good use of this list of providers, by correctly wiring each &lt;strong&gt;AuthRequest&lt;/strong&gt; to the accurate provider: You can do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt; 
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoginService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="nd"&gt;@Autowired&lt;/span&gt;
&lt;span class="k"&gt;lateinit&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;loginProviders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ILoginProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AuthRequest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;provider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;loginProviders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;firstOrNull&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;supports&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; 
        &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Provider not found"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&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;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By injecting lists of providers, we are able to maintain genericity between different sources of providers. In our example, it is very easy to disable a source (by making &lt;code&gt;supports&lt;/code&gt;return false), add a new one (by adding new &lt;strong&gt;AuthType&lt;/strong&gt; and creating a new provider).&lt;br&gt;
 It is very useful when the context is a constantly changing product&lt;/p&gt;

&lt;p&gt;You can scale this approach to any number of providers, and add more logic for provider selection through &lt;code&gt;supports&lt;/code&gt; function..&lt;/p&gt;

&lt;p&gt;Some common features benefits a lot from this approach, such as authentication, payment. This approach can be adapted to any language or framework, but my point was to highlight how elegant it was using Spring boot framework.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thanks for reading !&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>kotlin</category>
      <category>springboot</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Why you should build a starter project to enjoy your side-projects
</title>
      <dc:creator>Jérémy Basso</dc:creator>
      <pubDate>Thu, 16 Apr 2020 16:34:26 +0000</pubDate>
      <link>https://dev.to/lokosama/why-you-should-build-a-starter-project-to-enjoy-your-side-projects-47g1</link>
      <guid>https://dev.to/lokosama/why-you-should-build-a-starter-project-to-enjoy-your-side-projects-47g1</guid>
      <description>&lt;h2&gt;
  
  
  Background story
&lt;/h2&gt;

&lt;p&gt;When you are working as a developer for a company, and you want to keep working on side-projects at the same time, you will probably struggle finding a well-known and desirable resource : &lt;strong&gt;time&lt;/strong&gt;.  Directly linked to &lt;strong&gt;time&lt;/strong&gt;, another important resource is &lt;strong&gt;energy&lt;/strong&gt;. It is necessary, in my opinion, to save free &lt;strong&gt;time&lt;/strong&gt; for non work-related tasks, in order to relax and maintain enough &lt;strong&gt;energy&lt;/strong&gt;. Finally, the third resource is &lt;strong&gt;attention&lt;/strong&gt;, when a big task is ahead of you, it gets harder to maintain focus.&lt;/p&gt;

&lt;p&gt;I mentioned &lt;strong&gt;time&lt;/strong&gt;, &lt;strong&gt;energy&lt;/strong&gt; and &lt;strong&gt;attention&lt;/strong&gt; for a reason : those are often quoted as the components of the TEA framework. The idea behind TEA is that if you lack any of the 3 resources, you will never be able to achieve optimal productivity. In the case of side-projects, I think of "productivity" not as the amount of code you can deliver, but as the good balance that will provide pride, fulfillment and blooming from working on your side-projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---F2lHHfh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7n06znwanrs0wn1hhua8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---F2lHHfh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7n06znwanrs0wn1hhua8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the beginning of my carrer, I tried really hard to combine the work projects, and the side-projects. As a result, I lost motivation for my side-projects because :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I had less time to invest for the side projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It was hard for me to start something from scratch because the "motivating" part needed some boring setup first&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I did not want to spend all my free time working on my side-projects,  I just wanted to jump directly to the fun part&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Few weeks ago, an unexpected situation occurred : the COVID19 lockdown. Having to spend all my free time at home, I decided to give my side-projects a try again, and tried to find the tricks that could work for me.&lt;br&gt;
I wanted to share with you the trick that worked best, it is not a miracle solution, yet it worked very well for me : what I call &lt;strong&gt;starter&lt;/strong&gt; projects. &lt;/p&gt;
&lt;h2&gt;
  
  
  What is a starter project ?
&lt;/h2&gt;

&lt;p&gt;As a developer, whether you are an expert of a specific language, or more of a Swiss Army knife that likes to try a lot of languages, you probably have 2-3 "go-to" languages and frameworks, that you like and will always choose for a side-project. It is not necessary that the chosen language is something you work with your company, side projects can be a good opportunity to try something different.&lt;/p&gt;

&lt;p&gt;As an exemple, in my company I work mostly as backend engineer with Kotlin, but on my side projects I often go for Node.js + Typescript for backend, and Flutter for mobile frontend. It allows me to keep learning outside of my job, and most importantly have a blast developing in languages that seduces me (not that I dont like Kotlin, but I am getting used to it).&lt;/p&gt;

&lt;p&gt;So here we are, you picked a language, a framework you like, and you are ready to start !&lt;/p&gt;
&lt;h2&gt;
  
  
  Where to start ?
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Functional scope
&lt;/h3&gt;

&lt;p&gt;First of all, try to find out what are the features your starter should have. Pick few of your side-projects ideas or existing applications, and try to define what features are always needed among those. This should help you finding the scope of your starter project. You should think of this as a potential starting point for every of your projects. Your incoming projects should be a fork of this one.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Example for backend starter : authentication email/password, database connection, account management, admin routes&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Architecture
&lt;/h3&gt;

&lt;p&gt;Once you decided your functional scope, you &lt;strong&gt;should&lt;/strong&gt; spend some time on your architecture. That's the point of having a starter project : you need a good architecture, that &lt;strong&gt;you&lt;/strong&gt; like, and that &lt;strong&gt;you&lt;/strong&gt; feel confortable with. That's an opportunity for you to try something new, this starter is designed by &lt;strong&gt;you&lt;/strong&gt; and for &lt;strong&gt;you&lt;/strong&gt;, so feel free to try new things, as long as you can handle it.&lt;br&gt;
My tip for architecture is to use a whiteboard to visualize what you want to do, it will help you iterate over your architecture and spot potential issues.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Example for backend starter: hexagonal architecture&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;It is getting real now ! You can now start working on what you planned beforehand. &lt;br&gt;
Take the time to decide if you want to integrate some libraries into you starter. The idea is to limit as much as possible the number of libraries on your project, only the minimum necessary. &lt;/p&gt;

&lt;p&gt;Some tips I am sharing to you (take it or leave it):&lt;/p&gt;

&lt;p&gt;• Comment and document correctly your code. All of your projects using the starter will contain your starter.&lt;/p&gt;

&lt;p&gt;• Setup the test environment. Tests are good, make tests&lt;/p&gt;

&lt;p&gt;• Have a full implementation of a dummy resource (not a complex one). It allows you to immediately have a complete process to copy paste in your projects. For backend it would be from database to web services, and frontend from the API call to the display screen (even ugly).&lt;/p&gt;

&lt;p&gt;• Use a keyword for your project name : it will be helpful for search and replace afterwards&lt;/p&gt;

&lt;p&gt;• Setup minimal CI/CD. It could be pipeline to Heroku for backend, Bitrise for mobile dev, anything you like.&lt;/p&gt;

&lt;p&gt;• For object-oriented projects, think &lt;a href="https://en.wikipedia.org/wiki/SOLID"&gt;SOLID&lt;/a&gt;. It is more of a general advice, but still a good one.&lt;/p&gt;
&lt;h2&gt;
  
  
  What now ?
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Let's start !
&lt;/h3&gt;

&lt;p&gt;Congratulations, you built your starter ! It took some time but think of all the time you will save on your incoming projects.&lt;/p&gt;

&lt;p&gt;To start a new project from the starter, I usually do the following :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone myrepo/mystarterproject
cd mystarterproject
rm -R .git
git init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then you search for your starter project name and replace occurrences with your new project name. Another approach would be to fork the starter project, which I personally dont like because it means your starter project is public, I rather keep it private.&lt;/p&gt;

&lt;h3&gt;
  
  
  Going further
&lt;/h3&gt;

&lt;p&gt;If you want to go further, here are some things you can do to keep improving your starter.&lt;/p&gt;

&lt;p&gt;First of all, you are free to refactor, or change things on your starter. This is a good way of trying new things and then iterate on what you learned.&lt;/p&gt;

&lt;p&gt;Secondly, you can add features that you have done in one of your project to your starter, in order to save time for the next project that will need it. &lt;br&gt;
 To do so, you can branch from the master branch and include the code that you want to save for further projects. This way, the next time you will start a project, before deleting the git directory, you can merge into your local branch the features you want to include into your new project. &lt;br&gt;
 This approach can also be used to separate different technologic choices, such as database choice.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Example for backend starter: my master branch uses MongoDB database, but I have a branch that uses MySQL instead. I have as well a branch where I included full code for Facebook authentication.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why starter projects are cool ?
&lt;/h2&gt;

&lt;p&gt;Building starter projects helped a lot with my involvement in side-projects, and here is why.&lt;/p&gt;

&lt;p&gt;First of all, while I used to dislike building the basic features for my side-projects, building the starter became a side-project on itself, and it was easier to maintain &lt;strong&gt;attention&lt;/strong&gt; and &lt;strong&gt;energy&lt;/strong&gt; knowing that what I was building will save me tremendous &lt;strong&gt;time&lt;/strong&gt; later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jeAg5whS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/np5szt92uv0l03fzf8ts.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jeAg5whS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/np5szt92uv0l03fzf8ts.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;center&gt;&lt;em&gt;Accurate picture of me and my T.E.A.&lt;/em&gt;&lt;/center&gt;

&lt;p&gt;Then, it allows to summarize all your knowledge around a technology, and to have something practical that shows where you locate yourself. You can see yourself improving when improving the starter, it is setting interesting milestones&lt;/p&gt;

&lt;p&gt;I can finally start projects without spending hours of configurations and boring features, and directly jump to the fun part. The idea that drives me is : the more projects I create (and continue !) from my starter, the more the time spent on building the starter is worth.&lt;/p&gt;

&lt;p&gt;Finally, I even started created starters from my starters, for specific types of applications. Yeah I know, this is pretty meta. &lt;br&gt;
The idea is that certain types of applications always have the same core features, and the only difference between them is a standout factor that will decide if the product is successful or not. So imagine you have a starter for that kind of product : you can just try out without big investment different standout factors, until you find the one that makes a successful product. &lt;br&gt;
I am pretty convinced this approach has a potential, maybe it will come within an incoming article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thanks for reading !&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It was my first article there so any feedback is appreciated !&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>motivation</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
