<?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: Idan Shoshana</title>
    <description>The latest articles on DEV Community by Idan Shoshana (@idanshoshana).</description>
    <link>https://dev.to/idanshoshana</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%2F224853%2Fa45c78f5-dad5-4856-b5f6-5a17eecc088c.jpeg</url>
      <title>DEV Community: Idan Shoshana</title>
      <link>https://dev.to/idanshoshana</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/idanshoshana"/>
    <language>en</language>
    <item>
      <title>You Should Use Strapi</title>
      <dc:creator>Idan Shoshana</dc:creator>
      <pubDate>Mon, 17 Aug 2020 20:25:15 +0000</pubDate>
      <link>https://dev.to/idanshoshana/you-should-use-strapi-21be</link>
      <guid>https://dev.to/idanshoshana/you-should-use-strapi-21be</guid>
      <description>&lt;p&gt;I'm very passionate about &lt;a href="https://strapi.io/"&gt;Strapi&lt;/a&gt;! It helps me to push my team towards being more professional. Every person who saw the connection between Strapi and our application was amazed! I stopped counting how many times a person from another team came to see it.&lt;br&gt;
So, If you want to be more professional, save time for yourself and your product manager, this article is for you! &lt;/p&gt;

&lt;p&gt;In this article, I'm gonna talk about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What are CMS and Headless CMS&lt;/li&gt;
&lt;li&gt;What is Strapi&lt;/li&gt;
&lt;li&gt;My private story with Strapi&lt;/li&gt;
&lt;li&gt;Bootstrap Strapi&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  What are CMS and Headless CMS
&lt;/h2&gt;

&lt;p&gt;Before we'll talk about Strapi, you need to know what &lt;a href="https://en.wikipedia.org/wiki/Content_management_system"&gt;CMS&lt;/a&gt; (Content Management System) and &lt;a href="https://en.wikipedia.org/wiki/Headless_content_management_system"&gt;Headless CMS&lt;/a&gt; are.&lt;br&gt;
Maybe you've already heard of &lt;a href="https://wordpress.com/"&gt;WordPress&lt;/a&gt;, the traditional CMS. WordPress allows us to update the content of our application in a nice UI, but there is a strong relation between our application and the interface that helps us update the content of the app. You need to build your app using WordPress to enjoy the ability to change its content.&lt;/p&gt;

&lt;p&gt;Headless CMS shows us another perspective we can adopt.&lt;br&gt;
From &lt;a href="https://headlesscms.org/about"&gt;headlesscms.org&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Basically the frontend component of a Headless CMS is decoupled from the actual serving of the website or app.&lt;br&gt;
There’s a few ways the headless CMS can work (also look below). Either as purely API driven, where the end user connects to the api from the browser, or it can work by updating content in Git.&lt;br&gt;
Headless CMS' are opposite of legacy systems like Wordpress, Drupal, Joomla, etc. They are all CMS’ that traditionally have to be hosted and built together with the site every time it’s served.&lt;br&gt;
&lt;strong&gt;A headless CMS doesn’t care where it’s serving its content to. It’s no longer attached to the frontend, and the content can be viewed on any platform.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So as you can read, with Headless CMS I can hold another &lt;strong&gt;decoupled&lt;/strong&gt; component that helps me edit my app content (of course with a nice UI) without coupling to my existing application. To receive the data from Headless CMS, I can send API requests from the frontend component of my application.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Strapi
&lt;/h2&gt;

&lt;p&gt;Now, when you know about Headless CMS let's talk about &lt;a href="https://strapi.io/"&gt;Strapi&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From &lt;a href="https://strapi.io/documentation/v3.x/getting-started/introduction.html#what-is-strapi"&gt;Strapi Documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Strapi is a &lt;strong&gt;flexible&lt;/strong&gt;, &lt;strong&gt;open-source&lt;/strong&gt; Headless CMS that gives developers the freedom to choose their favorite tools and frameworks while also allowing editors to easily manage and distribute their content. By making the admin panel and API extensible through a plugin system, Strapi enables the world's largest companies to accelerate content delivery while building beautiful digital experiences.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You've noticed that Strapi is an implementation for Headless CMS. Why do I think Strapi is better than other implementations? Because after research I've done I found Strapi is the best &lt;strong&gt;open-source&lt;/strong&gt; option, has a &lt;strong&gt;great community&lt;/strong&gt;, and is written in &lt;a href="https://nodejs.org/"&gt;Node.js&lt;/a&gt; and &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt; so you can custom it very easily. Strapi has a &lt;strong&gt;great admin panel&lt;/strong&gt; that you can customize. You can consume the API from any client, mobile apps, or even IoT, using &lt;strong&gt;REST&lt;/strong&gt; or &lt;a href="https://graphql.org/"&gt;GraphQL&lt;/a&gt;. Strapi simplifies the &lt;strong&gt;API generation&lt;/strong&gt; (we'll see it later), gives you the ability to allow or prevent access to your API. Strapi has built-in the Auth system, comes with &lt;strong&gt;awesome plugins&lt;/strong&gt; you can connect to. Strapi can integrate with &lt;a href="https://www.mongodb.com/"&gt;MongoDB&lt;/a&gt;, &lt;a href="https://www.mysql.com/"&gt;MySQL&lt;/a&gt;, &lt;a href="https://www.postgresql.org/"&gt;PostgreSQL&lt;/a&gt;, and &lt;a href="https://www.sqlite.org/"&gt;SQLite&lt;/a&gt; databases.&lt;br&gt;
There are a lot of features you can read about!&lt;/p&gt;
&lt;h2&gt;
  
  
  My Private Story With Strapi
&lt;/h2&gt;

&lt;p&gt;A few months ago, my friend has told me about Strapi and he was very excited about it. I've liked this concept but I couldn't find any usage for me as a Software Engineer.&lt;/p&gt;

&lt;p&gt;After a few months, I've gotten a new feature from my product manager:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"In our application, we have two places I want to change often. &lt;br&gt;
The first is the &lt;strong&gt;Updates&lt;/strong&gt; screen (usually after a new version) and the second is the &lt;strong&gt;Help&lt;/strong&gt; screen. I'm tired of asking a developer to change the content in a "hard-coded" way! (requires to go inside the app's code, change the specific content, and publish a new version!) I must have an interface to change those sections in a perfect way!"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I understood his need, and I've started to think about a perfect solution for him. First I asked him if the feature could be in our existing app, a feature like Edit button for admin users, but He preferred an external application.&lt;/p&gt;

&lt;p&gt;So, Should I build a new app from scratch? This app should include a nice &lt;strong&gt;UI&lt;/strong&gt;, &lt;strong&gt;Server&lt;/strong&gt;, and &lt;strong&gt;Database&lt;/strong&gt;. I already did similar things in the past, but I've wanted to do the perfect solution in minimal time.&lt;/p&gt;

&lt;p&gt;Before I started working on a new app, I remembered the concept of Headless CMS. It felt like a solution that could match. Yes, I remembered Strapi, but I did a research to find some alternatives (I want the best for my team!). After that research, I found Strapi is surely the best option for me (see Strapi's features in What is Strapi section).&lt;/p&gt;

&lt;p&gt;I opened my computer, installed Strapi via &lt;code&gt;create-strapi-app&lt;/code&gt; (more instructions later...), logged in, added new resources, added some users, connected Strapi to MongoDB, and did other things to make sure that Strapi is the best option.&lt;/p&gt;

&lt;p&gt;Before I continue my story, let me show you Strapi!&lt;/p&gt;
&lt;h2&gt;
  
  
  Bootstrap Strapi
&lt;/h2&gt;

&lt;p&gt;Open a cli and start typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nf"&gt;npx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;create-strapi-app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;my-dream-project&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--quickstart&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You can omit &lt;code&gt;--quickstart&lt;/code&gt; and fill some inputs, like the DB type you want for example.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, start a Strapi application using this command in your application folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nf"&gt;npm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;develop&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Wait a few minutes and a new tab will open. Create a new admin user:&lt;/p&gt;

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

&lt;p&gt;This is the admin panel:&lt;/p&gt;

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

&lt;p&gt;You may say you like it! There is a lot of features you can do there. I'll focus on the main feature I want to cover, the API generation you can use later in your application.&lt;/p&gt;

&lt;p&gt;Click the &lt;code&gt;Content-Types Builder&lt;/code&gt; button, and you'll get this screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jyxoMkan--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/15slpa0ovjhbxna9506m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jyxoMkan--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/15slpa0ovjhbxna9506m.png" alt="content-types-builder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you can create &lt;code&gt;Collection Type&lt;/code&gt; and &lt;code&gt;Single Type&lt;/code&gt;. &lt;br&gt;
Think about it like that: &lt;code&gt;Collection Type&lt;/code&gt; is for an array with objects, and &lt;code&gt;Single Type&lt;/code&gt; is for one object. For example, you might generate an array of products (&lt;code&gt;Collection Type&lt;/code&gt;) and Add/Remove/Update the objects inside the array all the time. When you want to generate one object you can do it via (&lt;code&gt;Single Type&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Do you remember our Updates Screen? this screen consists of &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;content&lt;/code&gt; components: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;title&lt;/code&gt; component - consists of only plain text.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;content&lt;/code&gt; component - can consists of images, videos, and designed text. It needs to support some features of a rich text editor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's create a proper object in Strapi in order to consume it via REST and inject it into the Updates Screen component.&lt;/p&gt;

&lt;p&gt;Press on &lt;code&gt;Create new single type&lt;/code&gt;, and fill a name:&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;In my case, I choose the "UpdatesScreen" name&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Press the &lt;code&gt;Continue&lt;/code&gt; button and choose your object's fields. Give them a type and a name:&lt;/p&gt;

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

&lt;p&gt;I choose "Title" (text type) and "Content" (rich text editor type) fields corresponding to my Updates Screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xurCbPNH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xjhqtc6j2j8m7f24t8m5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xurCbPNH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xjhqtc6j2j8m7f24t8m5.png" alt="updates-screen-single-type"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the &lt;code&gt;Save&lt;/code&gt; button, your server will restart and you'll find new files on your codebase under the &lt;code&gt;api&lt;/code&gt; folder. Now you can find your new single type under &lt;code&gt;Single Types&lt;/code&gt; section, click on it. Feel free to edit and then click on the &lt;code&gt;Save&lt;/code&gt; button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--woz4D2aI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3f9em9w428f0lot3sio1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--woz4D2aI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3f9em9w428f0lot3sio1.png" alt="edit-updates-screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Awesome! now we want to be allowed to fetch this resource from our client.&lt;/p&gt;

&lt;p&gt;Go to &lt;code&gt;Roles &amp;amp; Permissions&lt;/code&gt;, Click on the edit button in the Public section. Under the Permission section, click on "find" checkbox:&lt;/p&gt;

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

&lt;p&gt;In the right side you can see the route you can go to, keep it for later:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hnG-1VCk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bcdm86x0q0k6182xthzt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hnG-1VCk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bcdm86x0q0k6182xthzt.png" alt="route"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, press the &lt;code&gt;Save&lt;/code&gt; button.&lt;br&gt;
Add your saved route to your base URL. The result should be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://localhost:1337/%7BYOUR_GENERATED_ROUTE%7D"&gt;http://localhost:1337/{YOUR_GENERATED_ROUTE}&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Go to this URL and you will get your object as a JSON, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"What's new?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"created_by"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"firstname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Idan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lastname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Shoshana"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"updated_by"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"firstname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Idan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lastname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Shoshana"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2020-08-12T07:28:32.132Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2020-08-12T07:28:32.186Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Wow, now you can fetch this resource from your application!&lt;/p&gt;

&lt;p&gt;For my case, as you can guess I've created two single types "UpdatesScreen" and "HelpScreen", with &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;content&lt;/code&gt; fields for each of them. I've replaced the Strapi's rich text editor with &lt;a href="https://github.com/zenoamaro/react-quill"&gt;React-Quill&lt;/a&gt;, in order to generate HTML instead of MARKDOWN. This is a &lt;a href="https://strapi.io/blog/how-to-change-the-wysiwyg-in-strapi"&gt;nice article&lt;/a&gt; that can be helpful for you.&lt;/p&gt;

&lt;p&gt;I've been sending requests to fetch some data from Strapi in my application, and the results are great.&lt;br&gt;
I bounce a popup (Updates Screen) for an app's user when he needs to see new updates (usually after a new app's version). I added some frontend logic in order to check if a specific user already read the updates of a specific app's version. When the product manager writes content for another app's version (via Strapi!), I know that any user on my app will get a new popup with new content!&lt;/p&gt;

&lt;p&gt;My clients see the data that comes from Strapi (They don't know 🤫)  and the product manager feels free to add new content without an effort of a developer!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UtiXRiC---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9l02fphz24mi9pkapzll.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UtiXRiC---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9l02fphz24mi9pkapzll.jpg" alt="winner"&gt;&lt;/a&gt; Photo by &lt;a href="https://unsplash.com/@brucemars?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;bruce mars&lt;/a&gt; on &lt;a href="https://unsplash.com/"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope you enjoyed! Feel free to comment!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>opensource</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Upgrading to a real time application - questions you must ask yourself</title>
      <dc:creator>Idan Shoshana</dc:creator>
      <pubDate>Fri, 07 Aug 2020 13:45:14 +0000</pubDate>
      <link>https://dev.to/idanshoshana/upgrading-to-a-real-time-application-questions-you-must-ask-yourself-3k50</link>
      <guid>https://dev.to/idanshoshana/upgrading-to-a-real-time-application-questions-you-must-ask-yourself-3k50</guid>
      <description>&lt;p&gt;Changing your existing application to support real time is absolutely becoming a common demand. Before you dive in to add some code, you must ask yourself some questions.&lt;/p&gt;

&lt;p&gt;I must note I write this post after a research I’ve done in order to upgrade my existing application (which uses &lt;a href="https://reactjs.org" rel="noopener noreferrer"&gt;React&lt;/a&gt;, &lt;a href="https://redux.js.org" rel="noopener noreferrer"&gt;Redux&lt;/a&gt; and &lt;a href="https://www.apollographql.com/docs/apollo-server" rel="noopener noreferrer"&gt;Apollo Server&lt;/a&gt; for &lt;a href="https://graphql.org" rel="noopener noreferrer"&gt;GraphQL&lt;/a&gt;) to real time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does the existing technology in my application already support real time?
&lt;/h2&gt;

&lt;p&gt;Before you go to explore some technologies, I recommend you to explore if your exist tech stack supports getting live updates or similar things.&lt;/p&gt;

&lt;p&gt;I wrote this recommendation because in my team's application we have been using Apollo Server for GraphQL, and I know GraphQL has something called &lt;strong&gt;Subscriptions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;From &lt;a href="https://graphql.org/blog/subscriptions-in-graphql-and-relay" rel="noopener noreferrer"&gt;Graphql Blog&lt;/a&gt;: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;just as the list of mutations that the server supports describes all of the actions that a client can take, the list of subscriptions that the server supports describes all of the events that it can subscribe to. Just as a client can tell the server what data to refetch after it performs a mutation with a GraphQL selection, the client can tell the server what data it wants to be pushed with the subscription with a GraphQL selection.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So the first thing I explored was how Apollo Server supports GraphQL Subscription. I was happy to find &lt;a href="https://www.apollographql.com/docs/apollo-server/data/subscriptions" rel="noopener noreferrer"&gt;Apollo Server has full support for Subscriptions&lt;/a&gt;. It's a huge benefit that a big part of your application has built in support for live updates.&lt;/p&gt;

&lt;p&gt;If you don't find something like that, go find a popular technology that can connect easily to your existing frameworks/libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  What kind of real time do I need in my application?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy1m8ooox2z2tc0nh1aax.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy1m8ooox2z2tc0nh1aax.jpg" alt="diversity"&gt;&lt;/a&gt; Photo by &lt;a href="https://unsplash.com/@sharonmccutcheon?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Sharon McCutcheon&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/boxes?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should ask yourself if you need updates like notifications from the server (unidirectional communication), or duplex messages like group chatting, multiplayer games, video conferencing (bidirectional communication). &lt;br&gt;
And why do I mention this? Because many people tend to choose a new trend before they really need it. For example, in our situation I talk about &lt;a href="https://wikipedia.org/wiki/WebSocket" rel="noopener noreferrer"&gt;WebSocket protocol&lt;/a&gt;. I definitely agree WebSockets is amazing but I also think not everybody needs it.&lt;/p&gt;

&lt;p&gt;WebSocket is a protocol that provides us full-duplex communication channels over a single &lt;a href="https://wikipedia.org/wiki/Transmission_Control_Protocol" rel="noopener noreferrer"&gt;TCP&lt;/a&gt; connection. Yes, the TCP connection must be stay open, therefore it can be overkill to maintain a open connection that you don't need. If you choose WebSocket protocol anyway, use a proper library that manages the connection for you.&lt;br&gt;
In some situations, Long-Polling can be the right choice, you don't need an open connection and it's based on HTTP protocol (&lt;a href="https://stackoverflow.com/questions/11077857/what-are-long-polling-websockets-server-sent-events-sse-and-comet" rel="noopener noreferrer"&gt;See a quick comparison of real time technologies&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;If you find a library that impresses you but doesn't have support for your preferred technology (Long-Polling, SSE, WebSocket), you can still consider that library. It will probably manage the hard parts for you.&lt;/p&gt;

&lt;p&gt;For example, when I did research for our team's app I discovered Long-Polling could be good enough for us. We didn't need bidirectional communication, only updates from a server. I found that GraphQL Subscriptions in Apollo Server is only supported via WebSocket, so I had to choose whether to stick with GraphQL Subscriptions or choose another technology (alternatives to Apollo Server are not an option).&lt;/p&gt;

&lt;p&gt;Eventually, I made a decision to go with GraphQL subscriptions and I took the risk of maintaining an open connection. I've been using &lt;a href="https://www.apollographql.com/docs/react" rel="noopener noreferrer"&gt;Apollo Client&lt;/a&gt; in our client side in order to keep an open connection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Would I need a new component to maintain?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxecgq9607ihd6bz81089.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxecgq9607ihd6bz81089.jpg" alt="gifts"&gt;&lt;/a&gt; Photo by &lt;a href="https://unsplash.com/@fempreneurstyledstock?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Leone Venter&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/boxes?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After you research some topics we've talked about earlier, you‘d probably need a new component in your architecture. Why? because if your application actually runs in a production environment, you have more than one instance for your server. It leads you to add a messaging system component to your architecture. &lt;/p&gt;

&lt;p&gt;Technologies such as Apache ActiveMQ and RabbitMQ were initially designed primarily for message queuing use cases. Other technologies such as Apache Kafka, Google Cloud Pub/Sub and Redis PubSub were designed primarily to support publish-subscribe use cases. &lt;/p&gt;

&lt;p&gt;In my team's case we need a publish-subscribe system. After some searches we chose Redis PubSub, a great product that fits our needs and has a great library that integrates with GraphQL Subscriptions.&lt;/p&gt;

&lt;p&gt;Note that you must maintain a new component, monitor it, take care of logs and more. Wake up, you will be having a baby soon and you’ll need to look after it ... &lt;/p&gt;

&lt;p&gt;My advice for you is to check if your team already has a similar messaging system you can connect to, I promise that you can save the headache of maintaining and monitoring.&lt;/p&gt;

&lt;p&gt;In addition, if you choose using the WebSocket protocol, make sure you have a corresponding &lt;strong&gt;load balancer&lt;/strong&gt;. It's very important, you choose to hold a lot of open connections so you must take care of it.&lt;br&gt;
We have a load balancer in our application but it doesn’t have support for the WebSocket protocol so we must replace it with another.&lt;/p&gt;

&lt;p&gt;I've made a diagram to make it clear:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsl1n7xjkjbcvcni7no31.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsl1n7xjkjbcvcni7no31.jpg" alt="realtime app diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Should I consider real time as reliable?
&lt;/h2&gt;

&lt;p&gt;In my opinion the answer is actually &lt;strong&gt;no&lt;/strong&gt;. Perhaps the performance is great, and you might not need to spend too much time to learn a real time technology, but you cannot trust those as reliable. Think about it like fire &amp;amp; forget: when the server sends a message for the client, it will never know if the message is received or not&lt;br&gt;
(Of course, you can implement it yourself but often this is the situation). &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;In this post, we’ve noticed some issues to care about before diving in. I've given you some tips and examples from my life but you could choose any technology you like. The bottom line is, the questions remain as they are.&lt;/p&gt;

&lt;p&gt;Thank you for reading!&lt;/p&gt;

&lt;p&gt;Cover image by &lt;a href="https://unsplash.com/@cjtagupa?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Cris Tagupa&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/boxes?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>architecture</category>
      <category>productivity</category>
      <category>graphql</category>
    </item>
  </channel>
</rss>
