<?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: Patryk Jeziorowski</title>
    <description>The latest articles on DEV Community by Patryk Jeziorowski (@pjeziorowski).</description>
    <link>https://dev.to/pjeziorowski</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%2F283456%2Fcd887553-0cdd-47ed-89dd-693ffcbbd4d2.jpg</url>
      <title>DEV Community: Patryk Jeziorowski</title>
      <link>https://dev.to/pjeziorowski</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pjeziorowski"/>
    <language>en</language>
    <item>
      <title>Blazingly fast Preview Environments for NextJS, NodeJS, and MongoDB on AWS</title>
      <dc:creator>Patryk Jeziorowski</dc:creator>
      <pubDate>Wed, 15 Dec 2021 10:00:59 +0000</pubDate>
      <link>https://dev.to/pjeziorowski/blazingly-fast-preview-environments-for-nextjs-nodejs-and-mongodb-on-aws-o1k</link>
      <guid>https://dev.to/pjeziorowski/blazingly-fast-preview-environments-for-nextjs-nodejs-and-mongodb-on-aws-o1k</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Have you ever dreamed of deploying your applications on the cloud without any hassle? Imagine a platform where all you need to do is to sign in with your AWS credentials, and automagically the platform does all the hard work of configuration of the cloud for you, and, on top of that, provides some extra features that do not exist out of the box anywhere else.&lt;/p&gt;

&lt;p&gt;Qovery is this platform - not only does it allow you to deploy your infrastructure and applications on your own cloud account, but also provides extra cool features, one of which we will see in this article.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don't take our words for granted - 14000 developers from more than 100 countries use Qovery to deploy their apps on AWS.&lt;/em&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Preview Environments
&lt;/h3&gt;

&lt;p&gt;Imagine working on a new feature. You're dealing with a full-stack application - you have a frontend, backend, and a database. You introduce a change to your backend app - how do you test all of it? It would be great if there was a service that could deploy everything for you so you can test your changes quickly and in separation with all the components...&lt;/p&gt;

&lt;p&gt;Qovery Preview Environments are designed to help you with exactly this.&lt;/p&gt;

&lt;p&gt;It not only deploys the app you changed but all other related applications and databases as well in the cloud so that you can test your new features and collaborate with reviewers of your code.&lt;/p&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%2Fuploads%2Farticles%2Fdvhsaudl4xqvxuw3rmnn.png" 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%2Fuploads%2Farticles%2Fdvhsaudl4xqvxuw3rmnn.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Preview environments feature is available on other platforms as well. Vercel and Netlify allows you to test your changes before merging code into production. It’s perfect for single frontend applications, but the concept of Preview Environments on Qovery goes far beyond this.&lt;/p&gt;

&lt;p&gt;Qovery is able not only to create a preview environment for your frontend, but also for the backend and databases - the whole stack is supported. Running a set of backend microservices? No worries, Qovery got you covered. All services will be replicated in the new environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preview environments benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time-saving&lt;/strong&gt; - You don't have to set up a fresh environment to test changes in isolation - Qovery does it all for you&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Productivity&lt;/strong&gt; - Faster changes, quicker review, better feedback loop - the productivity and quality of your application increases dramatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better tests&lt;/strong&gt; - It's best to test apps in isolation, but it's almost impossible with a complicated stack if you have to prepare the testing environment manually - Qovery does it all "automagically" for you&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independence&lt;/strong&gt; - Each environment is completely separate, meaning more people can work flawlessly on the project, testing the changes they introduce in parallel, not blocking each other&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deliver quickly&lt;/strong&gt; - Faster feedback loop, independent developers, fewer bugs, meaning the product is delivered more quickly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduce friction&lt;/strong&gt; - Waiting for others to test your changes is frustrating - with preview envs everyone has his own testing environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  AWS Infrastructure
&lt;/h3&gt;

&lt;p&gt;Before we start with the deployments, we need to have our AWS infrastructure ready and deployed. It can be done as simply as by providing credentials to your cloud account, you can see how to configure the credentials in this article - &lt;a href="https://hub.qovery.com/docs/using-qovery/configuration/cloud-service-provider/amazon-web-services/" rel="noopener noreferrer"&gt;https://hub.qovery.com/docs/using-qovery/configuration/cloud-service-provider/amazon-web-services/&lt;/a&gt;&lt;/p&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%2Fuploads%2Farticles%2F04ilry028dda5tk13pu3.png" 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%2Fuploads%2Farticles%2F04ilry028dda5tk13pu3.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;The initial setup takes about 15 min, and your cluster is ready to host your applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Full Stack Application
&lt;/h3&gt;

&lt;p&gt;In this example, we will use a Next.js frontend, Node.js backend, and MongoDB as a database. The app will display an image gallery with images fetched from the backend. Preview Environments feature will help us introduce a new change in the backend - moving away from a hardcoded POC list of images to a list fetched from our database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend
&lt;/h3&gt;

&lt;p&gt;Our simple image gallery will look like this&lt;/p&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%2Fuploads%2Farticles%2F3k56v3eqfatdm7zkim24.png" 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%2Fuploads%2Farticles%2F3k56v3eqfatdm7zkim24.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;To generate the application, we used &lt;code&gt;npx create-next-app@latest&lt;/code&gt;, but the source code can be found here - &lt;a href="https://github.com/pjeziorowski/gallery-demo/tree/master/frontend" rel="noopener noreferrer"&gt;https://github.com/pjeziorowski/gallery-demo/tree/master/frontend&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main changes introduced to the generated application scaffolding are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding a &lt;code&gt;Dockerfile&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:alpine&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /usr/src
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/src&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /usr/src&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; npm run start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Adding a query to our backend (which we will be built soon in the next steps) that fetches a list of images to display in our gallery&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useImages&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;images&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;apiRoot&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/api/v1/images`&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&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;/li&gt;
&lt;li&gt;&lt;p&gt;Plus, we adjusted the HTML and styling for the demo purpose of showing a list of images&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Backend
&lt;/h3&gt;

&lt;p&gt;Our backend is the main star of the demo. In its first version, the backend is displaying a hardcoded list of images. In the next step, we will gradually expand its capabilities. It will connect to a database and fetch the list from MongoDB instead. To make sure the changes are correct, we will use &lt;code&gt;Preview Environment&lt;/code&gt; feature before merging the pull request to our production environment&lt;/p&gt;

&lt;p&gt;The backend was generated using Express &lt;code&gt;npx express-generator --no-view&lt;/code&gt;, and the source code can be found here - &lt;a href="https://github.com/pjeziorowski/gallery-demo/tree/master/frontend" rel="noopener noreferrer"&gt;https://github.com/pjeziorowski/gallery-demo/tree/master/backend&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Changes that we introduced to the generated app scaffolding are the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Adding a Dockerfile&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:16&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/src/app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; [ "node", "src/index.js" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Creating a &lt;code&gt;/api/v1/images&lt;/code&gt; endpoint that returns a hardcoded array of images&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/images&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;IMG_4985.HEIC&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3.9 MB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://images.unsplash.com/photo-1582053433976-25c00369fc93?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&amp;amp;ixlib=rb-1.2.1&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;w=512&amp;amp;q=80&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;In the next step we will improve the function to use a Mongo database instead.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Deployment
&lt;/h3&gt;

&lt;p&gt;After creating a new project, let's now set up our &lt;code&gt;production&lt;/code&gt; environment.&lt;/p&gt;

&lt;p&gt;First, let's deploy our frontend. Click &lt;code&gt;Add my first application&lt;/code&gt;, select a correct repository, &lt;code&gt;Docker&lt;/code&gt; as build mode and expose port &lt;code&gt;3000&lt;/code&gt;. The application root path is &lt;code&gt;/frontend&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next step: add a &lt;code&gt;MongoDB&lt;/code&gt; database - it will be used by our backend later on. You can do so by clicking on &lt;code&gt;Add&lt;/code&gt; button in Qovery Console in Environment.&lt;/p&gt;

&lt;p&gt;Now let's deploy our backend. Click &lt;code&gt;Add&lt;/code&gt; → &lt;code&gt;Application&lt;/code&gt;, pick up &lt;code&gt;/backend&lt;/code&gt; as application root path, &lt;code&gt;8080&lt;/code&gt; port, and &lt;code&gt;Docker&lt;/code&gt; build mode.&lt;/p&gt;

&lt;p&gt;For the future connection to DB, let's add an alias named &lt;code&gt;DATABASE_URL&lt;/code&gt; that points to our Mongo database internal URL in our backend &lt;code&gt;Environment Variable&lt;/code&gt; settings:&lt;/p&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%2Fuploads%2Farticles%2Fhjh1gf92i7feako2fpig.png" 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%2Fuploads%2Farticles%2Fhjh1gf92i7feako2fpig.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Additionally, let's create an alias called &lt;code&gt;API_ROOT&lt;/code&gt; in our frontend application that points to our backend external URL:&lt;/p&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%2Fuploads%2Farticles%2Fvuf8ugubrao052hz48nq.png" 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%2Fuploads%2Farticles%2Fvuf8ugubrao052hz48nq.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;This is it! Now we can deploy our production environment. After a few minutes, navigate to the frontend app, click on &lt;code&gt;Open&lt;/code&gt; - you should be redirected to the image gallery&lt;/p&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%2Fuploads%2Farticles%2F3uyy1wn6aao02wx6wevn.png" 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%2Fuploads%2Farticles%2F3uyy1wn6aao02wx6wevn.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Enable Preview Environments
&lt;/h3&gt;

&lt;p&gt;The next step to see the preview environment feature in action is to enable it for our backend application.&lt;/p&gt;

&lt;p&gt;To do so, navigate to &lt;code&gt;Environment&lt;/code&gt; → &lt;code&gt;Settings&lt;/code&gt; → &lt;code&gt;Preview Env&lt;/code&gt; and tick it for the backend app&lt;/p&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%2Fuploads%2Farticles%2Faalevwhxkrxm8th41f28.png" 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%2Fuploads%2Farticles%2Faalevwhxkrxm8th41f28.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Great! The feature is enabled. To see it in action, let's edit our code in the backend app so that the list of images is fetched from the database instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing Preview Environments
&lt;/h3&gt;

&lt;p&gt;Let's make a small update of our backend - let's connect to MongoDB and fetch images from there. Here are changes to the function we could introduce to make it happen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;databaseUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DATABASE_URL&lt;/span&gt;
    &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongodb://localhost:27017/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;databaseUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;imageSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;data&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's now create a new branch in our repository and create a pull request to our production (master branch) environment. Preview Environments feature will spin up a new environment for us so that we can safely test changes we just introduced!&lt;/p&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%2Fuploads%2Farticles%2Fa8z9a6unj4zgjgj9atbe.png" 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%2Fuploads%2Farticles%2Fa8z9a6unj4zgjgj9atbe.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now, when we display environments in our project, we will see that a new environment for the pull request is being deployed:&lt;/p&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%2Fuploads%2Farticles%2Fkdg8dtj44r9vk0do92cv.png" 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%2Fuploads%2Farticles%2Fkdg8dtj44r9vk0do92cv.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;with all the resources we need! A database, backend, frontend - we can now test our changes in complete separation from the production without any manual setting up work:&lt;/p&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%2Fuploads%2Farticles%2Fpteka2uluhf2pgy9rxf8.png" 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%2Fuploads%2Farticles%2Fpteka2uluhf2pgy9rxf8.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Preview Environment Explained
&lt;/h3&gt;

&lt;p&gt;The Preview Environment feature can be enabled or disabled per app. It creates a complete copy of your environment so that you can test new changes from pull requests in separation. It deploys your databases, backend, and frontend applications to a  completely new environment once a pull request is opened. If you update your pull request, all new changes are also reflected in the new environment so that you can test them or fix problems during the review. What is great is that Qovery takes care of managing all environment variables for you as well, creates new aliases just as you had in your prod environment, so that everything is really tested separately and it all happens automagically. After the pull request is merged, Qovery automatically cleans up the preview environment to save your money.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing Preview Environments PT II
&lt;/h3&gt;

&lt;p&gt;After a few minutes, your preview environment should be up and running. You can now navigate to the frontend app and click &lt;code&gt;Open&lt;/code&gt; - in the image gallery, you will see an empty list because we don't yet have any images in the database.&lt;/p&gt;

&lt;p&gt;You can add a few images manually by connecting to your mongo instance via CLI. The credentials can be found in the database overview:&lt;/p&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%2Fuploads%2Farticles%2Fnqfhonsonx6yipnzfhfl.png" 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%2Fuploads%2Farticles%2Fnqfhonsonx6yipnzfhfl.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;After connecting, let's add images by executing the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;images&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;IMG_4985.HEIC&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3.9 MB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
             &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://images.unsplash.com/photo-1582053433976-25c00369fc93?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&amp;amp;ixlib=rb-1.2.1&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;w=512&amp;amp;q=80&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="p"&gt;},&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;IMG_4985.HEIC&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3.9 MB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
             &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://images.unsplash.com/photo-1582053433976-25c00369fc93?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&amp;amp;ixlib=rb-1.2.1&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;w=512&amp;amp;q=80&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="p"&gt;},&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;IMG_4985.HEIC&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3.9 MB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
             &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://images.unsplash.com/photo-1582053433976-25c00369fc93?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&amp;amp;ixlib=rb-1.2.1&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;w=512&amp;amp;q=80&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, after opening the frontend app in our preview environment, we will see all the images we put in the database! It looks like the feature is working well, so let's merge the PR:&lt;/p&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%2Fuploads%2Farticles%2Fxubg6kpwcx9qnal66g9z.png" 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%2Fuploads%2Farticles%2Fxubg6kpwcx9qnal66g9z.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;What now happens is automatically after the PR merge, the preview environment is automatically cleaned up:&lt;/p&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%2Fuploads%2Farticles%2F8mcqtug1mnj4ck8ztba4.png" 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%2Fuploads%2Farticles%2F8mcqtug1mnj4ck8ztba4.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Great job! Thanks to Qovery Preview Environments, we managed to develop a new feature in a complete separation from our production, we tested it in a real environment deployed in the cloud, and we didn't have to spend any time preparing our environment for tests at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In the article, we quickly went through the process of creating a full-stack application with frontend, backend, and database. We enabled the Preview Environment feature to develop new features more quickly. We learned what the benefits of Preview Environments are, how to use them, and how to integrate them to day to day development workflow.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>mongodb</category>
      <category>react</category>
    </item>
    <item>
      <title>Improving Product User Experience with  Data Science</title>
      <dc:creator>Patryk Jeziorowski</dc:creator>
      <pubDate>Wed, 11 Aug 2021 19:40:23 +0000</pubDate>
      <link>https://dev.to/pjeziorowski/improving-product-user-experience-with-data-science-5eie</link>
      <guid>https://dev.to/pjeziorowski/improving-product-user-experience-with-data-science-5eie</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://qovery.com" rel="noopener noreferrer"&gt;Qovery&lt;/a&gt; is a continuous deployment platform. Users deploy apps of all kinds, written in any language and framework they choose. The freedom users have come with a cost for the Qovery core team - the broad scope Qovery has to cover, makes it harder to make the deployment process stable and straightforward for everybody. It's easy to create a service focused on just one language or framework - supporting all of them requires considering many more factors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The challenge we face is to make deployments as reliable and simple as possible while letting users choose any language and framework they want. We need to automate and simplify the process of finding the most commonly occurring issues to be able to prioritize and fix the most urgent problems first.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's not possible to foresee and prepare for all the cases - the scope is just too broad. To make sure all the deployments of any kind of apps deploy and run smoothly and figure out the most common issues, we use a data-driven approach and use a few simple ML tools to simplify the process of determining the problems our users face while deploying their apps.&lt;/p&gt;

&lt;p&gt;Embracing a scientific approach of collecting data, making measurements and taking data-driven actions is the only way to find out and fix the most common problems in building and deploying our users applications.&lt;br&gt;
Error Reporting&lt;/p&gt;
&lt;h2&gt;
  
  
  Error Reporting
&lt;/h2&gt;

&lt;p&gt;When you deploy on Qovery, our deployment Engine runs the builds and deployments of your applications. Any error encountered in the deployment pipeline is reported back to Qovery.&lt;/p&gt;

&lt;p&gt;An example of errors we report include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"scope": "ENVIRONMENT", "state": "DEPLOYMENT_ERROR", "message": "\n-------------------------------------------------------------------------------\n\n MESSAGE FOR QOVERY TEAM:\n * Execution ID: 0548486d-0605-4b64-8049-24954ceec8e0-13-1625428767\n * Scope: Build platform 'beta-build' with id 'ze9e19029'\n * Rollback message: \n\n-------------------------------------------------------------------------------\n\n \u274c \u274c \u274c MESSAGE FOR THE USER \u274c \u274c \u274c\n\n \u2709\ufe0f Error message: Qovery can't build your container image beta-build (ze9e19029) with one of the following builders: heroku/buildpacks:20. Please do provide a valid Dockerfile to build your application or contact the support.\n \ud83d\udcac Need help: Look at the hint message first. If you need more assistance, you can reach the support team on Discord (https://discord.qovery.com) or on the Qovery console (https://console.qovery.com) with the integrated chat.\n \u2139\ufe0f Hint: None builders supports Your application can't be built without providing a Dockerfile\n "}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"scope": "ENVIRONMENT", "state": "DEPLOYMENT_ERROR", "message": "\n-------------------------------------------------------------------------------\n\n MESSAGE FOR QOVERY TEAM:\n * Execution ID: d5ab51f0-94d3-4671-8dc6-77fc228f2e35-6-1627037439\n * Scope: Build platform 'beta-build' with id 'ze9e19029'\n * Rollback message: \n\n-------------------------------------------------------------------------------\n\n \u274c \u274c \u274c MESSAGE FOR THE USER \u274c \u274c \u274c\n\n \u2709\ufe0f Error message: error while building container image beta-build (ze9e19029). Error: SimpleError { kind: Command(ExitStatus(ExitStatus(256))), message: Some(\"error while executing an internal command\") }\n \ud83d\udcac Need help: Look at the hint message first. If you need more assistance, you can reach the support team on Discord (https://discord.qovery.com) or on the Qovery console (https://console.qovery.com) with the integrated chat.\n \u2139\ufe0f Hint: It looks like there is something wrong in your Dockerfile. Try run locally using `qovery run` or build with `docker build --no-cache`\n "}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We collect hundreds of this kind of errors. Based on this data, we try to figure out what are the most common errors that our users encounter.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pipeline
&lt;/h2&gt;

&lt;p&gt;The first steps of the process resemble ETL pipeline. First, we Extract data from our data store. Then, we Transform it so that it can be used in our analytical use case. In the end, we come up with a new set of data that is Loaded to a separate location and then used as input in analytics.&lt;/p&gt;

&lt;p&gt;The picture below is a visual representation of all the steps of the process. We’ll go through each part more closely in the next sections of the article.&lt;/p&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%2Fuploads%2Farticles%2Fvxrbinlyow2gk4rb21w5.png" 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%2Fuploads%2Farticles%2Fvxrbinlyow2gk4rb21w5.png" alt="Pipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Extract
&lt;/h3&gt;

&lt;p&gt;The first step in our pipeline is exporting the data from our data store. Given the amount of data we have and the fact that the database is used in production by other platform functionalities, we take a daily dump/backup of the data and use it as input in the following pipeline steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transform
&lt;/h3&gt;

&lt;p&gt;The data we store, however, is not structured well for what we want to do. It was not designed for processing error messages in the first place - its primary purpose is different. Thus, we need to preprocess the data before it's useful for our goal.&lt;/p&gt;

&lt;p&gt;As an example - to improve the performance of the Qovery platform, we batch deployment events we receive, which results in multiple events being stored in a single unit. So, to prepare the input data, the first step we take is flattening those messages into a single flat list of deployment events.&lt;/p&gt;

&lt;p&gt;After we have our input (the flat list of raw error logs), we start another step - the data cleaning. To provide sharp and correct answers, we need to structure our data to be more accessible to process and segment in the algorithms we use further in the pipeline.&lt;/p&gt;

&lt;p&gt;Those steps are pretty standard in NLP and include things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lowercasing messages&lt;/li&gt;
&lt;li&gt;removing punctuation&lt;/li&gt;
&lt;li&gt;removing whitespace&lt;/li&gt;
&lt;li&gt;removing empty messages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code for this is very simple - it’s just executing data mapping functions on our input data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;no_uppercase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
 &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;no_numbers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
 &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;no_punctuation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
 &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;no_stopwords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
 &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;no_whitespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
 &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;no_qovery_specifics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
 &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;no_unicode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
 &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;non_empty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And an example of mapping function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;no_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;scope&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;scope&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\d+&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal is to make the logs structured efficiently for the ML algorithms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Load
&lt;/h3&gt;

&lt;p&gt;At the end of the Transform step, we end up with a relatively small set of data that, for now, we just store in a JSON file and use as an input for our simple NLP scripts.&lt;br&gt;
Python&lt;/p&gt;

&lt;p&gt;Python is excellent in how simple the language is and the number of battle-tested libraries existing in the NLP/ML space. Even though we don't use Python much at Qovery, it was an easy choice to pick it in this case.&lt;/p&gt;

&lt;p&gt;We didn't have to implement much ourselves. Each algorithm is already implemented and battle-tested by many of the popular Python libraries, starting from data cleaning, going through later steps as vectorizing data, clustering data, and so on.&lt;/p&gt;

&lt;p&gt;All we had to do was prepare the input data, configure the libraries, and play with parameters to achieve the best results - the Python ML ecosystem is vast and provides everything you need, so you don't need to implement much yourself.&lt;/p&gt;

&lt;p&gt;The libraries we used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NTLK&lt;/li&gt;
&lt;li&gt;Gensim - Doc2Vec&lt;/li&gt;
&lt;li&gt;sklearn&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Vectorizing Data
&lt;/h2&gt;

&lt;p&gt;After the data is transformed, what we want to do, is to vectorize our text data (error messages). Why would we want to vectorize the data, and what does it mean?&lt;/p&gt;

&lt;p&gt;In NLP, vectorization is used to map words or sentences into vectors of real numbers, which can be then used to find things like word predictions, similarities etc.&lt;/p&gt;

&lt;p&gt;We can also use vectorized data for clustering, and this is what we want to achieve - group error logs, so we can see if there are any commonly occurring patterns in deployment problems that we can address to improve the success rate of deployments at Qovery.&lt;/p&gt;

&lt;p&gt;The method we used for vectorizing data is Doc2Vec from Gensim - using the library is as simple as executing one function with your input data and adjusting parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;transformToVectors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Doc2Vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;epochs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;‍&lt;/p&gt;

&lt;h2&gt;
  
  
  Clustering Data
&lt;/h2&gt;

&lt;p&gt;In this step, we take our vectors (numerical representations of our documents - in this case - error logs) and group them based on their similarity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Density-based Spatial Clustering Of Applications With Noise (DBSCAN)
&lt;/h3&gt;

&lt;p&gt;The method we used to group errors is DBSCAN. The principle behind this method is pretty simple - it groups points that are close to each other based on distance (usually Euclidean distance) and a minimal number of points required to create a cluster. It also marks the points as outliers if they are located in a low-density region.&lt;/p&gt;

&lt;p&gt;The implementation, similarly to vectorizing data, is just about invoking the library with your data and adjusting parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dbscan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vecs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;DBSCAN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_samples&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metric&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cosine&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fit_predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;docvecs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index_to_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Identifying Errors
&lt;/h2&gt;

&lt;p&gt;The result of DBSCAN provided us with dozens of different error groups. Errors in each group are related to each other. In this (manual) step, I went through all the groups, starting from the biggest ones, and dug into the root cause of the issues in the group.&lt;/p&gt;

&lt;p&gt;The results were quite accurate - usually, most of the errors in one group were caused by one or two root causes. It wasn't always easy to find the cause - this part required a bit of digging and understanding.&lt;/p&gt;

&lt;p&gt;For errors with unclear cause, we came up with a hypothesis and plan to validate our guesses by implementing potential fixes and measuring the results of new deployments later on again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Insights
&lt;/h2&gt;

&lt;p&gt;The results and insights we got from analyzing the output of our simple ML pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;~23% of errors were caused during the build process using buildpacks to build users apps&lt;/li&gt;
&lt;li&gt;~17% - we couldn't determine what buildpacks builder to use for the build&lt;/li&gt;
&lt;li&gt;~16.5% - Kubernetes liveness problems failures - primarily due to users applications ports misconfiguration or crashing apps during the startup phase&lt;/li&gt;
&lt;li&gt;~6% - another build pack problem - application errors due to more than one process run and the default buildpacks configuration not being able to start the app&lt;/li&gt;
&lt;li&gt;~5% - build errors while building Docker images provided by users&lt;/li&gt;
&lt;li&gt;and a couple of sub-2% errors, like failures of deployment due to cloud provider limits, problems with cloning Git repositories, and minor bugs in our API or Qovery Engine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Coming up with those insights and numbers would not be possible without automating the process of analyzing deployments. With the number of deployments we have and different types of applications our users deploy, there is no way to do it "manually".&lt;/p&gt;

&lt;p&gt;Embracing the data-driven approach allowed us to make use of the information we already have in our databases to figure out what are the most common errors, prioritize the order of providing solutions to the problems, but also enabled us to identify many less frequently occurring problems, which when added up and fixed, should greatly increase the stability of deployments on the platform.&lt;/p&gt;

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

&lt;p&gt;It's quite impressive what we could achieve in such a short time with Python and simple NLP. A person who has little knowledge in data science can use existing libraries to process large amounts of data and develop valuable insights that can be used to improve the service.&lt;/p&gt;

&lt;p&gt;The following steps for us are to address problems we identified and repeat analyzing the error reporting data to see where we improved and what are the new most frequently occurring issues. Now, it's time to make use of the insights we learned and make the builds bulletproof! :)&lt;/p&gt;

</description>
      <category>ux</category>
      <category>datascience</category>
      <category>webdev</category>
      <category>startup</category>
    </item>
    <item>
      <title>How to Automagically Take Notes From Podcasts Without Typing A Word</title>
      <dc:creator>Patryk Jeziorowski</dc:creator>
      <pubDate>Thu, 20 May 2021 17:35:25 +0000</pubDate>
      <link>https://dev.to/pjeziorowski/how-to-automagically-take-notes-from-podcasts-without-typing-a-word-123m</link>
      <guid>https://dev.to/pjeziorowski/how-to-automagically-take-notes-from-podcasts-without-typing-a-word-123m</guid>
      <description>&lt;p&gt;Listening to podcasts is a great way to learn. It's a shame that taking notes of the most insightful information we hear forces us to pick up our phones or look for our pens and journals. It's disturbing and sometimes not even possible, especially while driving a car or having our hands occupied in any other way. Luckily, there are services and apps that make this process fully automatic, without requiring us to type a word.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we can achieve
&lt;/h2&gt;

&lt;p&gt;Imagine going for a walk with AirPods in your ears. You hear something very insightful. You press a button on a headphone. The valuable sentence you just heard is saved as text in your note-taking system (alongside the link to the podcast episode with the exact timing of the quote).&lt;/p&gt;

&lt;p&gt;Sounds cool, doesn't it? It's pretty easy to achieve by integrating a few services and an app on our phone. &lt;/p&gt;

&lt;h2&gt;
  
  
  First step - Airr
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.airr.io/" rel="noopener noreferrer"&gt;Airr&lt;/a&gt; is a podcast player that allows taking so-called &lt;strong&gt;AirrQuotes&lt;/strong&gt;. AirrQuotes are highlights of the best moments we hear in podcasts. When we hear something insightful, all we need to do is to press a button on AirPods (applies to Apple AirPods users - for other hardware users, you'll probably have other options). &lt;/p&gt;

&lt;p&gt;Airr allows exporting all the AirQuotes automagically to other services, alongside text transcription of the quote. It all happens automatically, without requiring us to trigger export manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Second step - Readwise
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://readwise.io/" rel="noopener noreferrer"&gt;Readwise&lt;/a&gt; is an extremely useful service. It's a hub for highlights and notes from other systems - note something in Kindle, take AirrQuote in Podcast app, highlight something in RSS reader - all of this can be automatically ingested by Readwise and stored in one place. &lt;a href="https://help.readwise.io/article/103-how-do-i-save-highlights-from-the-podcasts-i-listen-to-using-airr" rel="noopener noreferrer"&gt;Steps for integrating it with Airr are extremely simple&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Right now, I'm exporting highlights from 8 apps and services to my Readwise hub.&lt;/p&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%2Fuploads%2Farticles%2Fd0kcr6fvr8jvbh78sx0h.png" 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%2Fuploads%2Farticles%2Fd0kcr6fvr8jvbh78sx0h.png" alt="Readwise Integrations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But, what is the most important, Readwise also allows exporting everything we ingest automatically to other systems (e.g. note-taking apps) like Notion, Evernote, Roam etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Third step - note-taking app
&lt;/h2&gt;

&lt;p&gt;I use Readwise to export all my notes (including AirrQuotes from podcasts, which are stored safely in my Readwise) to the best note-taking (it's an understatement) app in this world - &lt;a href="https://roamresearch.com/" rel="noopener noreferrer"&gt;Roam&lt;/a&gt; (I'm not sorry for this biased, strong opinion. Roam rulez).&lt;/p&gt;

&lt;p&gt;All we need to do to set up the integration is to sign up and follow easy steps from the manual, which takes less than a minute. This process will depend on what app you use to store your notes. In my case, it looked like &lt;a href="https://help.readwise.io/article/71-how-does-the-readwise-to-roam-export-integration-work" rel="noopener noreferrer"&gt;this&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enjoy
&lt;/h2&gt;

&lt;p&gt;That's it. Having it all done, we can reward ourselves by going for a walk, listening to a podcast, and taking notes of the best insights with a single button click on our earphone.&lt;/p&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%2Fuploads%2Farticles%2Ffdcss0z5jfpmvewll496.png" 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%2Fuploads%2Farticles%2Ffdcss0z5jfpmvewll496.png" alt="Automatic Notes From Podcasts"&gt;&lt;/a&gt; &lt;/p&gt;

</description>
      <category>productivity</category>
      <category>blogging</category>
      <category>learning</category>
      <category>automation</category>
    </item>
    <item>
      <title>Bloomly, a new full-stack project to manage your content online</title>
      <dc:creator>Patryk Jeziorowski</dc:creator>
      <pubDate>Sat, 15 May 2021 21:10:12 +0000</pubDate>
      <link>https://dev.to/pjeziorowski/bloomly-a-new-full-stack-project-to-manage-your-content-online-43gb</link>
      <guid>https://dev.to/pjeziorowski/bloomly-a-new-full-stack-project-to-manage-your-content-online-43gb</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/pjeziorowski/365-days-of-blogging-challenge-or-i-transfer-1000-to-your-bank-account-5dj9"&gt;previous post&lt;/a&gt;, I announced that I start my &lt;strong&gt;365 days of blogging challenge&lt;/strong&gt;. I also released a &lt;a href="https://dev.to/pjeziorowski/how-i-publish-articles-to-all-developer-platforms-and-my-private-blog-in-one-shot-38aj"&gt;mini CLI tool&lt;/a&gt; that publishes articles to all the major developer blogging platforms (dev.to, hashnode, medium) with one command.&lt;/p&gt;

&lt;p&gt;The tool lacks some features, though, and I saw that people have the same problem as I have - they need a centralized place to manage their articles or avoid publishing their content manually on multiple sites. &lt;strong&gt;Automating stuff saves time&lt;/strong&gt;...&lt;/p&gt;

&lt;p&gt;This is why I decided to help them (and myself) by creating a service that allows you to write your articles, publish them, and manage them on all the previously mentioned platforms in one place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pain to solve
&lt;/h2&gt;

&lt;p&gt;In general, I want to create a tool that will &lt;strong&gt;reduce the friction and effort you need to put in to create and distribute your content as a developer&lt;/strong&gt;. In the future, it should also help you &lt;strong&gt;reach more people and let you analyze what works best&lt;/strong&gt; and what your audience like to read about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;The MVP will cover writing articles and integrations with all the platforms (publishing, updating, and deleting articles). It also covers all the basics like signups, creating projects and adding collaborators.&lt;/p&gt;

&lt;p&gt;Next steps I have in my mind if the project gains traction or if I find it helpful to my blogging journey:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;displaying article statistics from all platforms in one place&lt;/li&gt;
&lt;li&gt;generating article covers, adjusting stuff best for the given platform (e.g. cover sizes), in general - reducing the effort of publishing&lt;/li&gt;
&lt;li&gt;marketing - integrations with Twitter, LinkedIn, Instagram, Facebook, to help you announce to the world that your articles are published&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tech stack
&lt;/h2&gt;

&lt;p&gt;To quickly build the backend and GraphQL API, I decided to go with &lt;a href="https://hasura.io/" rel="noopener noreferrer"&gt;Hasura&lt;/a&gt;. It's not the only backend component - to perform custom business logic, I need a separate microservice or serverless functions that Hasura will call on certain events. For this, I decided to go with Golang and a great &lt;a href="https://echo.labstack.com/" rel="noopener noreferrer"&gt;Echo HTTP framework&lt;/a&gt;. I'm still thinking, though, if I should use Node.js, as Hasura provides some excellent tooling that helps you generate code for your serverless functions.&lt;/p&gt;

&lt;p&gt;For the frontend - React.js with &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next&lt;/a&gt; and &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind&lt;/a&gt;. I've been a fan of those technologies since their humble beginnings, so the choice here was pretty easy for me.&lt;/p&gt;

&lt;p&gt;For deploying and hosting the app I'll use &lt;a href="https://www.qovery.com/" rel="noopener noreferrer"&gt;Qovery&lt;/a&gt; - it's a startup that aims to provide great developer experience in deploying and building full-stack applications in the cloud. For disclosure - I'm building this platform during my working hours :P.&lt;/p&gt;

&lt;h2&gt;
  
  
  Progress
&lt;/h2&gt;

&lt;p&gt;I've just started today coding the backend part - most of the MVP API and data modelling is done.&lt;/p&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%2Fuploads%2Farticles%2Fg02jpn1dup0906wev390.png" 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%2Fuploads%2Farticles%2Fg02jpn1dup0906wev390.png" alt="MVP Query API"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I still need to implement the custom actions (interactions with APIs of the publishing platforms) in the Golang microservice. When it's done, I'll jump into coding the frontend part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collaborators are welcome
&lt;/h2&gt;

&lt;p&gt;I can do everything by myself, but it would be much more pleasant to work in a group, so if you are interested in building this kind of project, or you feel the pain that it aims to solve, feel free to reach out to me - we can build it together. Backend, frontend, UI/UX designers - everyone's help would come in handy! Just leave a comment or &lt;a href="https://twitter.com/PJeziorowski" rel="noopener noreferrer"&gt;find me @ Twitter&lt;/a&gt; :).&lt;/p&gt;

&lt;h2&gt;
  
  
  Leave your feedback and feature ideas
&lt;/h2&gt;

&lt;p&gt;If you have any feedback or an idea that I could integrate into this project, feel free to leave a comment or &lt;a href="https://twitter.com/PJeziorowski" rel="noopener noreferrer"&gt;reach out to me @ Twitter&lt;/a&gt;! &lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>go</category>
      <category>react</category>
      <category>showdev</category>
    </item>
    <item>
      <title>3 Steps Protocol to boost your Learning Speed and Memory</title>
      <dc:creator>Patryk Jeziorowski</dc:creator>
      <pubDate>Thu, 13 May 2021 18:51:20 +0000</pubDate>
      <link>https://dev.to/pjeziorowski/3-steps-protocol-to-boost-your-learning-speed-and-memory-29dn</link>
      <guid>https://dev.to/pjeziorowski/3-steps-protocol-to-boost-your-learning-speed-and-memory-29dn</guid>
      <description>&lt;p&gt;In this post, I'll show you how you can use hormones that are naturally produced in your body (cortisol and epinephrine, a.k.a adrenaline) to help you learn faster, improve your memory and increase your overall performance.&lt;/p&gt;

&lt;p&gt;If you don't have the time to read the whole article, I'll give you the three steps protocol to follow to get all the benefits. I strongly recommend reading the entire article to understand better the science behind which will allow you to implement it in your life more easily and adjust to your needs if needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  3 Steps Formula to improve your learning and performance
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Start the session with 90 minutes of deep focus learning or work (expect distractions in the first ~10 minutes, as well as at the end of the session)&lt;/li&gt;
&lt;li&gt;Increase adrenaline in your body using the Wim Hof breathing or any other breathing method&lt;/li&gt;
&lt;li&gt;Go into a non-sleep deep rest state (e.g. meditation, or something equally relaxing) for about 10-20 minutes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Additionally, make sure at the end of the day, your sleep is high quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  The magic (science) behind
&lt;/h2&gt;

&lt;p&gt;Many of you may know those hormones (cortisol and adrenaline/epinephrine) as something terrible, released when you are stressed, in a fight-or-flight mode. It's true, partially. I would like you to think about those hormones as hormones of alertness, activation, energy, though.&lt;/p&gt;

&lt;p&gt;In fact, cortisol and epinephrine are vital to your health. They are helping you boost your immune system, be alert and ready to act, boost energy levels, and have many other positive effects, including better learning performance.&lt;br&gt;
Cortisol is vital. You shouldn't call it a stress hormone. It makes you more alert and ready to take action, which is often perceived as anxiety if it raises too high levels. &lt;/p&gt;

&lt;p&gt;Cortisol can be more thought of as a hormone of energy. It makes you want to act, increases your heartbeat, makes you alert and turns off some non-vital processes like digestion.&lt;/p&gt;

&lt;p&gt;In general, cortisol can be a good tool if released at the right time, for the right amount of time, and in the correct dose - the same goes for adrenaline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pubmed.ncbi.nlm.nih.gov/19555723/"&gt;Research says a sharp increase in cortisol and adrenaline leads to better learning and performance&lt;/a&gt;. Epinephrine is actually your best friend when it comes down to learning and remembering. &lt;/p&gt;

&lt;p&gt;It does so because it's usually released before extreme situations, e.g. you'll easily remember every detail of what happened before a car accident, and you'll remember it for a long time. I still remember how I crashed my uncle's car... It's all about how much, when and for how long you release cortisol and epinephrine.&lt;/p&gt;

&lt;p&gt;This is why increasing your adrenaline levels after a learning session may help you learn faster, and remember more. This is something deeply ingrained in human evolution. The same way a child learns not to touch a hot stove, you learn whatever you want to learn, as long as you get the adrenaline boost right after you stopped learning.&lt;/p&gt;

&lt;h2&gt;
  
  
  When those hormones are harmful?
&lt;/h2&gt;

&lt;p&gt;They are harmful when being in a stress state is chronic and not controlled. You can not stay in this highly alert state for long. If you are stressed for more than a day you can consider it harmful.&lt;/p&gt;

&lt;p&gt;Also, remember that you want those shots of hormones right AFTER the learning session, not while learning!&lt;/p&gt;

&lt;h2&gt;
  
  
  How to control it when it's chronic?
&lt;/h2&gt;

&lt;p&gt;Many methods may help you reduce cortisol levels in your body, but it's a topic for another article. Among those, you may find things like... meditation, breathing, deep rest, and all of the well-known relaxation methods.&lt;/p&gt;

&lt;p&gt;Avoid fasting, high-intensity training, cold showers as they all tend to increase cortisol and adrenaline levels in your body. Try to sleep well. Take care of yourself first. The basics are the most important!&lt;/p&gt;

&lt;p&gt;However, if you do everything well, take care of all the basics but still struggle, you can look at supplements like &lt;a href="https://examine.com/supplements/ashwagandha/"&gt;Ashwagandha&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'll cover the topic of dealing with chronic high levels of cortisol in your body in one of the next articles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Last words
&lt;/h2&gt;

&lt;p&gt;To summarize - the so-called stress hormone and adrenaline are not your enemies. They are vital for your well being &lt;a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4034215/"&gt;and immune system&lt;/a&gt;. Use them as tools, take the control and get benefits in your learning and performance.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>biohacking</category>
      <category>learning</category>
      <category>health</category>
    </item>
    <item>
      <title>First week of the 365 Days Of Blogging Challenge!</title>
      <dc:creator>Patryk Jeziorowski</dc:creator>
      <pubDate>Tue, 11 May 2021 19:53:30 +0000</pubDate>
      <link>https://dev.to/pjeziorowski/first-week-of-the-365-days-of-blogging-challenge-4f18</link>
      <guid>https://dev.to/pjeziorowski/first-week-of-the-365-days-of-blogging-challenge-4f18</guid>
      <description>&lt;p&gt;So, &lt;a href="https://dev.to/pjeziorowski/365-days-of-blogging-challenge-or-i-transfer-1000-to-your-bank-account-5dj9"&gt;in the previous post&lt;/a&gt; I announced the challenge of blogging daily for the next 365 days or sending $1000 to a random person chosen from the comments section. &lt;/p&gt;

&lt;p&gt;After doing it I received tons of comments (hopefully not just because of the potential easy $ you may win if I fail :D) about what am I going to write about, about the quantity and quality of the articles and so on. &lt;/p&gt;

&lt;p&gt;A few fellow dev.to members suggested that I should substitute the goal of "1 article daily" by "x words daily" to make sure the published articles are high quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quality over quantity
&lt;/h2&gt;

&lt;p&gt;I agree that goal of writing "X amount of words daily" may lead to higher quality posts, so I decided to follow the suggestions I got in the comments section, and instead of publishing 1 article a day, I'll be writing 500 words daily, or 3500 words weekly. &lt;/p&gt;

&lt;p&gt;This is a quite aggressive goal - as @InHuoOfficial mentioned &lt;a href="https://dev.to/inhuofficial/comment/1ecdi"&gt;in his comment&lt;/a&gt;, this would result in writing basically two novels in one year (over 180K words!).&lt;/p&gt;

&lt;h2&gt;
  
  
  Topics of the posts
&lt;/h2&gt;

&lt;p&gt;To answer all the questions I had about topics of the articles - I'll be writing about things I'm currently working on at &lt;a href="https://www.qovery.com/"&gt;startup I help to build&lt;/a&gt;, about things I'm currently learning, about things I'm interested in. &lt;/p&gt;

&lt;p&gt;I'm a pretty geeky tech person, so it's going to all revolve around software, programming and tech topics. You may also expect stuff about productivity, biohacking, and basically anything that may help you in your tech journey.&lt;/p&gt;

&lt;p&gt;If this challenge goes well, I'll also describe my case study and show you how I managed to write and publish consistently over such a long time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing in Public &amp;amp; Transparency
&lt;/h2&gt;

&lt;p&gt;To keep the challenge fair and give you visibility into the process, besides publishing articles, I'll be publishing drafts of posts to a &lt;a href="https://github.com/pjeziorowski/cyberwritings/tree/main/content/drafts"&gt;public Github repository&lt;/a&gt; (which is the repo of my private blog BTW). &lt;/p&gt;

&lt;p&gt;You'll be able to track what I'm working on, topics of following articles, number of words or whatever you want to know about my writing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Changes in the challenge
&lt;/h2&gt;

&lt;p&gt;So, as I previously mentioned, I'm changing the numbers in the challenge - instead of publishing 1 article a day, I'll write 500 words a day, 3500 words a week, over 180k words (2 novels!) a year. I'll do the counting, reporting and tracking if I meet the challenge's goals every week during the weekend. &lt;/p&gt;

&lt;p&gt;If you want to be informed about progress and the results (and also about the potential $1000 winner in case I fail), you can &lt;a href="https://app.getresponse.com/site2/patrykjeziorowski/?u=yXSNe&amp;amp;webforms_id=BaviR"&gt;sign up to the newsletter&lt;/a&gt; I quickly created for the purpose of this challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stay up to date
&lt;/h2&gt;

&lt;p&gt;Besides the newsletter, I'll publish all the articles (and challenge updates) here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/pjeziorowski"&gt;https://dev.to/pjeziorowski&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cyberwritings.com"&gt;https://cyberwritings.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.cyberwritings.com"&gt;https://medium.cyberwritings.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hashnode.cyberwritings.com"&gt;https://hashnode.cyberwritings.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And drafts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/pjeziorowski/cyberwritings/tree/main/content/drafts"&gt;https://github.com/pjeziorowski/cyberwritings/tree/main/content/drafts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  It all starts this week!
&lt;/h2&gt;

&lt;p&gt;Please let me know what do you think about the changes and the form of the challenge. I'll try to constantly improve the process, but I'd also like to start the challenge ASAP (this week), so any feedback now is highly appreciated! &lt;/p&gt;

</description>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>365 Days of Blogging Challenge</title>
      <dc:creator>Patryk Jeziorowski</dc:creator>
      <pubDate>Mon, 10 May 2021 17:02:55 +0000</pubDate>
      <link>https://dev.to/pjeziorowski/365-days-of-blogging-challenge-or-i-transfer-1000-to-your-bank-account-5dj9</link>
      <guid>https://dev.to/pjeziorowski/365-days-of-blogging-challenge-or-i-transfer-1000-to-your-bank-account-5dj9</guid>
      <description>&lt;p&gt;Everyone sometimes struggles with consistency. Do you want to develop a good habit but often fail after a few days? Well, &lt;strong&gt;you are not alone&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To help myself with that (and possibly you), I come up with the idea of making a &lt;strong&gt;public commitment&lt;/strong&gt; and finding &lt;strong&gt;accountability partners&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Public commitment
&lt;/h3&gt;

&lt;p&gt;This post is my public commitment to writing and publishing articles daily for the next 365 days. It's well over any magic number you hear that is necessary to form a habit. For my liking, it's fair enough.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accountability partners
&lt;/h3&gt;

&lt;p&gt;To hold myself accountable (and to make you more interested in helping me stay consistent), &lt;strong&gt;I declare that I'll pay $1000 to one of my accountability partners&lt;/strong&gt; (by whom I mean anyone who comments on this post on dev.to) &lt;strong&gt;if I miss a day in publishing articles in the next year&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The rules
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;One article a day published, no excuses.&lt;/li&gt;
&lt;li&gt;No article published - a script chooses a random person from the comments section to transfer money to their bank account.&lt;/li&gt;
&lt;li&gt;The way of choosing a random person may change with time - I want to make it automated and public, to provide transparency and fairness (and to prove I'm taking it seriously!). Feel free to propose your ideas on how to approach this problem.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Join me in the challenge
&lt;/h3&gt;

&lt;p&gt;I encourage all of you who want to develop a good habit of putting yourself out there to join the challenge. &lt;/p&gt;

&lt;p&gt;Of course, your numbers may be different. Maybe your goal is to publish just one article a week. Maybe $1000 is too much or too little to make you feel uncomfortable. &lt;/p&gt;

&lt;p&gt;Choose your perfect numbers and join me in the challenge!  If you struggle with this, &lt;a href="https://twitter.com/PJeziorowski"&gt;DM me on Twitter&lt;/a&gt;, and I'll do my best to help you come up with numbers that will work for you.&lt;/p&gt;

&lt;p&gt;And please, let me know what you think about this idea. Feedback highly appreciated!&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How I publish articles to all developer platforms (and my private blog) in one shot</title>
      <dc:creator>Patryk Jeziorowski</dc:creator>
      <pubDate>Sun, 11 Apr 2021 07:47:06 +0000</pubDate>
      <link>https://dev.to/pjeziorowski/how-i-publish-articles-to-all-developer-platforms-and-my-private-blog-in-one-shot-38aj</link>
      <guid>https://dev.to/pjeziorowski/how-i-publish-articles-to-all-developer-platforms-and-my-private-blog-in-one-shot-38aj</guid>
      <description>&lt;h3&gt;
  
  
  Where to host your blog?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.qovery.com/"&gt;Qovery&lt;/a&gt; CEO, Romaric has just started &lt;a href="https://www.heapstack.sh/"&gt;his own blog on hashnode&lt;/a&gt;. I become jealous, so I started thinking about blogging again. I couldn't decide where to publish my content, though:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://hashnode.com/"&gt;Hashnode&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to"&gt;Dev.to&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://cyberwritings.com"&gt;My.own.site&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com"&gt;Medium&lt;/a&gt;?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The answer &amp;gt; everywhere!
&lt;/h3&gt;

&lt;p&gt;To reach the highest number of people, I decided to publish it everywhere with automated content distribution tools. Unluckily, I couldn't find any tool that would meet my needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;allowing me to write just once&lt;/li&gt;
&lt;li&gt;have it published automagically everywhere&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post, I'll show you how I achieved what I wanted - I hope you'll find it helpful on your own blogging adventure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Markdown
&lt;/h3&gt;

&lt;p&gt;My blog uses markdown to build the HTML for the articles. Markdown is quite good for it as it's very portable. All, Hashnode, Dev.to, and Medium support markdown in their APIs. This is perfect - it allows me to write a single markdown file and have it published everywhere.&lt;/p&gt;

&lt;p&gt;After the markdown file (the article) is written down, we need to use APIs. So, the tool needs to take the markdown and deliver it in the correct format to APIs of all the different platforms we target.&lt;/p&gt;

&lt;h3&gt;
  
  
  CLI
&lt;/h3&gt;

&lt;p&gt;The first version of the tool is a simple CLI app. It's relatively fast to create and validates the concept quickly - we don't need backends, UIs or any other crazy stuff from the very beginning. BTW, I named the app &lt;strong&gt;Rollout&lt;/strong&gt; to refer to it in this post more easily, hah!&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Rollout
&lt;/h3&gt;

&lt;p&gt;I won't go over the details of how the CLI is implemented (as it's not the topic of this post, it's very simple, though - you can see the code &lt;a href="https://github.com/pjeziorowski/rollout"&gt;here&lt;/a&gt;).&lt;br&gt;
I'll jump straight into showing how to use the tool and how simple it is to have your posts published everywhere.&lt;/p&gt;

&lt;h4&gt;
  
  
  1 &lt;strong&gt;Install the tool&lt;/strong&gt;
&lt;/h4&gt;

&lt;h4&gt;
  
  
  MacOS
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew tap pjeziorowski/rollout-cli
brew &lt;span class="nb"&gt;install &lt;/span&gt;rollout-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Windows/Linux
&lt;/h4&gt;

&lt;p&gt;If you are on Linux/Windows, for now you need to build the app &lt;a href="https://github.com/pjeziorowski/rollout"&gt;from the source&lt;/a&gt;. I'll improve it soon!&lt;/p&gt;

&lt;h4&gt;
  
  
  2 &lt;strong&gt;Write the article&lt;/strong&gt; - this is definitely the most challenging part! Luckily for you, I wrote one that you can use for the test!
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"---
title: "&lt;/span&gt;Test Rollout CLI&lt;span class="s2"&gt;"
canonical_url: https://google.com/test
tags: [Blogging, Automation]
---  
## Hello Rollout!
"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ./test.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3 &lt;strong&gt;Distribute the article&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rollout test.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;P.S. you also need to provide API tokens for the tool to use, it'll show you a hint you when you give it a try.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Congrats! Your post is now published everywhere
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Hey... Did you forget somethin? You only published to Dev.to, Hashnode and Medium. What about your (and mine!) private blog?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, in my workflow, I publish posts to my blog by simply pushing markdown to my Github repository, so the tool doesn't have to do anything more. It's enough for me now, but in the future, &lt;strong&gt;Rollout&lt;/strong&gt; could also be integrated with any headless CMS, for example. If I had a WordPress blog, I would simply use the WordPress API to push the article there. Luckily for me, all I have to do is store my posts on Github. If it's the same for you, welcome to the happy bloggers club!&lt;/p&gt;

&lt;h3&gt;
  
  
  It's open-sourced!
&lt;/h3&gt;

&lt;p&gt;As I mentioned earlier, you can see the tool's code in its &lt;a href="https://github.com/pjeziorowski/rollout"&gt;Github repository&lt;/a&gt;.&lt;br&gt;
If you like the idea or the tool works for you - please give it a star and leave a feedback comment (if they are yet implemented on this site, ha) or contact me on &lt;a href="https://twitter.com/pjeziorowski"&gt;Twitter&lt;/a&gt;/&lt;a href="https://www.linkedin.com/in/patrykjeziorowski/"&gt;Linkedin&lt;/a&gt; directly.&lt;/p&gt;

&lt;p&gt;If I see interest in the tool, I'll put more work to make it more versatile and probably create a UI (SPA) and some backend for managing the content and configuration. Contributions and suggestions are also very welcome!&lt;/p&gt;

&lt;h2&gt;
  
  
  BTW - this article was published with Rollout!
&lt;/h2&gt;

</description>
      <category>blogging</category>
      <category>automation</category>
      <category>productivity</category>
    </item>
    <item>
      <title>A month after switching from Slack to Discord in a remote-first tech startup</title>
      <dc:creator>Patryk Jeziorowski</dc:creator>
      <pubDate>Thu, 14 May 2020 18:02:36 +0000</pubDate>
      <link>https://dev.to/qovery/a-month-after-switching-from-slack-to-discord-in-a-remote-first-tech-startup-3f1l</link>
      <guid>https://dev.to/qovery/a-month-after-switching-from-slack-to-discord-in-a-remote-first-tech-startup-3f1l</guid>
      <description>&lt;p&gt;Nowadays, Slack is often the default choice for an online communication tool in the tech industry. Startups, enterprises, open-source projects - they all use Slack to communicate within their organization but sometimes also with their users and community. Our startup was no different. In this article, I explain what made us look for Slack alternative and what are our impressions after a month of switching to Discord, so you can learn from those before you make your decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  The background
&lt;/h2&gt;

&lt;p&gt;Qovery is a remote-first startup founded at the end of the last year. I was hired as the first full-time employee. We are all distributed and work remotely. All our communication happens online. Meetings, plannings, brainstorming sessions, talks with founders, technical discussions, and all the rest - it all happens online without exception.&lt;/p&gt;

&lt;p&gt;Our product is focused on solving the developers' problems. We help them in deploying their applications on the cloud. We work with all types of programmers - passionate hobbyists, innovative startup guys, serious enterprise architects but also programming newbies. This is why we work with many different kinds of applications and need to be there to answer various community questions.&lt;/p&gt;

&lt;p&gt;This all makes it crucial for us to have a tool that allows communicating flawlessly with our community but also internally within our startup, as all our communication happens online.&lt;/p&gt;

&lt;h2&gt;
  
  
  What made us switch
&lt;/h2&gt;

&lt;p&gt;Slack is not a bad tool. In fact, there's a reason why it's so popular. But, like all tools, it's not perfect.&lt;/p&gt;

&lt;p&gt;What we didn't like was primarily the message history limit. On Slack, you have to pay per user. If you want to preserve the chat history for a growing number of community users, this can get pretty expensive quickly. In this regard, it doesn't really support our needs. Don't get me wrong - we are willing to pay for the tools we use, but Slack pricing model is not well suited for a community communication tool.&lt;/p&gt;

&lt;p&gt;We talk (voice) a lot. We think it's important to communicate effectively using our tools, especially when that's the only channel of our verbal communication. Slack was not doing its job well in this regard. Sound, connection issues, and noticeable delay of sound despite decent internet connection made the experience at least not perfect. It's not only Slack issue - we tried many other tools, too, and they all often face similar problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution?
&lt;/h2&gt;

&lt;p&gt;Discord? It's a tool for online gamers, isn't it? Maybe, but... "On paper" it looked like it could fix all the problems we had with Slack. No history limit, focus on great voice communication... We decided to ignore the "it's a tool for gamers only' stereotype and took a bold move to give it a try in our organization. What's the result?&lt;/p&gt;

&lt;h3&gt;
  
  
  What was expected to be better is in fact better
&lt;/h3&gt;

&lt;p&gt;In practice, all promises Discord gave us, in real day-to-day usage, turned out to be true: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pricing model - we no longer have to pay per user to keep our chat history. You could use it, in fact, for free. We pay less than 80$ per month now for even better audio quality and HD video calls. The price won't change with our growing number of community users.&lt;/li&gt;
&lt;li&gt;Voice / Video chats. This is where Discord shines. The audio quality is excellent, screen sharing works flawlessly, the latency between you speaking and your listeners hearing it is much lower than on Slack and other solutions. Also, what I really like is you do not have to call somebody directly or prepare a group calls - you can just enter a voice channel (Teamspeak and Ventrilo nostalgic memories...).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What was expected to be worse, is in fact worse
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Integrations - we were aware that as a mainly gamers' tool, Discord lacks some of the integrations we used on Slack. Slack has a huge advantage in this space. However, thanks to webhooks combined with Zapier, we were able to configure all integrations we had before also Discord.&lt;/li&gt;
&lt;li&gt;Threaded messages - we were aware of the fact it's missing in Discord, and in fact, it's painful. I do miss it. I wish it was there.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What surprised positively
&lt;/h2&gt;

&lt;p&gt;What surprised me from the first second I launched Discord app was the smoothness and responsiveness of the app. It runs truly, noticeably, SMOOTHER and FASTER than Slack. Using Slack in comparison to Discord feels like being in a slow mode for me now. I completely didn't expect this (in fact I was not aware that Slack was so clunky). It's simply a pleasure to use Discord.&lt;/p&gt;

&lt;p&gt;Another thing that surprised me is that Discord seems to grow really fast. In just a month of our usage, the added noise suppression, which eliminates random noises from your background and an option to turn on the webcam during talks on group channels.&lt;/p&gt;

&lt;h2&gt;
  
  
  What surprised negatively
&lt;/h2&gt;

&lt;p&gt;What surprised me negatively the most is a very inconvenient upload of very long texts (e.g. application logs). If your copy-paste a very long text, it won't be displayed in the chat in any way - it appears as a text file to download instead.&lt;/p&gt;

&lt;p&gt;Another thing - file upload size limits are a bit restrictive. There are no limits for the workspace like on Slack, but for a single file upload, the limits are pretty harsh (8MB / 50MB/ 100MB depending on your plan). This means you'll have to share your files elsewhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  My final thoughts after one month of switching to Discord
&lt;/h2&gt;

&lt;p&gt;I'm selfish. I wish Discord would switch focus from gamers to professionals. It would be then the perfect tool for any IT organization. But for now, these are just my dreams - the reality is that Discord is much better for voice conversations. The app works much smoother and feels more responsive &amp;amp; modern. Chat is worse due to the lack of threaded messages.&lt;/p&gt;

&lt;p&gt;In my opinion, you should use Discord if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you value quality voice conversations&lt;/li&gt;
&lt;li&gt;you communicate a lot with your users/community&lt;/li&gt;
&lt;li&gt;you don't mind using gamers focused tool (the UI is less suited for enterprise usage than Slack)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think Discord may gradually turn into a more business-oriented tool. They add features that are useful for IT teams. There's yet a bit to be done, but I hope it will naturally go in this direction. There are a lot of &lt;a href="https://discord.com/open-source"&gt;open-source communities using Discord&lt;/a&gt; to build their communities at the moment (including Rust, Django, Hasura, Typescript, and many others) and I believe Discord's popularity will grow in our industry.&lt;/p&gt;

&lt;p&gt;And, it the end, &lt;a href="https://blog.discord.com/why-discord-is-switching-from-go-to-rust-a190bbca2b1f"&gt;they use Rust&lt;/a&gt; so no wonder why Discord works so smooth! :)&lt;/p&gt;

&lt;p&gt;P.S. If you want to try Discord or ask me or our team any question, feel free to join &lt;a href="https://discord.qovery.com"&gt;our Discord server&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>startup</category>
    </item>
    <item>
      <title>Productive and simple way to deploy Dockerized applications </title>
      <dc:creator>Patryk Jeziorowski</dc:creator>
      <pubDate>Wed, 06 May 2020 18:51:22 +0000</pubDate>
      <link>https://dev.to/qovery/productive-and-simple-way-to-deploy-dockerized-applications-56f4</link>
      <guid>https://dev.to/qovery/productive-and-simple-way-to-deploy-dockerized-applications-56f4</guid>
      <description>&lt;p&gt;In recent years, Docker has been becoming more and more popular tool used to deploy web applications. &lt;a href="https://www.datadoghq.com/docker-adoption/" rel="noopener noreferrer"&gt;According to Datadog&lt;/a&gt; in 2018, the adoption of Docker in large organizations reached about 47 percent and almost 20 percent in small organizations. This report it two years old - no doubt Docker is even more common now.&lt;/p&gt;

&lt;p&gt;In my opinion, knowing Docker basics is an essential tool in the toolbox of every software engineer, especially in the web development ecosystem. In this article, I'll demonstrate the easiest way to Dockerize and deploy a simple application. Before we dive deep into practical steps, let's first answer two essential questions - "What is Docker" and "Why should I use it" in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker in a nutshell
&lt;/h2&gt;

&lt;p&gt;Docker is a tool that makes it easy to build and deploy your applications, typically to the cloud environment. It allows you to package your application in a container that contains your app with all of the things it needs, such as libraries and other dependencies. Then, this package can be run on any machine with a Docker engine installed, no matter the underlying configuration or system distribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should I use Docker?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;It works on my machine&lt;/code&gt; sentence has become a meme in the software world. You can even get a sticker on your laptop:&lt;/p&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%2Fz2jt18liia6u0k52qb0u.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%2Fz2jt18liia6u0k52qb0u.jpg" alt="It works on my machine"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Making applications run consistently in various environments is one of the issues addressed very well by Docker.&lt;/p&gt;

&lt;p&gt;Docker makes sure that your containerized applications run in the same way on your machine, on your friend's machine, and on the AWS server (and anywhere else where Docker engine is installed). It is truly a superpower. As a developer, you no longer need to worry about the underlying system. After you Dockerize your app, you can be sure that it behaves in the same manner in your development, testing, and production environments, as well as on your local machine. It makes building and testing applications way more comfortable than it was before.&lt;/p&gt;

&lt;p&gt;Another reason why you should be interested in Docker is the popularization of cloud, microservices, and Kubernetes. Docker is the first-class citizen in the cloud-native world, so if you want to take the full advantage of scalable, cloud-native application architectures, Docker is the way to go.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to deploy Docker containers
&lt;/h2&gt;

&lt;p&gt;Let's move on to the practical application and usage of Docker. We'll now build a very simple web application that responds to HTTP requests, dockerize it and deploy to &lt;a href="https://docs.qovery.com/docs/getting-started/what-is-qovery/" rel="noopener noreferrer"&gt;Qovery - a scalable Container as a Service platform&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a simple application
&lt;/h3&gt;

&lt;p&gt;For the sake of simplicity, we'll create a simple Node.js application that returns a &lt;code&gt;Hello, World&lt;/code&gt; text in response to HTTP requests. I choose Node.js here because it's simple and popular technology, but you can use Docker with basically any language and framework.&lt;/p&gt;

&lt;p&gt;Let's create an empty folder for our new application and initialize an empty Git repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;deploying-docker
&lt;span class="nb"&gt;cd &lt;/span&gt;deploying-docker
git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, create &lt;code&gt;app.js&lt;/code&gt; file with the source code of our server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hostname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.0.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server running at http://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;hostname&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="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is a very simple server that returns "Hello World" text on its root endpoint. After it's done, we want to make this app run in a Docker container. To do so, we need to create a Dockerfile.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Dockerfile?
&lt;/h3&gt;

&lt;p&gt;Besides containers, Docker uses the concept of &lt;strong&gt;Images&lt;/strong&gt;. Image is a template used to create and run containers. Dockerfile describes the steps required to build the image. Later on, this image is used as a template to run containers with your application.&lt;/p&gt;

&lt;p&gt;You can think about images and containers as a good analogy to classes and objects (instances of a given class) in the Object-Oriented Programming world.&lt;/p&gt;

&lt;p&gt;Create a Dockerfile that will allow us to run our Node.js app in a container. Create a file named Dockerfile with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:13-alpine&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /usr/src/app

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/src/app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; node app.js&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's discuss all lines of the Dockerfile:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FROM node:13-alpine&lt;/code&gt; specifies the base of our Docker image. It's a base used to get started with building an image.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RUN mkdir -p /usr/src/app&lt;/code&gt; creates a new empty folder in &lt;code&gt;/usr/src/app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WORKDIR /usr/src/app&lt;/code&gt; defines the &lt;em&gt;working directory&lt;/em&gt; of our container&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COPY . .&lt;/code&gt; adds the contents of our application to the container&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;EXPOSE 3000&lt;/code&gt; informs Docker that the container listens on the specified network port at runtime &lt;/li&gt;
&lt;li&gt;and, finally: &lt;code&gt;CMD node app.js&lt;/code&gt; is the command that starts our application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we got all basic things we need to run our application in a Docker container! Let's try it out:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build Docker image of the app using &lt;code&gt;docker build testing/docker .&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run a container with our application by executing &lt;code&gt;docker run -p 3000:3000 testing/docker&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;the &lt;code&gt;-p 3000:3000&lt;/code&gt; flag makes container port &lt;code&gt;3000&lt;/code&gt; accessible on your &lt;code&gt;localhost:3000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Great&lt;/strong&gt;! The container is up. Run &lt;code&gt;docker ps&lt;/code&gt; to see the list of running containers and confirm that it is indeed running.&lt;/p&gt;

&lt;p&gt;Now open a browser at &lt;code&gt;http://localhost:3000&lt;/code&gt; to see that the application in a container responded with &lt;code&gt;Hello, World&lt;/code&gt; message.&lt;/p&gt;

&lt;p&gt;Did it work? Great. Our app works well in the Docker container. It's adorable, but we want to share our app with the world - running applications only on our own machine won't make us millionaires!&lt;/p&gt;

&lt;h3&gt;
  
  
  Container as a Service
&lt;/h3&gt;

&lt;p&gt;To deploy our Dockerized application, we'll use Qovery. It's a Container as a Service platform that allows us to deploy Dockerized apps without any efforts. Qovery is free up to three applications (and databases!) in the community version.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Qovery CLI
&lt;/h3&gt;

&lt;p&gt;To Sign Up and install the CLI, you can follow the steps described in &lt;a href="https://docs.qovery.com/docs/using-qovery/interface/cli/#sign-up" rel="noopener noreferrer"&gt;this link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After you have access to Qovery, it's time to deploy the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy the docker container
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;qovery init&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Choose application name, e.g., &lt;code&gt;node-app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Choose project name, e.g., &lt;code&gt;testing-docker&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Commit and push your changes to Github: &lt;code&gt;git add . ; git commit -m "Initial commit" ; git push -u origin master"&lt;/code&gt; (create an empty repository beforefor your application on Github before if it's not done yet)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Voila! That's all. Your Dockerized application is being deployed as a Docker container. To deploy a Docker container on Qovery, all you need is a Dockerfile that describes containers with your application + running &lt;code&gt;qovery init&lt;/code&gt; command to initialize Qovery. From now on, Qovery will build and deploy your Dockerized application after you make any changes in your repository to scalable Kubernetes clusters as a Docker container.&lt;/p&gt;

&lt;p&gt;To check that your application is in fact deploying, run &lt;code&gt;qovery status&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;BRANCH NAME       | STATUS  | ENDPOINTS                            | APPLICATIONS    | DATABASES
master            | running | https://some.url.qovery.io           | node-app  | 

APPLICATION NAME  | STATUS  | DATABASES
node-app          | running | 

DATABASE NAME     | STATUS  | TYPE       | VERSION | ENDPOINT | PORT     | USERNAME | PASSWORD | APPLICATIONS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In this guide, you learned the essential basics of Docker. You also learned why you should be interested in using it, and how to deploy your application to the cloud as a Docker container. This is all you need to know to improve your development experience and deploy your application to the cloud with ease! If you have any questions or feedback please do let me know in the comments or join &lt;a href="https://discord.qovery.com" rel="noopener noreferrer"&gt;Qovery Discord server&lt;/a&gt; and feel free to speak your mind.&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>docker</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Do you use a monorepo?</title>
      <dc:creator>Patryk Jeziorowski</dc:creator>
      <pubDate>Thu, 09 Apr 2020 13:33:01 +0000</pubDate>
      <link>https://dev.to/pjeziorowski/do-you-use-a-monorepo-2l1n</link>
      <guid>https://dev.to/pjeziorowski/do-you-use-a-monorepo-2l1n</guid>
      <description>&lt;p&gt;I'm curious how many of you (and how, if so) use a monorepo. Do you use it for both backend and frontend? Do you use any tools to help you with that?&lt;/p&gt;

&lt;p&gt;I would be grateful for your answers.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>git</category>
      <category>devops</category>
    </item>
    <item>
      <title>How to build and deploy realtime GraphQL APIs in a few minutes</title>
      <dc:creator>Patryk Jeziorowski</dc:creator>
      <pubDate>Thu, 09 Apr 2020 09:18:50 +0000</pubDate>
      <link>https://dev.to/qovery/how-to-build-and-deploy-realtime-graphql-apis-in-a-few-minutes-5bap</link>
      <guid>https://dev.to/qovery/how-to-build-and-deploy-realtime-graphql-apis-in-a-few-minutes-5bap</guid>
      <description>&lt;p&gt;Before we dive deep into details, I'll &lt;strong&gt;quickly describe the tools I used&lt;/strong&gt; to build and deploy a realtime GraphQL API and tell you &lt;strong&gt;why you should fall in love with GraphQL&lt;/strong&gt; and all the tools I used.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, why to use GraphQL?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GraphQL&lt;/strong&gt; is a query language for APIs and a runtime for fulfilling those queries with existing data. GraphQL provides a &lt;strong&gt;schema&lt;/strong&gt; that describes the API and allows clients (e.g. your frontend or mobile application) to easily fetch data they want and nothing more.&lt;/p&gt;

&lt;p&gt;Here is what you get from using GraphQL instead of standard RESTful APIs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GraphQL queries get exactly what you need, nothing more and nothing less&lt;/li&gt;
&lt;li&gt;Instead of making multiple requests to fetch required data, you make just one request to one endpoint&lt;/li&gt;
&lt;li&gt;GraphQL schema is typed, what makes the contract between frontend and backend clear and understandable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are a frontend engineer, &lt;strong&gt;you will not like to consume other APIs than GraphQL after trying it out&lt;/strong&gt;. It makes your life so much more pleasurable and easy.&lt;/p&gt;

&lt;p&gt;You don't need to know GraphQL to follow this article. All you need to know is that GraphQL allows you to define contract between frontend and backend and do operations on the data you are interested in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Productivity boosting tools
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Hasura&lt;/strong&gt; is an open source engine that connects to your databases &amp;amp; microservices and auto-generates a production-ready GraphQL backend. By using Hasura in conjunction with &lt;strong&gt;Qovery&lt;/strong&gt; (platform that combines the power of Kubernetes, the reliability of AWS and the simplicity of Heroku to allow developers deploy their apps with pleasure), you get a &lt;strong&gt;blazing fast, auto-scallable and extensible solution to quickly build your applications&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Hasura?
&lt;/h3&gt;

&lt;p&gt;Consuming GraphQL APIs is a pleasure. We'd like to have more GraphQL APIs. But those APIs do not come out of nowhere. Somebody has to implement them first - the data won't just flow out of the database through the schema to your frontend automagically, right? Well... with Hasura it will!&lt;/p&gt;

&lt;p&gt;Hasura allows you to bootstrap a realtime GraphQL API in seconds by simply modeling your data. Hasura will do the hard work of translating your needs into queries to the database and translating them to GraphQL schema. Thanks to this, all you need to do is to define the data you want to store in the database - Hasura will do the rest.&lt;/p&gt;

&lt;p&gt;This is unbelievable how much time it saves. If you don't believe, try implementing a GraphQL server yourself - with all the featuers and options that Hasura offers.&lt;/p&gt;

&lt;p&gt;If you have doubts about flexibility - you don't have to worry. If you need to perform a very custom business logic, you can implement this part in any language you want and connect it to Hasura engine. This way you will not only save a lot of time, but also have flexibility to write your custom code if needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Qovery?
&lt;/h3&gt;

&lt;p&gt;Managing infrastructure is hard and takes time. &lt;strong&gt;Developers want to focus on building their apps instead of wasting time on managing servers or databases&lt;/strong&gt;. Qovery is tool that does it all for you - all you have to do is to write your application code. It's *&lt;em&gt;powered by Docker and Kubernetes *&lt;/em&gt; underneath, so you get all the benefits of using those modern tools without the complexity and costs of learning and managing them.&lt;/p&gt;

&lt;p&gt;Qovery is also a great fit for Hasura - its &lt;strong&gt;free plan allows you to deploy Hasura and database for free, without any limits, performance degradations or putting your app to sleep&lt;/strong&gt; like it's done on other platforms.&lt;/p&gt;

&lt;p&gt;If you have any questions regarding this post or other things, feel free to reach me on &lt;a href="https://discord.qovery.com" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hasura deployment on Qovery
&lt;/h2&gt;

&lt;p&gt;Deploying Hasura on Qovery is really easy. All you have to do is to bootstrap a project using Qovery CLI in a Git repository &amp;amp; export environment variables required by Hasura.&lt;/p&gt;

&lt;p&gt;1/ Bootstrap a project with Qovery CLI (the script will ask you for project and application name, which you can choose as you like)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;qovery template hasura
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2/ Point Hasura to your Postgres database and enable Hasura Console using environment variables&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;qovery application &lt;span class="nb"&gt;env &lt;/span&gt;add HASURA_GRAPHQL_DATABASE_URL &lt;span class="s1"&gt;'$QOVERY_DATABASE_MY_POSTGRESQL_DATABASE_CONNECTION_URI'&lt;/span&gt;
qovery application &lt;span class="nb"&gt;env &lt;/span&gt;add HASURA_GRAPHQL_ENABLE_CONSOLE &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3/ Commit and push your changes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "Deploy Hasura on Qovery"
git push -u origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Well done!&lt;/strong&gt; After pushing changes, Postgres and Hasura deployment will start. You can use &lt;code&gt;‍qovery status --watch&lt;/code&gt; to track the progress. Once the deployment is done, you’ll see your Hasura application URL in the status:&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%2Fuploads-ssl.webflow.com%2F5de176c0d41c9b4a1dbbb0aa%2F5e8d9e3c75a7e46396d483d9_status.png" 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%2Fuploads-ssl.webflow.com%2F5de176c0d41c9b4a1dbbb0aa%2F5e8d9e3c75a7e46396d483d9_status.png" alt="Qovery Status"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating realtime GraphQL APIs
&lt;/h2&gt;

&lt;p&gt;Navigate to your Hasura application URL and choose Data tab in the console:&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%2Fuploads-ssl.webflow.com%2F5de176c0d41c9b4a1dbbb0aa%2F5e8d9e5e4788f066d395e4ac_data-tab.png" 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%2Fuploads-ssl.webflow.com%2F5de176c0d41c9b4a1dbbb0aa%2F5e8d9e5e4788f066d395e4ac_data-tab.png" alt="Hasura Console"&gt;&lt;/a&gt;&lt;br&gt;
In this section we'll configure our data model. Now, click on the &lt;strong&gt;Create Table&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;You’ll see the table creator. We are going to create a simple "Todo" items table. We'll name it "todos" and the table will contain three columns:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. id - unique identifier of given "Todo" item
2. title
3. description - optional description of "Todo" item
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Fill the form as in the screenshots below to prepare the table.&lt;/p&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%2Fuploads-ssl.webflow.com%2F5de176c0d41c9b4a1dbbb0aa%2F5e8d9eccfd0cf4040e3017ff_table-name.png" 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%2Fuploads-ssl.webflow.com%2F5de176c0d41c9b4a1dbbb0aa%2F5e8d9eccfd0cf4040e3017ff_table-name.png" alt="Table"&gt;&lt;/a&gt;&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%2Fuploads-ssl.webflow.com%2F5de176c0d41c9b4a1dbbb0aa%2F5e8d9edd3f6105fd73982190_table-columns.png" 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%2Fuploads-ssl.webflow.com%2F5de176c0d41c9b4a1dbbb0aa%2F5e8d9edd3f6105fd73982190_table-columns.png" alt="Table"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the end, we should specify our id column as a Primary Key.‍&lt;/p&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%2Fuploads-ssl.webflow.com%2F5de176c0d41c9b4a1dbbb0aa%2F5e8d9ef4d87c6c421133c2e7_primary-key.png" 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%2Fuploads-ssl.webflow.com%2F5de176c0d41c9b4a1dbbb0aa%2F5e8d9ef4d87c6c421133c2e7_primary-key.png" alt="Primary Key"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The table is ready to be created. Click &lt;strong&gt;Add Table&lt;/strong&gt; button at the bottom of the page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Voila!&lt;/strong&gt; The table has been created in Postgres and Hasura has exposed GraphQL APIs to interact with our data.&lt;/p&gt;
&lt;h2&gt;
  
  
  Testing GraphQL APIs
&lt;/h2&gt;

&lt;p&gt;To test the GraphQL API, navigate to the GraphiQL tab and run the following query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;query&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="n"&gt;todos&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="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuploads-ssl.webflow.com%2F5de176c0d41c9b4a1dbbb0aa%2F5e8da0edcf123c19f5918594_graphiql.png" 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%2Fuploads-ssl.webflow.com%2F5de176c0d41c9b4a1dbbb0aa%2F5e8da0edcf123c19f5918594_graphiql.png" alt="GraphiQL"&gt;&lt;/a&gt;&lt;br&gt;
As you can see, Hasura returned an empty array of "Todo" items. Let’s add a "Todo" item by executing the following query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&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="n"&gt;insert_todos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;objects&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="n"&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;"My first TODO"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"It's very important TODO item"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;affected_rows&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After you run the above query, in the response you'll see information about one affected row. Congrats! You have created a first "Todo" item. Let's now move further to a more interesting topic.&lt;/p&gt;

&lt;h2&gt;
  
  
  GraphQL realtime APIs
&lt;/h2&gt;

&lt;p&gt;It's time to use a realtime GraphQL APIs - &lt;strong&gt;GraphQL Subscriptions&lt;/strong&gt;. Subscription allows you to fetch data and get updates about any changes that occur in data you are interested in.&lt;/p&gt;

&lt;p&gt;In the GraphiQL, run the following query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;subscription&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="n"&gt;todos&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="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the response in the right-hand of console you'll see a "Todo" item you have created previously. That's great. Let's now test if the subscription really works - open one more Hasura console in a separate browser tab and navigate to GraphiQL.&lt;/p&gt;

&lt;p&gt;Execute the following query a few times:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&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="n"&gt;insert_todos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;objects&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="n"&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;"Another TODO to test subscriptions"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Subscriptions!"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;affected_rows&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the same time, keep an eye at the subscription. Each and every newly created "Todo" item automagically appears in the subscription response!&lt;/p&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%2Fuploads-ssl.webflow.com%2F5de176c0d41c9b4a1dbbb0aa%2F5e8d9de17e6837d53983c32f_subscription.gif" 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%2Fuploads-ssl.webflow.com%2F5de176c0d41c9b4a1dbbb0aa%2F5e8d9de17e6837d53983c32f_subscription.gif" alt="Realtime GraphQL"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;By following this article you quickly deployed a realtime GraphQL backend using Qovery, Hasura and Postgres database.&lt;/p&gt;

&lt;p&gt;Using this stack saves you tons of time. Deploying it on Qovery is extremely easy. We take care of your application and your database. With Qovery and Hasura all you have to do to expose quality, realtime GraphQL backend is just a few clicks. After minutes your application is ready - define your data schema and expose GraphQL API to the world!&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>javascript</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
