<?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: Cynthia HENAFF</title>
    <description>The latest articles on DEV Community by Cynthia HENAFF (@monsieur_riz).</description>
    <link>https://dev.to/monsieur_riz</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%2F302045%2F0861ac41-250e-461a-b196-8fd76640e009.jpg</url>
      <title>DEV Community: Cynthia HENAFF</title>
      <link>https://dev.to/monsieur_riz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/monsieur_riz"/>
    <language>en</language>
    <item>
      <title>Get started with Raspberry Pi and start hacking</title>
      <dc:creator>Cynthia HENAFF</dc:creator>
      <pubDate>Fri, 10 Feb 2023 11:28:27 +0000</pubDate>
      <link>https://dev.to/monsieur_riz/get-started-with-raspberry-pi-and-start-hacking-1fpk</link>
      <guid>https://dev.to/monsieur_riz/get-started-with-raspberry-pi-and-start-hacking-1fpk</guid>
      <description>&lt;p&gt;Since 2022 I have been lucky enough to have a garden and I love to watch the plants and shrubs grow and the birds fly by. Spending my time looking out of the office window inspired me to come up with a project idea: a time-lapse camera. Usually, I would have gone with an Arduino or an ESP with a camera module. However, this time, I wanted to test and train myself with the Raspberry Pi. So, I'm taking this opportunity to share with you the basics and the new knowledge I acquired during this time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Raspberry Pi?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zmzil0i44mxrguinbh3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zmzil0i44mxrguinbh3.jpg" alt="Raspberry Pi logo&amp;lt;br&amp;gt;
" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Raspberry Pi is a series of credit-card sized mini-computers (except for a few models I'll talk about below), designed in the UK in 2012 by the Raspberry Pi Foundation. The purpose of this computer was originally to promote computer science education in schools by providing a cheap and easy-to-use computer. Since its creation, it has become a worldwide success with developers, tinkerers and technology enthusiasts in general.&lt;/p&gt;

&lt;p&gt;Indeed, the Raspberry Pi has everything to please:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;small size&lt;/li&gt;
&lt;li&gt;attractive price&lt;/li&gt;
&lt;li&gt;low-power consumption&lt;/li&gt;
&lt;li&gt;many electronic inputs/outputs&lt;/li&gt;
&lt;li&gt;Wi-Fi, Bluetooth&lt;/li&gt;
&lt;li&gt;HDMI, USB&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is used in many projects, from a computer for yourself or a child, to a home file server, a NAS, a home automation control device, or even a media player on the TV and a retro gaming console.&lt;/p&gt;
&lt;h3&gt;
  
  
  Different models of Raspberry Pi
&lt;/h3&gt;

&lt;p&gt;There are currently several Raspberry Pi models on the market, each with different features and uses. Here is a non-exhaustive list of the most popular models.&lt;/p&gt;
&lt;h4&gt;
  
  
  Raspberry Pi 4
&lt;/h4&gt;

&lt;p&gt;The latest model. It is the most powerful model in the range and is recommended for performance-intensive applications such as development or streaming gaming.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fma759xg5joaj40yjjf5c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fma759xg5joaj40yjjf5c.png" alt="Raspberry Pi 4" width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Raspberry Pi 400
&lt;/h4&gt;

&lt;p&gt;This new Raspberry is a computer built right into the keyboard!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxhqbpa0rc88xjl4j7rwd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxhqbpa0rc88xjl4j7rwd.png" alt="Raspberry Pi 400" width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F01il0j4ftl86quveq3ac.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F01il0j4ftl86quveq3ac.jpg" alt="Raspberry Pi 400 kit" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Raspberry Pi 3
&lt;/h4&gt;

&lt;p&gt;A slightly less powerful model than the Raspberry Pi 4, but still very powerful. It is recommended for applications requiring fewer resources, such as web development or home automation.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6a1navow4gpdcfdqlrms.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6a1navow4gpdcfdqlrms.jpeg" alt="Raspberry Pi 3" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Raspberry Pi Zero
&lt;/h4&gt;

&lt;p&gt;The smallest and cheapest model in the range, equipped with Wi-Fi and Bluetooth.&lt;/p&gt;

&lt;p&gt;It is recommended for DIY projects and applications that do not require high performance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyel3jatvpgg3mk61dzip.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyel3jatvpgg3mk61dzip.jpeg" alt="Raspberry Pi Zero" width="800" height="639"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Raspberry Pi Zero 2 W
&lt;/h4&gt;

&lt;p&gt;The latest model, identical to the Raspberry Pi Zero but five times faster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fet3a42qntjh2we0m4w5i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fet3a42qntjh2we0m4w5i.png" alt="Raspberry Pi Zero 2 W" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is important to choose the most suitable Raspberry Pi model for your needs based on performance and functionality.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why are Raspberry Pi prices so high at the moment?
&lt;/h3&gt;

&lt;p&gt;The price of the different models of Raspberry Pi is normally between 10 and 40€, however at the moment stock-outs are more and more observed and the prices are almost twice as high, but why?&lt;/p&gt;

&lt;p&gt;This is mainly due to a shortage of semiconductors, i.e. the electronic chips that make up our computers (transistors, processors, RAM, graphics units, etc.). This shortage is due to the high demand for laptops, tablets and other electronic devices, which has increased sharply with the advent of remote working and lock-ups. The Raspberry Pi, which is a cheap microcomputer, is particularly affected by this shortage, as it has a low profit margin and uses partly older, and therefore cheaper, technology. As a result, the foundation that produces the Raspberry Pi is struggling to find chips at affordable prices or in sufficient quantity.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up your Raspberry Pi
&lt;/h2&gt;

&lt;p&gt;The Raspberry Pi documentation is known to be very comprehensive, accessible and regularly updated. It is available online at the official Raspberry Pi website and covers a wide range of topics, from installing the OS to using different devices and accessories.&lt;/p&gt;

&lt;p&gt;The documentation is well-structured and easy to navigate, making learning about the Raspberry Pi affordable for everyone, whether you are a beginner or an experienced user.&lt;/p&gt;

&lt;p&gt;In addition, there is an active community of Raspberry Pi developers and users who share their knowledge and experience on the internet, which can be an excellent source of further assistance.&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;A minimum of hardware is required to get started with the installation of your Raspberry Pi. You will need :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Raspberry Pi&lt;/li&gt;
&lt;li&gt;A sufficiently powerful power supply for the Raspberry Pi&lt;/li&gt;
&lt;li&gt;A microSD card&lt;/li&gt;
&lt;li&gt;A USB SD card reader&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Configuring the Raspberry Pi with Raspberry Pi Imager
&lt;/h3&gt;

&lt;p&gt;To install our Raspberry Pi, we will use the Raspberry Pi Imager software which you can now download and install.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.raspberrypi.com/software/" rel="noopener noreferrer"&gt;https://www.raspberrypi.com/software/&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
Once you have completed this first step, connect your microSD to your computer and launch Raspberry Pi Imager.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8luheyim0q0bto51s0xq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8luheyim0q0bto51s0xq.png" alt="Raspberry Pi Imager" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Operating System
&lt;/h4&gt;

&lt;p&gt;First of all, you will have to choose the OS that will be installed on your microSD. Several Operating Systems (OS) will be proposed to you, which we can divide into two categories:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The type of OS&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Lite: this is an OS with a headless environment, i.e. no desktop environment. When you boot your Raspberry, you will only have access to a terminal. This very light OS version is recommended for all server applications. In other words, if you don't plan to plug a keyboard/mouse and monitor into your Raspberry, this is the distribution you need.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Full: This is a desktop distribution with some “recommended” applications already installed. It is ideal if you want to use your Raspberry as a work computer, browse the internet…&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If nothing is specified, it is a desktop OS.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;OS in 32-bit or 64-bit versions&lt;/strong&gt;. Overall, the 64-bit versions will be more powerful. All Raspberry computers support 32-bit OS. However, only the Raspberry Pi 3B, 3B+, 3A+, 4, 400 and Zero 2 W support 64-bit OS.&lt;/p&gt;

&lt;p&gt;For my project, I chose to use the 64-bit Raspberry Pi OS Lite version.&lt;/p&gt;
&lt;h4&gt;
  
  
  Storage
&lt;/h4&gt;

&lt;p&gt;For Storage, you simply need to select the microSD you have connected to your computer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7qepy57jq32dx2t6ftf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7qepy57jq32dx2t6ftf.png" alt="Raspberry Pi Image - Advanced options button" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Advanced options
&lt;/h4&gt;

&lt;p&gt;Many options are available in the advanced settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Hostname&lt;br&gt;
This is the name of your Raspberry Pi. I advise you to leave the default value, which is raspberrypi.local.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SSH&lt;br&gt;
This option allows you to connect to your Raspberry Pi remotely via SSH. I recommend that you enable SSH. If you know what an SSH key is, put in your own. If you don't know what it means, put a password. WARNING : with the LITE version, you must activate SSH; otherwise, you will need a screen and a keyboard connected to your Raspberry!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User&lt;br&gt;
If, like me, you use a Lite OS, it is essential to create a user on your Raspberry. You need to enable this option by adding a username and password. If you are using a desktop distribution, you will be able to create your user when you first boot your Raspberry.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wi-Fi&lt;br&gt;
This option allows you to connect your Raspberry directly to your Wi-Fi by filling in the SSID and password of your Wi-Fi. It is also possible to connect your Raspberry to the Internet via an Ethernet cable if you would rather not use Wi-Fi. You can also set the Wireless LAN country if it does not match yours. However, I strongly advise you to set it via the selector and not to write it directly in the input. I have lost a few hours of my time with a Raspberry that did not connect to Wi-Fi, because spaces had been inserted behind my country code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, you can set the timezone of your Raspberry and the keyboard layout if you want to use a keyboard connected directly to your Raspberry.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As an example, here is my configuration for my project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvkcnldn0mrd8j1nfauf7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvkcnldn0mrd8j1nfauf7.png" alt="Raspberry Pi Imager - Advanced options" width="800" height="1489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that your configuration is done, you can press the Write button, which will launch the installation of your OS on your microSD. This may take a while depending on the type of OS you choose.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ntaXWS8Lk34"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Once finished, you can insert your microSD into your Raspberry Pi and plug in the power supply. You will need to wait a few minutes for your Raspberry Pi to boot up, and it will be accessible either by connecting a monitor and keyboard to it, or by SSH if you have opted for this solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connecting to your Raspberry Pi via SSH
&lt;/h3&gt;

&lt;p&gt;If you have set up your Raspberry Pi correctly by setting up SSH and a User in Raspberry Pi Imager, here are the steps to follow.&lt;/p&gt;

&lt;p&gt;To begin, in your terminal, try pinging your Raspberry Pi with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ping raspberrypi.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you changed the hostname during configuration on Raspberry Pi Imager, you need to replace &lt;code&gt;raspberry.local&lt;/code&gt; with &lt;code&gt;your-hostname.local&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, in my case, it will be &lt;code&gt;monsieurrizpi.local&lt;/code&gt; (see config above).&lt;/p&gt;

&lt;p&gt;The ping command should return something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;PING raspberrypi.local &lt;span class="o"&gt;(&lt;/span&gt;192.168.1.131&lt;span class="o"&gt;)&lt;/span&gt; : 56 data bytes
64 bytes from 192.168.1.131: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;255 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2.618 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it does not ping, wait a few more minutes. It may not have finished booting.&lt;/p&gt;

&lt;p&gt;Once it pings you can connect to it via SSH with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh pi@raspberrypi.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You must replace &lt;code&gt;pi&lt;/code&gt; by the username defined during the configuration on Raspberry Pi Imager and &lt;code&gt;raspberrypi.local&lt;/code&gt; by the hostname of your Raspberry if you had modified it.&lt;/p&gt;

&lt;p&gt;By default, the user defined is &lt;code&gt;pi&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For example, in my case, I use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh cynthia@monsieurrizpi.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on the authentication mode chosen during configuration, you will be asked for your password or passphrase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting your project
&lt;/h2&gt;

&lt;p&gt;Your Raspberry Pi is now installed and ready to use. It's time to get started on your project or just use it as a computer.&lt;/p&gt;

&lt;p&gt;I'll be back soon with a new article about the development of my time-lapse camera project.&lt;/p&gt;

&lt;p&gt;If you are looking for an idea or a project, I recommend some websites with tutorials and interesting projects.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://projects.raspberrypi.org/en/projects?hardware%5B%5D=raspberry-pi" rel="noopener noreferrer"&gt;Raspberry Pi Foundation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.raspberrypi-france.fr/category/projets/" rel="noopener noreferrer"&gt;Raspberry Pi France&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.instructables.com/Raspberry-Pi-Projects/" rel="noopener noreferrer"&gt;Instructables&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devto</category>
      <category>announcement</category>
      <category>web3</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Create your eCommerce website with Gatsby</title>
      <dc:creator>Cynthia HENAFF</dc:creator>
      <pubDate>Tue, 24 Jan 2023 18:11:58 +0000</pubDate>
      <link>https://dev.to/monsieur_riz/create-your-ecommerce-site-with-gatsby-1h12</link>
      <guid>https://dev.to/monsieur_riz/create-your-ecommerce-site-with-gatsby-1h12</guid>
      <description>&lt;p&gt;Setting up an e-commerce site is often seen as laborious, but with the Jamstack ecosystem, we can create an e-commerce site very easily. This is what I'm going to demonstrate here by creating a fictitious e-commerce site that will offer graphic novels inspired by the world of music, called PaperJam. My GitHub directory is available here &lt;a href="https://github.com/cynthiahenaff/paperjam"&gt;https://github.com/cynthiahenaff/paperjam&lt;/a&gt; and the demo site is available at this address &lt;a href="https://paperjam.henaff.io/"&gt;https://paperjam.henaff.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I chose to use the following technical stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.gatsbyjs.com/"&gt;Gatsby&lt;/a&gt; as a static site generator&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.datocms.com/"&gt;DatoCMS&lt;/a&gt; for the content&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://snipcart.com/"&gt;Snipcart&lt;/a&gt; for the e-commerce part&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vercel.com/"&gt;Vercel&lt;/a&gt; for CDN hosting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To get off to a good start, we will create an account on each SaaS that we will use: DatoCMS, Snipcart and Vercel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initiating the project with Gatsby
&lt;/h2&gt;

&lt;p&gt;Gatsby is a static site generator based on React and GraphQL. The initialization of a project with Gatsby is quite simple and accessible to all, it is enough to type the following command in our terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init gatsby
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can be guided through the CLI steps to the next question: &lt;em&gt;&lt;code&gt;Will you be using a CMS?&lt;/code&gt;&lt;/em&gt;  We then select the answer &lt;em&gt;&lt;code&gt;DatoCMS&lt;/code&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To the question &lt;em&gt;&lt;code&gt;Would you like to install a styling system?&lt;/code&gt;&lt;/em&gt; , let's answer no, and concentrate on the other aspects of the design.&lt;/p&gt;

&lt;p&gt;Continuing with the question &lt;em&gt;&lt;code&gt;Would you like to install additional features with other plugins?&lt;/code&gt;&lt;/em&gt;, select the options below:&lt;/p&gt;

&lt;p&gt;◉ Add responsive images&lt;br&gt;
◉ Add page meta tags with React Helmet&lt;br&gt;
◉ Add an automatic sitemap&lt;br&gt;
◉ Generate a manifest file&lt;/p&gt;

&lt;p&gt;Finally, let's enter our API key for DatoCMS in response to the question &lt;em&gt;&lt;code&gt;Configure the DatoCMS plugin.&lt;/code&gt;&lt;br&gt;
This key can be found under the name &lt;code&gt;Read-only API token&lt;/code&gt; in the Settings/API tokens section of our project&lt;/em&gt;, on the DatoCMS website. It is write-protected and read-only for the data.&lt;/p&gt;

&lt;p&gt;To start the project server, just use the following command at its root.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now that our server is up and running, the home page of our web application is accessible at &lt;a href="http://localhost:8000/"&gt;http://localhost:8000&lt;/a&gt;. The code for this page can be found in the JavaScript file &lt;code&gt;src/pages/index.js&lt;/code&gt;. Within the &lt;code&gt;pages&lt;/code&gt; folder, the different pages of our web application are determined.&lt;/p&gt;

&lt;p&gt;For example, it is common on an e-commerce site to have an « About »  page that talks either about our company or our product in detail. So we will create this page on our application. As we want to create the &lt;code&gt;/about&lt;/code&gt; route, we will create an about.js file in the &lt;code&gt;pages&lt;/code&gt; folder, as below:&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="o"&gt;|&lt;/span&gt;&lt;span class="err"&gt;–&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="err"&gt;–&lt;/span&gt; &lt;span class="nx"&gt;pages&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;about&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&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;AboutPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;My « About » page&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The route &lt;a href="http://localhost:8000/about"&gt;http://localhost:8000/about&lt;/a&gt; is then automatically created.&lt;/p&gt;

&lt;p&gt;For an e-commerce site, beyond the performance of the site, it is essential for a good referencing to add the metadata tags in the HTML files.&lt;br&gt;
To add these elements in the &lt;code&gt;head&lt;/code&gt; tag of our pages, the simplest method is to use the &lt;a href="https://www.npmjs.com/package/react-helmet"&gt;Helmet&lt;/a&gt; library.&lt;/p&gt;

&lt;p&gt;We will create a Layout component in our &lt;code&gt;components&lt;/code&gt; folder which we will call on our various pages. This component will also allow us to use the same layout throughout our site. We will include the &lt;code&gt;header&lt;/code&gt; and &lt;code&gt;footer&lt;/code&gt; of our project in this component.&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Helmet&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-helmet&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;Layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Helmet&lt;/span&gt; 
    &lt;span class="na"&gt;defaultTitle&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"PaperJam"&lt;/span&gt; 
    &lt;span class="na"&gt;defer&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
    &lt;span class="na"&gt;htmlAttributes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&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="si"&gt;}&lt;/span&gt;
       &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"og:title"&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"og:description"&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"og:type"&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"website"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"og:locale"&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en_GB"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"twitter:card"&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"summary_large_image"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"twitter:creator"&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"@monsieur_riz"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Helmet&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;footer&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This is what our &lt;code&gt;pages/about.js&lt;/code&gt; file looks like after adding our Layout component.&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/Layout&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;AboutPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt; 
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"My About page"&lt;/span&gt; 
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Discover why I decided to create this ecommerce website"&lt;/span&gt;
     &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;My "About" page&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Content creation with DatoCMS
&lt;/h2&gt;

&lt;p&gt;Now that our project is ready, we will move on to creating a product data model with DatoCMS.&lt;/p&gt;

&lt;p&gt;DatoCMS has the advantage of being easy to use and ergonomic. It allows you to easily make mandatory elements such as product names or alternative texts on images. A gallery is available, which allows to store images, but also to edit them directly. It is also possible to manage the translation of our site into up to 5 different languages.&lt;/p&gt;

&lt;p&gt;To do this, let's go to the Settings/Models section of the project in DatoCMS.&lt;/p&gt;

&lt;p&gt;We will name our first data model &lt;code&gt;Product&lt;/code&gt;; it will contain the following elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name&lt;/strong&gt; - &lt;em&gt;Text — Single-line string&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will make this element mandatory as it is essential for the correct display of a product&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ts18uhwI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4flwaah1nzm9n8c6kte7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ts18uhwI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4flwaah1nzm9n8c6kte7.png" alt="DatoCMS - Name field" width="880" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j32q5Nr_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0sbu7rdoub85ztw0p2j8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j32q5Nr_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0sbu7rdoub85ztw0p2j8.png" alt="DatoCMS - Name field validation" width="880" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Slug&lt;/strong&gt; - &lt;em&gt;type SEO — Slug&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The slug is a part of the address that will allow us to uniquely identify a page. It must be in a format that is easily readable by users and search engines for UX and SEO purposes.&lt;br&gt;
DatoCMS allows us to use a reference value such as the name of our product to generate it automatically.&lt;br&gt;
It will have the following validations:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7-Kq4hE9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xzj0dwws0jopooqrysdm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7-Kq4hE9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xzj0dwws0jopooqrysdm.png" alt="DatoCMS - Slug field validation" width="880" height="623"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Thumbnail&lt;/strong&gt; - &lt;em&gt;type Media — Single asset&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In terms of validation, we will make alternative text mandatory with the &lt;code&gt;Require alt and/or title&lt;/code&gt; option as this is essential for accessibility and SEO.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Price&lt;/strong&gt; - &lt;em&gt;type Number – Floating-point number&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This will also be mandatory.&lt;/p&gt;



&lt;p&gt;During development, after a modification of a data model, it is necessary to shut down the server and type the following command in the terminal before restarting it.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This will clear our site's cache and search for it on DatoCMS.&lt;/p&gt;

&lt;p&gt;Now that our template is created, we can go back to the &lt;code&gt;Content&lt;/code&gt; section and create our first product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the homepage
&lt;/h2&gt;

&lt;p&gt;We will now display our products on the home page. To do this, we'll get the products registered in DatoCMS in the &lt;code&gt;index.js&lt;/code&gt; file&lt;/p&gt;

&lt;p&gt;The first thing to do is to import &lt;code&gt;graphql&lt;/code&gt; from Gatsby by adding this line to the top of the JavaScript file.&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the HomePage component declaration, let's export a new constant called query. The name of the constant is not important, as Gatsby looks for a GraphQL string exported from the file rather than a specific variable. It is important to remember that we can only have one GraphQL query per file.&lt;/p&gt;

&lt;p&gt;The first part of writing a GraphQL query is to define the type of operation (in this case &lt;code&gt;query&lt;/code&gt;) and a name.&lt;/p&gt;

&lt;p&gt;Gatsby integrates the GraphiQL tool, which is a development environment available at &lt;a href="http://localhost:8000/__graphql"&gt;http://localhost:8000/__graphql&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It allows us to build GraphQL queries and copy/paste them directly into our code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HDYH4dl7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lqtsm0g0xp38f2m1yn1d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HDYH4dl7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lqtsm0g0xp38f2m1yn1d.png" alt="graphiQL" width="880" height="501"&gt;&lt;/a&gt;&lt;br&gt;
Now that the request is ready, we can directly retrieve the data object from the component props as below.&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby&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;IndexPage&lt;/span&gt; &lt;span class="o"&gt;=&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;allDatoCmsProduct&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;edges&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Last product&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="s2"&gt;`
  query getProducts {
    allDatoCmsProduct {
      edges {
        node {
          id
          slug
          name
          price
          thumbnail {
        url
        alt
          }
        }
      }
    }
  }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Snipcart integration
&lt;/h2&gt;

&lt;p&gt;Our home page now contains a list of items, so we can now look at integrating Snipcart for the e-commerce part.&lt;/p&gt;

&lt;p&gt;Snipcart is a shopping cart manager that is very easy to integrate into a web application. A simple addition of a piece of JavaScript code allows you to integrate the resources, JavaScript and CSS files into the source code. This is similar to adding a third party script like Google Analytics. As Gatsby has a very large community, there is already a plugin that will allow us to add the necessary scripts to Snipcart. We will install the &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-snipcart-advanced/"&gt;gatsby-plugin-snipcart-advanced&lt;/a&gt; library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;gatsby-plugin-snipcart-advanced
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the installation is complete, we will add the necessary configuration to the &lt;code&gt;gatsby-config.js&lt;/code&gt; file&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;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`gatsby-plugin-snipcart-advanced`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;publicApiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR_SNIPCART_APIKEY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;eur&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;openCartOnAdd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;useSideCart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// be careful with this mode cart. The cart in this mode has a bug of scroll in firefox&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API key needed to run Snipcart is available in the configuration area of our dashboard. Once logged in, this area can be accessed by clicking on the user icon in the upper right corner of the screen. It allows you to configure all administrative settings such as payment gateways, delivery, etc.&lt;/p&gt;

&lt;p&gt;The API key is accessible in the API KEYS area under the name "public test API key".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IpDNqv4X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/at93y9lpi6dkfw7szfp3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IpDNqv4X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/at93y9lpi6dkfw7szfp3.png" alt="Snipcart - API key" width="880" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is also necessary to customise our regional settings (located in the Regional Settings tab) to configure the currency supported, the time zone and the countries in which it will be possible to place orders.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qArJ5gOo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h735ghlrczj50zu944w5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qArJ5gOo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h735ghlrczj50zu944w5.png" alt="Snipcart - Regional settings" width="880" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Snipcart offers many features that can be configured in this area, such as inventory management, delivery, automatic email layout and payment gateway.&lt;/p&gt;

&lt;p&gt;Snipcart supports many payment gateways such as Stripe, Paypal or Square. For this guide, we will not configure the payment gateway and will remain in the "test" mode of Snipcart.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding an item to the basket
&lt;/h3&gt;

&lt;p&gt;In order for Snipcart to react to add-to-cart events, we need to add the class &lt;code&gt;snipcart-add-item&lt;/code&gt; to the add-to-cart buttons for each product, along with the following attributes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;data-item-id&lt;/code&gt;: Unique identifier for our product&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-item-price&lt;/code&gt; : Price of the product&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-item-image&lt;/code&gt; : URL of the product image&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-item-name&lt;/code&gt; : Name of the product
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby&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;IndexPage&lt;/span&gt; &lt;span class="o"&gt;=&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;allDatoCmsProduct&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;edges&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Last product&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; 
        &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"snipcart-add-item"&lt;/span&gt;
        &lt;span class="na"&gt;data-item-id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;data-item-price&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;data-item-image&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;data-item-name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Add to basket
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="s2"&gt;`
  query getProducts {
    allDatoCmsProduct {
      edges {
        node {
          id
          slug
          name
          price
          thumbnail {
        url
        alt
          }
        }
      }
    }
  }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Viewing the cart
&lt;/h3&gt;

&lt;p&gt;A summary of the basket allows customers to access it quickly and reminds them of its contents.&lt;/p&gt;

&lt;p&gt;We have the ability to add elements with specific CSS classes to our web application that allow interaction with Snipcart directly.&lt;/p&gt;

&lt;p&gt;To add a button that opens the shopping cart, we need to add the class &lt;code&gt;snipcart-checkout&lt;/code&gt; . It is also possible to display the number of items in the basket or the total price by adding the &lt;code&gt;snipcart-items-count&lt;/code&gt; or &lt;code&gt;snipcart-total-price&lt;/code&gt; class to a JSX element.&lt;/p&gt;

&lt;p&gt;We'll add this button inside our header element in our layout component to display this information and give our user the option to go and view their basket in detail.&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="p"&gt;...&lt;/span&gt; 
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"snipcart-checkout"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    Basket
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"snipcart-total-price"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    (&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"snipcart-items-count"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;)
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our shopping tunnel is now ready to be tested on the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting your website online with Vercel
&lt;/h2&gt;

&lt;p&gt;We are going to use Vercel which is one of the big players in automated front-end deployment.&lt;/p&gt;

&lt;p&gt;Vercel allows us, in addition to simplifying the deployment, to deploy our site on servers in the four corners of the world. This is what we call a CDN (Content Delivery Network). In addition to the unbeatable price and the certainty that the site will withstand any load, it allows the content of the web page to be loaded from the server closest to the user and therefore reduces the loading time.&lt;/p&gt;

&lt;p&gt;It is essential to use Vercel, or any other CDN, to host your code on a Git platform such as GitHub or GitLab.&lt;/p&gt;

&lt;p&gt;Vercel allows you to easily import a Git directory once authenticated with the chosen Git platform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PrMqAgqD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pdisrn1bvy3hx22larvi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PrMqAgqD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pdisrn1bvy3hx22larvi.png" alt="Vercel - Import Repo" width="880" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When importing our project, Vercel detects which library it uses and pre-fills the necessary configuration. A good practice in terms of security is to add our environment variables on Vercel and not to expose them on your Github.&lt;/p&gt;

&lt;p&gt;Now it's time to deploy our site. Vercel will automatically assign it a URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GjH0999W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2hlyulre2yeejcyl1sr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GjH0999W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2hlyulre2yeejcyl1sr.png" alt="Vercel - Deploy Site" width="880" height="1070"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that our e-commerce site is available online, we still have a few steps to go before we have a working site.&lt;/p&gt;

&lt;p&gt;Let's start with the configuration on the Snipcart dashboard.&lt;/p&gt;

&lt;p&gt;In the Domains &amp;amp; URLS section, we will add the domain we just created with Vercel. This will determine the domains and sub-domains that our Snipcart shop can run on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K0HXTu-M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hwtycfmi3j5wx6bg6w6n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K0HXTu-M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hwtycfmi3j5wx6bg6w6n.png" alt="Snipcart - Domains &amp;amp; URLs" width="880" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, we will import all the products available on our site into Snipcart.&lt;br&gt;
To do this, in the Products / Fetch section, simply enter the address of the page in our web application where our list of products is located; this is the home page.&lt;/p&gt;

&lt;p&gt;Snipcart will automatically fetch our page to retrieve the items that carry the classes we added earlier.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mNyJKu4R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/heiwmmfnsprxaylptp5l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mNyJKu4R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/heiwmmfnsprxaylptp5l.png" alt="Snipcart - Fetch products" width="880" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can now go to the end of our purchase tunnel and validate our very first order. Snipcart automatically manages the sending of the summary email to the customer.&lt;/p&gt;

&lt;p&gt;Finally, as our site is pre-built on our server, we need a site update function to take into account the updated data on DatoCMS.&lt;br&gt;
To do this, it is necessary to add a build trigger in the DatoCMS project parameters. This is directly connected to Vercel and configured as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_ZOIzfKB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vnksqgut5v63qxpwa911.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_ZOIzfKB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vnksqgut5v63qxpwa911.png" alt="DatoCMS - Build trigger" width="880" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The "build method" automatically adds the DatoCMS integration to Vercel, which adds a site redeployment button to all DatoCMS pages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--41zse0Kx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ilrlkko0rkr22ye8xbbm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--41zse0Kx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ilrlkko0rkr22ye8xbbm.png" alt="DatoCMS - Build trigger button" width="880" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our e-commerce site is now online, quickly accessible from anywhere in the world and ready to receive our first visitors!&lt;/p&gt;

&lt;h2&gt;
  
  
  SEO = Performance, but not only
&lt;/h2&gt;

&lt;p&gt;Thanks to Gatsby, our e-commerce site is fast and efficient. But if speed is essential for referencing, it is not everything. Indeed, one should not put aside the basics of SEO which are among others :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A good structure of the pages by using the appropriate tags (h1, h2,...)&lt;/li&gt;
&lt;li&gt;A unique and quality content&lt;/li&gt;
&lt;li&gt;Optimised images to reduce their loading time&lt;/li&gt;
&lt;li&gt;Alternative text on all images that require it&lt;/li&gt;
&lt;li&gt;Good internal linking (links from one page to another)&lt;/li&gt;
&lt;li&gt;A large number of inbound links to the site&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You now have all the cards in hand to launch and optimise your e-commerce site, but don't forget your target: you must always be a user of your own product in order to understand your customers and satisfy them as much as possible.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>react</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Revolutionizing Natural Language Processing with ChatGPT-3</title>
      <dc:creator>Cynthia HENAFF</dc:creator>
      <pubDate>Sat, 03 Dec 2022 16:36:44 +0000</pubDate>
      <link>https://dev.to/monsieur_riz/revolutionizing-natural-language-processing-with-chatgpt-3-4mlc</link>
      <guid>https://dev.to/monsieur_riz/revolutionizing-natural-language-processing-with-chatgpt-3-4mlc</guid>
      <description>&lt;p&gt;OpenAI is a research institute focused on developing artificial intelligence in a safe and beneficial way. Founded in 2015, the institute has made significant contributions to the field of AI, including the development of language models such as ChatGPT.&lt;/p&gt;

&lt;p&gt;ChatGPT is a large language model trained by OpenAI that can generate human-like text responses based on a given input. The model has undergone several iterations, with the latest version being ChatGPT-3.&lt;/p&gt;

&lt;p&gt;In this article, we will discuss the history and achievements of OpenAI, the development of ChatGPT and its previous versions, and the new features of ChatGPT-3.&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%2Fh48e39za4i1q9g0vbsay.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%2Fh48e39za4i1q9g0vbsay.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAI and its History
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://openai.com/" rel="noopener noreferrer"&gt;OpenAI&lt;/a&gt; was founded in 2015 by Elon Musk, Sam Altman, Greg Brockman, and others with the goal of advancing the field of artificial intelligence in a safe and beneficial way. The institute has since become a leader in the development of AI technologies, with a focus on advancing the capabilities of language models.&lt;/p&gt;

&lt;p&gt;Some of OpenAI's major achievements include the development of GPT-2, a language model that can generate human-like text responses based on a given input. GPT-2 was a major advancement in the field of natural language processing, and paved the way for the development of ChatGPT.&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT and its Development
&lt;/h2&gt;

&lt;p&gt;ChatGPT is a large language model trained by OpenAI that can generate human-like text responses based on a given input. The model uses a combination of natural language processing techniques and machine learning algorithms to generate responses that are similar to those of a human.&lt;/p&gt;

&lt;p&gt;Previous versions of ChatGPT included ChatGPT-2, which was released in 2019 and had a significantly larger training dataset than its predecessor. ChatGPT-2 also introduced the ability to generate responses in multiple languages, making it a more versatile language model.&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT-3 and its New Features
&lt;/h2&gt;

&lt;p&gt;The latest version of ChatGPT, ChatGPT-3, was released in 2022 and introduced several new features and capabilities. Some of the notable new features of ChatGPT-3 include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Improved language generation capabilities, allowing the model to generate more human-like responses&lt;/li&gt;
&lt;li&gt;The ability to generate responses in over 100 languages, making it even more versatile than previous versions&lt;/li&gt;
&lt;li&gt;Improved memory capabilities, allowing the model to retain information from previous interactions and use it to generate more relevant responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In comparison to previous versions of ChatGPT, ChatGPT-3 has significantly improved capabilities and is a major advancement in the field of natural language processing.&lt;/p&gt;

&lt;p&gt;In conclusion, OpenAI has played a significant role in the development of artificial intelligence, with a focus on advancing the capabilities of language models. ChatGPT and its previous versions have been major milestones in the field, and the latest version, ChatGPT-3, introduces several new features and capabilities. The potential impact of ChatGPT-3 and future developments in AI are exciting to consider.&lt;/p&gt;

&lt;h2&gt;
  
  
  Didn't you notice anything?
&lt;/h2&gt;

&lt;p&gt;This article is a perfect example of ChatGPT-3's capability as it is generated by ChatGPT-3 itself as shown in the following screenshot.&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%2Famnhf4h8k6wnmglcq6ph.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%2Famnhf4h8k6wnmglcq6ph.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even the title of the article was generated by ChatGPT.&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%2F7gktgehogtluplongoa1.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%2F7gktgehogtluplongoa1.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since a few days, you must have seen a lot of publication on Twitter and others social networks about ChatGPT-3.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1598269692082151424-524" src="https://platform.twitter.com/embed/Tweet.html?id=1598269692082151424"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1598269692082151424-524');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1598269692082151424&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;ChatGPT is very impressive because it is able to generate meaningful and relevant content in many different areas. Whether it's a recipe, a mathematical problem, popular science or a development question, it will give you a pretty good answer in either English or French.&lt;/p&gt;

&lt;p&gt;The best way to understand the immensity of the thing is to go and test it and ask it some very specific questions. So, go to &lt;a href="https://chat.openai.com/" rel="noopener noreferrer"&gt;chat.openai.com&lt;/a&gt; to create your account and try to ask it anything you can think of.&lt;/p&gt;

</description>
      <category>openai</category>
      <category>chatgpt</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Jamstack, the rescuer of small businesses</title>
      <dc:creator>Cynthia HENAFF</dc:creator>
      <pubDate>Tue, 02 Aug 2022 09:48:35 +0000</pubDate>
      <link>https://dev.to/monsieur_riz/jamstack-the-rescuer-of-small-businesses-2gd1</link>
      <guid>https://dev.to/monsieur_riz/jamstack-the-rescuer-of-small-businesses-2gd1</guid>
      <description>&lt;p&gt;Since the outbreak of COVID-19 and the measures that were taken to mitigate the pandemic, e-commerce has boomed and allowed merchants to bounce back and keep their businesses afloat. However, when everyone is getting into e-commerce, it is important to differentiate yourself from the competition. This is where Jamstack plays a role and can become the saviour of these businesses.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hHCJvn0J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gt3wpzsdpexlz0wyiiu1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hHCJvn0J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gt3wpzsdpexlz0wyiiu1.png" alt="Image description" width="880" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Jamstack
&lt;/h2&gt;

&lt;p&gt;Jamstack is an abbreviation coined by Mathias Biilmann, CEO of Netlify, which stands for “JavaScript, API and Markup”.&lt;/p&gt;

&lt;p&gt;Jamstack refers to a web development architecture that allows developers to leverage the benefits of a static website while retaining the dynamic attributes of a database-driven CMS, without the database.&lt;/p&gt;

&lt;p&gt;It can be used for many purposes: showcase websites (for lawyers, restaurants, …), personal websites (blog, portfolio, …), e-commerce websites.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8He75-kU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7bvty25xuz84ivudjs2c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8He75-kU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7bvty25xuz84ivudjs2c.png" alt="Image description" width="880" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A Jamstack site is made up of different elements, which are :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A static site generator&lt;/strong&gt; (SSG) &lt;br&gt;
A static site generator is a tool that builds static HTML pages. Using content from a CMS or other system, the SSG applies a template of your choice and generates a structure of purely static HTML files, resulting in web-ready pages. Among the best known are Gatsby, Next.js, and Eleventy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A headless CMS&lt;/strong&gt;&lt;br&gt;
A CMS (Content Management System) is a type of web application that manages the content of a website. If it is “headless”, then it exposes the data in the form of an API only and is totally decoupled from the front-end.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Continuous integration and deployment (CI/CD) pipelines&lt;/strong&gt; &lt;br&gt;
Each content modification, on the CMS or on the source code, is notified to a continuous integration server that will rebuild the site.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CDN hosting&lt;/strong&gt;&lt;br&gt;
A CDN (Content Delivery Network) is a means of hosting from several servers located in different geographical areas. It allows the content of the web page to be loaded from the server closest to the user and therefore reduces the loading time. The main ones are Netlify and Vercel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One or more &lt;strong&gt;third-party services&lt;/strong&gt;&lt;br&gt;
The thriving API ecosystem provides a solution for just about any need, from payment and form data management to user authentication, real-time data storage and retrieval, and e-commerce task management.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nvoOtB9L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ts1djkhccoam2fkhhe4k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nvoOtB9L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ts1djkhccoam2fkhhe4k.png" alt="Image description" width="880" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a classical architecture, pages are computed on the fly: each request is received by the server, which generates the view and sends it back to the user, whereas in a Jamstack architecture, pages are pre-generated: when the server receives the order, it builds the view of each page of the site, and the whole site is served from a CDN.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Jamstack?
&lt;/h2&gt;

&lt;p&gt;There are many advantages to developing an e-commerce site with the Jamstack, but the most obvious one is the considerable performance improvement.&lt;/p&gt;

&lt;p&gt;For a start, every time a content change is applied in the CMS, the site is completely rebuilt on the server side. As a result, when users visit the site, neither the APIs nor the databases are called. If we add to this the fact that all the pages generated are ready to be consumed on CDN servers geographically close to the user, wherever they are in the world, then we obtain a significant increase in performance compared to a traditional architecture.&lt;/p&gt;

&lt;p&gt;Using a CDN also makes it possible to transparently compensate for any sudden spikes in traffic. It puts an end to problems related to server capacity or an interruption in the connection to the database. In addition, these pre-rendered static web pages are always indexed without problems by Google's robots.&lt;/p&gt;

&lt;p&gt;Finally, being able to rely on a multitude of third-party services and focus exclusively on the front-end makes the development experience much better. Indeed, all these services are developed by entire teams dedicated to a single need, a single problem. This saves a lot of time in terms of development and experience as these solutions are already optimised, perfected and secured.&lt;/p&gt;

&lt;p&gt;Once in production, no maintenance is required on a Jamstack website. With the headless CMS, the client has control over all content and becomes autonomous if they need to make changes. These CMS have the advantage of being simple and intuitive to use for the client. This also makes them an ideal choice for agencies and freelance developers to provide turnkey sites to their clients by making them autonomous.&lt;/p&gt;

&lt;p&gt;Thanks to the CMS and the use of third-party services, the development cost is reduced compared to a traditional architecture. And some CMS such as Contentful or DatoCMS and some hosting services such as Netlify or Vercel offer free plans, which can bring the actual hosting costs down to almost zero.&lt;/p&gt;

&lt;p&gt;At present, there are two major limitations to the Jamstack e-commerce solution. The first is when you have a very large product catalogue. By nature with Jamstack, when a small change is made to a single page, all the pages of the site are rebuilt. If the site contains thousands of pages, this can take several minutes.&lt;/p&gt;

&lt;p&gt;However, solutions already exist. Gatsby and NextJS have already released an incremental build option. Incremental builds allow you to rebuild only the relevant pages, i.e. the ones that are actually modified. This now makes it possible to have e-commerce sites with very large product catalogues in Jamstack.&lt;/p&gt;

&lt;p&gt;The second limitation is the lack of customisation of the website for each user. Indeed, as the site is generated upstream, all users have the same version. In the age of ultra-customisation, this can become a real problem for some. However, the e-commerce site Everlane has implemented a very effective solution to overcome this problem. They add dynamic bricks to the static version of the site in order to personalise the site to the profile of the logged-in user. If the user has already ordered women products, they will see the women items highlighted. In order to avoid the white page during the loading time of these dynamic bricks, they use the “Skeleton Screen”. This technique put forward by Luke Wroblewski in 2013 starts from the observation that the usual loading pages draw the attention of users to the fact that they are waiting. The &lt;a href="https://www.lukew.com/ff/entry.asp?1797"&gt;Skeleton Screen&lt;/a&gt; consists of displaying what the page should look like, but with placeholders instead of data. In this way, it allows the user to wait while giving the impression that the site is loaded. This trick is already used by most of the Internet giants such as Slack, Netflix, or Twitter to name a few.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Tjb_oafHVoI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  The COVID crisis and the advent of the Jamstack
&lt;/h2&gt;

&lt;p&gt;In March 2020, the first containment due to COVID-19, which was initially planned to last 2 weeks, was put in place. Unfortunately, as the health crisis was difficult to manage, we had to carry out a series of confinements. The economic victims of these repeated confinements were the small shops which, not being “essential” shops, had to close their doors. Despite their well-stocked inventory, they were unable to sell and thus to maintain their turnover. It was time for these shops to adapt! This is where solutions such as click&amp;amp;collect or e-commerce solutions became vital and started to boom.&lt;/p&gt;

&lt;h3&gt;
  
  
  What does this have to do with the Jamstack?
&lt;/h3&gt;

&lt;p&gt;Beyond the elaboration of the marketing strategy, the choice of products and the design, it is essential when designing an e-commerce site to carefully choose the technology that will be used to develop it. Moreover, nowadays, 53% of web consumption is done via mobile, so it is obvious that the site must be designed in “mobile first”.&lt;/p&gt;

&lt;p&gt;For an e-commerce site, it is essential to have a high-performance and secure website. We have already seen that Jamstack is secure, reliable, flexible and above all fast. But why is this so important?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www2.deloitte.com/ie/en/pages/consulting/articles/milliseconds-make-millions.html"&gt;The Google/Deloitte “Milliseconds Make Millions” report&lt;/a&gt;, which analysed the correlation between conversion rates and website speed, shows that the two are linked: the higher the performance, the higher the conversion rate. Speed plays a key role in the success of any digital initiative, especially for e-commerce sites. Indeed, it has been shown that improving loading time by 0.1 seconds improves conversion rates by 8%.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5voaBv0w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aydbhmy3he0vj4z05ca9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5voaBv0w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aydbhmy3he0vj4z05ca9.png" alt="Image description" width="880" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The loading time also has a direct influence on the retention rate. Who has never suffered from a web page that is too long?&lt;/p&gt;

&lt;p&gt;According to the study, 56% of people say they will abandon a website if it takes more than 3 seconds to load and 1 in 5 users will never return to the site. To put it more simply, half of all customers leave a site before they have even visited it. In addition to losing a potential buyer, you lose a customer who will never return.&lt;/p&gt;

&lt;p&gt;When site speed improves by 0.1 seconds, the data shows a positive correlation with consumers viewing more pages per session. More page views per session also means more transactions and more spending. Indeed, on average, users spent 9.2% more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Tl9U-KFA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1qx02mqj1ms0i1rx88uf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Tl9U-KFA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1qx02mqj1ms0i1rx88uf.png" alt="Image description" width="880" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another important criterion to consider when developing an e-commerce site is natural referencing. Search Engine Optimization (SEO) encompasses all the methods and techniques that aim to position a website in the top results of search engines.&lt;/p&gt;

&lt;p&gt;Jamstack offers all the qualities of SEO. Faster loading time means better SEO, as search engines will always favour a lighter, faster site when indexing a site. It is obvious that the higher a website is in the search engine results, the more visible and visited it will be.&lt;/p&gt;

&lt;p&gt;Contrary to solutions such as Magento and Shopify which allow you to easily create product catalogues, a Jamstack gives you the possibility to create editorial content which is also very beneficial for natural referencing. Indeed, the Core Update from Google in December 2020 now gives pride of place to websites with more editorial content.&lt;/p&gt;

&lt;p&gt;The many advantages seen above are contributing to the rise in popularity of Jamstack development and e-commerce sites. This has a direct impact on the ecosystem, which regularly sees the birth of new tools: for each need, a service. The abundance of tools and resources available contributes to pushing the limits of what is possible with a static website.&lt;/p&gt;

&lt;p&gt;It is difficult to keep up with the development of the ecosystem as it is so fast at the moment. However, here is a small, non-exhaustive list of the main third-party services in terms of e-commerce sites.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_-dFUH6k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/158a2i6tx4fj2yhl14c4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_-dFUH6k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/158a2i6tx4fj2yhl14c4.png" alt="Image description" width="880" height="1659"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The adoption of Jamstack
&lt;/h3&gt;

&lt;p&gt;According to 2020 figures, the number of Jamstack websites has increased by 85% compared to 2019 for desktop websites and by 147% for mobile sites. There are almost twice as many Jamstacks as in 2019. This shows a real sign of the community's attraction to this solution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--APuyXkd4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tlwzdotk05ii8us09emc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--APuyXkd4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tlwzdotk05ii8us09emc.png" alt="Image description" width="880" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IYnlITPZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v2x4lhyvdmu6bcxmyw98.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IYnlITPZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v2x4lhyvdmu6bcxmyw98.png" alt="Image description" width="880" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://www.forbes.com/sites/johnkoetsier/2020/06/12/covid-19-accelerated-e-commerce-growth-4-to-6-years/"&gt;Forbes&lt;/a&gt;, COVID accelerated the development of e-commerce by 4 to 6 years. As a result of the pandemic, all physical sellers are launching their own e-commerce sites. It is therefore vital to stand out from the crowd in order to optimise your revenues. Jamstack can make this difference, it allows you to be at the top of the search results pages which brings better traffic, and it guarantees better performance, which influences the user experience and therefore the association with the brand.&lt;/p&gt;

&lt;p&gt;Furthermore, opting for the Jamstack brings a real saving in development time thanks to the use of third-party services, but also a reduction in costs due to its efficiency and the low maintenance required post development.&lt;/p&gt;

&lt;p&gt;The buzz around Jamstack and e-commerce is so intense that Shopify has just decided to remove its commissions for the first million dollars of annual revenue. This gives many merchants the opportunity to get into e-commerce: this may be the perfect opportunity to get started 🚀&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/WkkHXIuJg_Y"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Raising a testing trophy</title>
      <dc:creator>Cynthia HENAFF</dc:creator>
      <pubDate>Fri, 24 Jul 2020 13:56:14 +0000</pubDate>
      <link>https://dev.to/monsieur_riz/raising-a-testing-trophy-4j5a</link>
      <guid>https://dev.to/monsieur_riz/raising-a-testing-trophy-4j5a</guid>
      <description>&lt;p&gt;Originally published at &lt;a href="https://henaff.io/blog/raising-a-testing-trophy" rel="noopener noreferrer"&gt;henaff.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm a front-end developer and I work in a web agency. I love this job because I have the opportunity to develop many projects from scratch and therefore continuously learn new development concepts. &lt;/p&gt;

&lt;p&gt;But I'm often working on 3 or 4 projects at the same time, so it's hard to keep up with each one of them.&lt;/p&gt;

&lt;p&gt;Moreover, I lose a lot of time processing feedbacks made either by my product owner or customers. This could be avoided by making testing an essential part of the development cycle.  It would allow us to avoid some tiny bugs which cost time to the developer, product owner and client. At the same time, it would help us detect side effects in our codebase caused by the development of new features. Ultimately, we want to avoid clients seeing regressions in the application at all cost!&lt;/p&gt;

&lt;p&gt;Simply put, what are our problems:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bugs are evil&lt;/li&gt;
&lt;li&gt;Clients don't like bugs&lt;/li&gt;
&lt;li&gt;Our reputation is at stake&lt;/li&gt;
&lt;li&gt;Regressions are hard to detect&lt;/li&gt;
&lt;li&gt;Lot of review and bug reports to handle&lt;/li&gt;
&lt;li&gt;Time is lost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clients without a technical background often don’t get the importance of automated tests. They are keener to pay for features that have a visual impact. I understand this point of view, but I think testing our web and mobile applications is crucial because it's a small investment compared to the future earnings. The final user shouldn't undergo bugs and we shall guarantee the best experience possible. &lt;/p&gt;

&lt;p&gt;So, I decided to give you a brief introduction of React application testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of tests
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Static Test
&lt;/h3&gt;

&lt;p&gt;Static tests are performed without executing the code but just by reading it. This includes typing your code with &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt; or Flow and linters like ESLint or other similar tools.&lt;/p&gt;

&lt;p&gt;These helpers are easy and fast to set-up and allow you to catch typos and type errors continuously while developing the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unit test
&lt;/h3&gt;

&lt;p&gt;According to Wikipedia, a unit test is &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;a software testing method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures, are tested to determine whether they are fit for use.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not clear, right? &lt;/p&gt;

&lt;p&gt;To simplify, we are testing one function in isolation from the rest of the code.  Doing so, if you have a function that is supposed to convert a timestamp into a duration, your test checks that you always receive a correct output when calling it. For this kind of test, the most commonly used library is &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This sort of test is rather quick and suitable for testing functions but not an application as a whole.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integration test
&lt;/h3&gt;

&lt;p&gt;Integration tests happen at a higher level, the idea behind this test is to render one or several components and to simulate requests API (mocking) and check that components are working well together. These are the main tests for an application because it insures the global behaviour as well as the synergy between components. I think that these are harder to apprehend than unit test because it's very hard to determine what we should be testing. They are also time-consuming and rather hard to set up. To write integration test the most commonly used combination of libraries is &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt; and &lt;a href="https://github.com/testing-library/react-testing-library" rel="noopener noreferrer"&gt;React Testing Library&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  End to End test
&lt;/h3&gt;

&lt;p&gt;End-to-end testing simulates the behaviour of a real user browsing through your app. It emulates clicks in order to test some flows (like login), which can be critical and generate some bugs. For a web agency like us, this sort of test speeds up the sprint review by product owner and clients, allows us to test feature like password reset and some flows developed during the first sprint and never tested ever since. Thus, it is very good for detecting regressions. E2E test is easy to set up but tedious to write and maintain. However, &lt;a href="https://www.cypress.io/" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt; makes this process a lot more enjoyable. &lt;/p&gt;

&lt;h2&gt;
  
  
  Towards the trophy
&lt;/h2&gt;

&lt;p&gt;The three most common forms of testing when it comes to automated testing are Unit, Integration and End-to-End.&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%2Fwww.datocms-assets.com%2F22029%2F1595597162-testingpyramid-edited-edited.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%2Fwww.datocms-assets.com%2F22029%2F1595597162-testingpyramid-edited-edited.png" alt="testing pyramid"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Above is a combination of Martin Fowler testing pyramid and Google’s testing pyramid, put together by Kent C. Dodds. This pyramid shows these 3 common forms of testing with 2 metrics: the time to set-up and the cost (in terms of time and resources). At the top, the test (here end-to-end) is very slow and costs a lot to set up. And at the bottom, the test is faster to set up and costs fewer resources. So if we follow this method, mainly it is necessary to do unit testing and a few other tests. &lt;/p&gt;

&lt;p&gt;But tools have changed beyond the assumption in Martin's original Testing Pyramid concept. Static test is very quick to set up and unit test should be used parsimoniously whereas Integration test is the main subject of testing react applications. Therefore, Integration tests should have a bigger spot in the diagram than Static and Unit Tests. Finally, E2E test is sparely used and reserved for specifics workflows. This is why Kent C. Dodds introduced the testing trophy. &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-960723172591992832-673" src="https://platform.twitter.com/embed/Tweet.html?id=960723172591992832"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-960723172591992832-673');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=960723172591992832&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;In this trophy we have a scale of cost, time and complexity. Here again, the more you climb up the trophy, the costlier and slower the tests are to write and maintain. Tests placed atop the trophy are more tedious to write but bring more confidence that everything works as expected.&lt;/p&gt;

&lt;p&gt;This slide from the &lt;em&gt;Testing React and Web Applications&lt;/em&gt; workshop by Kent C. Dodds recaps this idea. &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%2Fwww.datocms-assets.com%2F22029%2F1595597110-testingtrophy.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%2Fwww.datocms-assets.com%2F22029%2F1595597110-testingtrophy.png" alt="testing trophy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything can be summed up by a simple tweet by Guillermo Rauch, Vercel CEO 👇&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-807626710350839808-862" src="https://platform.twitter.com/embed/Tweet.html?id=807626710350839808"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-807626710350839808-862');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=807626710350839808&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;At Tymate, our back-end developers have been accustomed to integrating unit and integration testing into their development process for some time. But in the front-end, we had different issues to address. Unlike the APIs that can be tested endpoint by endpoint, the functionality of our applications often involves multiple interlocking logics, which are often themselves API-dependent.&lt;br&gt;
The Testing Trophy helped us a lot building our front-end testing policy without losing more time than necessary. &lt;/p&gt;

&lt;p&gt;Have you also had to set up tests in your company from scratch? Do you have any tips to share?&lt;/p&gt;

&lt;h2&gt;
  
  
  tl;dr: Efficiency of each type of test
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22029%2F1596022438-frame-1-2x.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%2Fwww.datocms-assets.com%2F22029%2F1596022438-frame-1-2x.png" alt="Efficiency of each type of test"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>testing</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Easily build a connected temperature and humidity sensor</title>
      <dc:creator>Cynthia HENAFF</dc:creator>
      <pubDate>Mon, 02 Mar 2020 15:31:14 +0000</pubDate>
      <link>https://dev.to/monsieur_riz/easily-build-a-connected-temperature-and-humidity-sensor-22g5</link>
      <guid>https://dev.to/monsieur_riz/easily-build-a-connected-temperature-and-humidity-sensor-22g5</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;To monitor the temperature of the main room or the baby bedroom, you can create and develop your own connected temperature sensor easily.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We will create a connected temperature sensor by following these steps. To achieve this, we will use an esp8266 and 2 shields.&lt;br&gt;
The ESP8266 is a microcontroller like an Arduino but with an integrated Wi-Fi module.&lt;/p&gt;

&lt;p&gt;A shield is a board that can be added to the main board to expand its features. The shields have the advantage of being extremely easy to set up and use.&lt;br&gt;
For now, 20 shields are available for the esp8266 D1 Mini.&lt;br&gt;
So we can create many IoT projects easily by clipping the shields on top of each other and with little code to write.&lt;/p&gt;
&lt;h2&gt;
  
  
  Things used in this project
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;a href="https://www.aliexpress.com/item/32651747570.html?spm=a2g0o.productlist.0.0.d1365f31wIAKiN&amp;amp;algo_pvid=72c09ffe-f52c-43ae-bc31-31736129f39e&amp;amp;algo_expid=72c09ffe-f52c-43ae-bc31-31736129f39e-0&amp;amp;btsid=c11006ac-7a9d-44fc-ab25-decffc59f849&amp;amp;ws_ab_test=searchweb0_0,searchweb201602_5,searchweb201603_53"&gt;ESP8266 Wemos D1 mini&lt;/a&gt;. It's the main mini Wi-Fi board.&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://fr.aliexpress.com/item/32922483927.html?spm=a2g0o.productlist.0.0.23b8743eIe3EmW&amp;amp;algo_pvid=338c97dd-7aa1-4d4f-abcc-de3a703f12c6&amp;amp;algo_expid=338c97dd-7aa1-4d4f-abcc-de3a703f12c6-1&amp;amp;btsid=aea2daf0-5eed-4304-9045-e6ecafd71891&amp;amp;ws_ab_test=searchweb0_0,searchweb201602_5,searchweb201603_53"&gt;SHT30 Shield&lt;/a&gt;. It's the temperature and humidity sensor module. I advise you to take the V2 because it is much more precise and is not impacted by the heat from the ESP8266. For this article, I will use the V1 of the module.&lt;/li&gt;
&lt;li&gt;An &lt;a href="https://www.aliexpress.com/item/32801063529.html?spm=a2g0o.productlist.0.0.1cdd1ff5edEMuE&amp;amp;algo_pvid=41f39093-fde7-4470-b6b3-a7d590525d9d&amp;amp;algo_expid=41f39093-fde7-4470-b6b3-a7d590525d9d-0&amp;amp;btsid=7113f5d3-52f3-4e2a-a0f5-38cea564d622&amp;amp;ws_ab_test=searchweb0_0,searchweb201602_5,searchweb201603_53"&gt;OLED display Shield&lt;/a&gt;. It's a screen that will allow us to display the temperature&lt;/li&gt;
&lt;/ul&gt;


&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jQmBQBan--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581622658-e072262d-f357-4c76-9569-c965c36549901105c.png" width="880" height="880"&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dPOTuYBw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581623918-sht30.png" width="880" height="880"&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qlQnnXlB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581624183-oled.png" width="880" height="880"&gt;

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

&lt;ul&gt;
&lt;li&gt;The latest version of the &lt;a href="https://www.arduino.cc/en/main/software"&gt;Arduino IDE&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Add the ESP8266 board :
Add this url &lt;a href="https://arduino.esp8266.com/stable/package_esp8266com_index.json"&gt;https://arduino.esp8266.com/stable/package_esp8266com_index.json&lt;/a&gt; on &lt;code&gt;Arduino/Preferences/Additional Boards Manager URLs&lt;/code&gt;
Install the ESP8266 on board manager &lt;code&gt;Tools/Board/Board Manager&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add this libraries with &lt;code&gt;Tools/Manage Libraries&lt;/code&gt;:
    &lt;code&gt;Adafruit_SHT31&lt;/code&gt;
    &lt;code&gt;Adafruit_SSD1306&lt;/code&gt;
    &lt;code&gt;BlynkSimpleEsp8266&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Change the configuration on &lt;code&gt;Tools&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Board : &lt;code&gt;LOLIN(WEMOS) D1 mini lite&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Port: &lt;code&gt;/dev/cu.wchusbserial…&lt;/code&gt; for Mac&lt;/li&gt;
&lt;li&gt;Upload Speed: &lt;code&gt;921600&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click on &lt;code&gt;Serial Monitor&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 1 - Read the temperature value
&lt;/h2&gt;

&lt;p&gt;For the time being, we're going to connect the SHT30 shield on top of the ESP8266. With the following code, we're going to get the room temperature and humidity back into the console every four seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0qmZLqvE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581267783-bf17b2f6-333f-4ea4-98ec-2aa1b540a7fc1105c.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0qmZLqvE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581267783-bf17b2f6-333f-4ea4-98ec-2aa1b540a7fc1105c.jpeg" alt="SHT30" width="880" height="660"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"Adafruit_SHT31.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="n"&gt;Adafruit_SHT31&lt;/span&gt; &lt;span class="n"&gt;sht30&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Adafruit_SHT31&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// will pause until serial console opens&lt;/span&gt;

  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SHT30 test"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;sht30&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x45&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Couldn't find SHT30"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sht30&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readTemperature&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sht30&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readHumidity&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;isnan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;// check if 'is not a number'&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Temp *C = "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to read temperature"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;isnan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;// check if 'is not a number'&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hum. % = "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to read humidity"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="c1"&gt;// wait 4 seconds before coming back into the loop&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the following code, we're going to get the room temperature and humidity back into the console every four seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iCO-EhIO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581616758-screenshot-2020-02-13-at-18-58-10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iCO-EhIO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581616758-screenshot-2020-02-13-at-18-58-10.png" alt="Console" width="880" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 - Show a message on the screen
&lt;/h2&gt;

&lt;p&gt;Let's connect the OLED display shield on top of the ESP8266 and post a simple message.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gjQsROyQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581270250-3944d834-c7f0-45c7-9667-c3500a29f9bc1105c.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gjQsROyQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581270250-3944d834-c7f0-45c7-9667-c3500a29f9bc1105c.jpeg" alt="OLED display" width="880" height="660"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;Adafruit_SSD1306.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="n"&gt;Adafruit_SSD1306&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SSD1306_SWITCHCAPVCC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x3C&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="c1"&gt;// initialize with the I2C addr 0x3C (for the 64x48)&lt;/span&gt;

  &lt;span class="c1"&gt;// set the text size and color&lt;/span&gt;
  &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setTextSize&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;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setTextColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WHITE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clearDisplay&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"World"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clearDisplay&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now know how to display a text and how to clear the screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3MtH0rhs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.datocms-assets.com/22029/1581599018-hello-world.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3MtH0rhs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.datocms-assets.com/22029/1581599018-hello-world.gif" alt="Hello World" width="600" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 - Show the temperature on the screen
&lt;/h2&gt;

&lt;p&gt;Now that the temperature value can be read and a text displayed on the screen, for the next step, we will display the temperature and humidity values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"Adafruit_SHT31.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;Adafruit_SSD1306.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="n"&gt;Adafruit_SSD1306&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&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;Adafruit_SHT31&lt;/span&gt; &lt;span class="n"&gt;sht30&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Adafruit_SHT31&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;sht30&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x45&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Couldn't find SHT30"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SSD1306_SWITCHCAPVCC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x3C&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="c1"&gt;// initialize with the I2C addr 0x3C (for the 64x48)&lt;/span&gt;

  &lt;span class="c1"&gt;// set the text size and color&lt;/span&gt;
  &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setTextSize&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;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setTextColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WHITE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clearDisplay&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sht30&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readTemperature&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sht30&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readHumidity&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%.1fC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%.0f%%&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clearDisplay&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3FSsjrJ5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581599333-ba71db00-e1d3-4de7-80a8-1ea81fdd92a11105c.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3FSsjrJ5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581599333-ba71db00-e1d3-4de7-80a8-1ea81fdd92a11105c.jpeg" alt="Temperature sensor" width="768" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 - Connect to Blynk app
&lt;/h2&gt;

&lt;p&gt;Having the temperature and humidity value is good but it is not very practical to consult them. So we will connect our temperature sensor to the Internet in order to post data on the cloud and get it back on an application we will build with Blynk.&lt;/p&gt;

&lt;p&gt;Blynk is an application free for small applications such as ours. It's the most popular IoT platform to connect your devices to the cloud and to design our application easily.&lt;/p&gt;

&lt;p&gt;You can follow this link for detailed explanations on how to create a new project in the application.&lt;br&gt;&lt;br&gt;
➡️ &lt;a href="http://docs.blynk.cc/#getting-started-getting-started-with-the-blynk-app"&gt;http://docs.blynk.cc/#getting-started-getting-started-with-the-blynk-app&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define BLYNK_PRINT Serial
&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"Adafruit_SHT31.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;Adafruit_SSD1306.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;BlynkSimpleEsp8266.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="n"&gt;Adafruit_SSD1306&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&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;Adafruit_SHT31&lt;/span&gt; &lt;span class="n"&gt;sht30&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Adafruit_SHT31&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"BLYNK_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;ssid&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"WIFI_NAME"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"WIFI_PASSWORD"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// connect to the WiFi&lt;/span&gt;
  &lt;span class="n"&gt;Blynk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ssid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;sht30&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x45&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Couldn't find SHT30"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SSD1306_SWITCHCAPVCC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x3C&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

  &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setTextSize&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;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setTextColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WHITE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clearDisplay&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// start blynk&lt;/span&gt;
   &lt;span class="n"&gt;Blynk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sht30&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readTemperature&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sht30&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readHumidity&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%.1fC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="c1"&gt;// send the temp value on the virtual pin 1 (V1)&lt;/span&gt;
   &lt;span class="n"&gt;Blynk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;virtualWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setCursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%.0f%%&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="c1"&gt;// send the humidity value on the virtual pin 2 (V2)&lt;/span&gt;
   &lt;span class="n"&gt;Blynk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;virtualWrite&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;h&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clearDisplay&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 you can configure your application on Blynk by setting 2 labeled value as on the following pictures. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q2yzi_kA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581623253-humidityblynk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q2yzi_kA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581623253-humidityblynk.png" width="729" height="1430"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WDlGH9IJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581623260-temperatureblynk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WDlGH9IJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581623260-temperatureblynk.png" width="734" height="1439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can have a little fun with the modules offered in the application. On mine I made a graph that represents the values of temperature and humidity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kAV-Tvtq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581623483-020aea85-4cb5-4e8b-ae8d-86c4002377a61102o.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kAV-Tvtq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581623483-020aea85-4cb5-4e8b-ae8d-86c4002377a61102o.jpeg" alt="Blynk application" width="828" height="1792"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations, you have made your connected temperature sensor. 👏&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://henaff.io/blog/easily-build-a-connected-temperature-and-humidity-sensor"&gt;https://henaff.io&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>tech</category>
    </item>
    <item>
      <title>How to install Matomo on Ubuntu 18.04</title>
      <dc:creator>Cynthia HENAFF</dc:creator>
      <pubDate>Wed, 26 Feb 2020 12:48:11 +0000</pubDate>
      <link>https://dev.to/monsieur_riz/how-to-install-matomo-on-ubuntu-18-04-1i98</link>
      <guid>https://dev.to/monsieur_riz/how-to-install-matomo-on-ubuntu-18-04-1i98</guid>
      <description>&lt;p&gt;Matomo is an open-source web analytics platform. It is a great alternative to Google Analytics. This platform offers you 100% control of yours and your users’ data.&lt;/p&gt;

&lt;p&gt;You don’t need to install Matomo to see what it can do for you. Let’s take a quick tour around the demo site at &lt;a href="https://demo.matomo.org/index.php"&gt;demo.matomo.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7Oo6c4eg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1582457850-matomo-dashboard.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7Oo6c4eg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1582457850-matomo-dashboard.png" alt="" width="880" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The open-source self-hosted Matomo can show the following reports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Top keywords and search engines, referrals, social media.&lt;/li&gt;
&lt;li&gt;Top pages URLs, page titles, user countries, providers, operating systems, browsers shares, screens resolutions, desktop vs. mobile.&lt;/li&gt;
&lt;li&gt;Engagement (time on site, pages per visit, repeated visits).&lt;/li&gt;
&lt;li&gt;Top campaigns, custom variables, top entry/exit pages, downloaded files, and many more.&lt;/li&gt;
&lt;li&gt;Classified into four main analytics report categories – Visitors, Actions, Referrers, Goals/Ecommerce (30+ reports).&lt;/li&gt;
&lt;li&gt;Statistics email reports.&lt;/li&gt;
&lt;li&gt;Web server analytics logs.&lt;/li&gt;
&lt;li&gt;Tools to comply with GDPR (such as cookie consent)&lt;/li&gt;
&lt;li&gt;Install free or premium plugins to extend and expand the functionality of Matomo.&lt;/li&gt;
&lt;li&gt;And more features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can check the &lt;a href="https://matomo.org/features/"&gt;Matomo features page&lt;/a&gt;, for the full list of features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I’ve chosen to self-host my own Matomo for these benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full control of data. Data is only stored on your server, and you can choose which country the server is located in.&lt;/li&gt;
&lt;li&gt;No data limits. You can hold as much data as your server can fit.&lt;/li&gt;
&lt;li&gt;Fully customisable and extensible.&lt;/li&gt;
&lt;li&gt;Firefox started blocking cross-site tracking cookies, including Google analytics. By hosting the analytics software under your own domain name, you tracking cookies won’t be blocked.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Required services
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The latest PHP 7.x release&lt;/li&gt;
&lt;li&gt;MySQL 5.7+ for your database&lt;/li&gt;
&lt;li&gt;Nginx Webserver&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create MySQL database
&lt;/h2&gt;

&lt;p&gt;Install PHP and MySQL.&lt;br&gt;
&lt;/p&gt;

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

sudo apt-get install --no-install-recommends php php-fpm php-curl php-gd php-cli php-mysql mysql-server php-xml php-mbstring
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connect to your MySQL database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a database for Matomo. Replace &lt;code&gt;matomo_db_name&lt;/code&gt; with your database name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; CREATE DATABASE matomo_db_name;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a user called matomo. Replace &lt;code&gt;strong-password&lt;/code&gt; with your strong secured password.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; CREATE USER 'matomo'@'localhost' IDENTIFIED BY 'strong-password';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Grant this user matomo the permission to access your &lt;code&gt;matomo_db_name&lt;/code&gt; database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, DROP, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON matomo_db_name.* TO 'matomo'@'localhost';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Grant this user matomo the FILE global privilege.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql&amp;gt; GRANT FILE ON *.* TO 'matomo'@'localhost';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exit MySQL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install Matomo
&lt;/h2&gt;

&lt;p&gt;Install unzip.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Get the latest version of Matomo and unzip it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo wget https://builds.matomo.org/matomo.zip &amp;amp;&amp;amp; unzip matomo.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Move matomo directory to &lt;code&gt;/srv/&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mv matomo /srv/matomo/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change the ownership of Matomo directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo chown -R www-data:www-data /srv/matomo/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  NGINX
&lt;/h2&gt;

&lt;p&gt;Get NGINX.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Create NGINX configuration file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /etc/nginx/conf.d/matomo.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Insert the following lines in the configuration file. Replace &lt;code&gt;analytics.example.com&lt;/code&gt; with the domain you would like to use to access your Matomo installation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
  server_name analytics.example.com;
  root /srv/matomo;
  index index.php index.html;
  access_log /var/log/nginx/matomo_access.log;
  error_log /var/log/nginx/matomo_error.log;

  client_max_body_size 100M;

  location ~ ^/(index|matomo|piwik|js/index|plugins/HeatmapSessionRecording/configs)\.php {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  }

  location ~* ^.+\.php$ {
    deny all;
    return 403;
  }

  location / {
    try_files $uri $uri/ =404;
  }

  location ~ /(config|tmp|core|lang) {
    deny all;
    return 403;
  }

  location ~ /\.ht {
    deny all;
    return 403;
  }

  location ~ js/container_.*_preview\.js$ {
    expires off;
    add_header Cache-Control 'private, no-cache, no-store';
  }

  location ~ \.(gif|ico|jpg|png|svg|js|css|htm|html|mp3|mp4|wav|ogg|avi|ttf|eot|woff|woff2|json)$ {
    allow all;
    expires 1h;
    add_header Pragma public;
    add_header Cache-Control "public";
  }

  location ~ /(libs|vendor|plugins|misc/user) {
    deny all;
    return 403;
  }

  location ~/(.*\.md|LEGALNOTICE|LICENSE) {
    default_type text/plain;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test your NGINX configuration, restart it and add it to boot services.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nginx -t
sudo systemctl restart nginx
sudo systemctl enable nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  SSL certificate
&lt;/h2&gt;

&lt;p&gt;Install Certbot.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install certbot python-certbot-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Certbot, you can generate a SSL certificate (thanks to LetsEncrypt) by running this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;certbot --nginx -d analytics.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure Matomo
&lt;/h2&gt;

&lt;p&gt;Go to your domain, here analytics.example.com. If everything is installed correctly, you should see the Matomo Installation Welcome Screen. Follow the steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  System Check
&lt;/h3&gt;

&lt;p&gt;Matomo will check your installation to make sure that your server meets the Matomo requirements. If everything is okay, you’ll see a long list like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PmMW-Emc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1582457846-matomo-check-sucess.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PmMW-Emc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1582457846-matomo-check-sucess.png" alt="" width="700" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If there is a problem, Matomo will identify it and tell you how to solve it, as in this example:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z00_NoXb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1582457843-matomo-check-failed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z00_NoXb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1582457843-matomo-check-failed.png" alt="" width="678" height="384"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  MySQL Database Setup
&lt;/h3&gt;

&lt;p&gt;For the database setup, use the following credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database Server : 127.0.0.1
Login: matomo
Password: &amp;lt;YourStrongPassword&amp;gt;
Database Name: matomo
Adapter: PDO/MYSQL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TxbAbq_Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1582457854-matomo-db-setup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TxbAbq_Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1582457854-matomo-db-setup.png" alt="" width="664" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Super User
&lt;/h3&gt;

&lt;p&gt;Now you should create your super user. This user has the highest permissions. Insert your username, password and email. Do not lose those; it is the only way for you to log in to Matomo for the first time&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dw_NzMk0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1582457849-matomo-superuser-setup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dw_NzMk0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1582457849-matomo-superuser-setup.png" alt="" width="700" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup Your First Website
&lt;/h3&gt;

&lt;p&gt;Enter the name and URL of the first website you want to track. You can add more websites once the installation is complete.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wioMD1-0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1582457851-matomo-website-setup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wioMD1-0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1582457851-matomo-website-setup.png" alt="" width="880" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Install the JavaScript Tracking Tag
&lt;/h3&gt;

&lt;p&gt;Matomo will generate a JavaScript tag for you. This code must appear on every page that you want Matomo to analyze. It's recommended that you paste this code immediately before your closing  tag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GZZ9R_dB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1582457856-matomo-javascript-tag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GZZ9R_dB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1582457856-matomo-javascript-tag.png" alt="" width="700" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For Gatsby sites, you could use the &lt;a href="https://www.gatsbyjs.org/packages/gatsby-plugin-matomo/"&gt;gatsby-plugin-matomo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add this line to your gatsby.config file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plugins: [
 {
   resolve: 'gatsby-plugin-matomo',
   options: {
     siteId: 'YOUR_SITE_ID',
     matomoUrl: 'https://analytics.example.com',
     siteUrl: 'https://YOUR_LIVE_SITE_URL.COM'
   }
 }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Congratulations
&lt;/h2&gt;

&lt;p&gt;You have installed your self hosted Matomo Web Analytics. Now you can perform a wide range of functions, including tracking goals and placing orders online. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/8P1wfpFs14vDRZJnJ7/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/8P1wfpFs14vDRZJnJ7/giphy.gif" alt="" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://henaff.io/blog/how-to-install-matomo-on-ubuntu-18-04"&gt;https://henaff.io&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>analytics</category>
      <category>ubuntu</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How being a crypto-currencies addict led me to develop my own bot</title>
      <dc:creator>Cynthia HENAFF</dc:creator>
      <pubDate>Fri, 14 Feb 2020 10:58:12 +0000</pubDate>
      <link>https://dev.to/monsieur_riz/how-i-became-a-crypto-currencies-addict-1mnj</link>
      <guid>https://dev.to/monsieur_riz/how-i-became-a-crypto-currencies-addict-1mnj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;The world of crypto-currencies is a world that moves very fast and very impressively. So I create a bot who allows to get the values of any currencies in real time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I got interested in crypto-currencies in 2018 and bought Ethereum and Ripple to get started.&lt;br&gt;
The world of crypto-currencies is a world that moves very fast and very impressively. Sometimes within an hour the exchange rate of a currency can be completely reversed.&lt;/p&gt;

&lt;p&gt;From my first investment, I became obsessed with this one. I wanted to see if I was earning or losing  money and especially I wanted to see which currencies were going up. I needed a platform that would gather information and values of the currencies, and that would keep me informed every hour of the important variations of the currencies. &lt;/p&gt;

&lt;p&gt;So &lt;strong&gt;I had fun creating CryptoShark&lt;/strong&gt; and creating a channel where it publishes the course of crypto-currencies hourly.&lt;/p&gt;

&lt;p&gt;CryptoShark is a bot available on Telegram. &lt;br&gt;
It allows you to &lt;strong&gt;get the values of any crypto-currency in real-time in US dollar and Euro&lt;/strong&gt;. All the data is fetched on Coin Market Cap, the world's most trusted source for crypto market.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Bmb0NbVU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581614667-cryptoshark-16-9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Bmb0NbVU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581614667-cryptoshark-16-9.jpg" alt="" width="871" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can ask the bot for any currency by sending a command (starting by &lt;code&gt;/&lt;/code&gt;) with the name (or symbol) of the cryptocurrency you are interested in.&lt;br&gt;
For example, for the Bitcoin you can send  &lt;code&gt;/BTC&lt;/code&gt; or &lt;code&gt;/bitcoin&lt;/code&gt;, for the Cardano &lt;code&gt;/ADA&lt;/code&gt; or &lt;code&gt;/cardano&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here are the other commands available:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;/top10&lt;/code&gt; - Query the market for the top 10 crypto-currencies by market capitalization&lt;br&gt;&lt;br&gt;
&lt;code&gt;/best1h&lt;/code&gt; – Top 5 performing currencies in the last hour&lt;br&gt;&lt;br&gt;
&lt;code&gt;/best24h&lt;/code&gt; – Top 5 performing currencies in the last 24h&lt;br&gt;&lt;br&gt;
&lt;code&gt;/best7d&lt;/code&gt; – Top 5 performing currencies in the last week&lt;br&gt;&lt;br&gt;
&lt;code&gt;/worst1h&lt;/code&gt; – Least 5 performing currencies in the last hour&lt;br&gt;&lt;br&gt;
&lt;code&gt;/worst24h&lt;/code&gt; – Least 5 performing currencies in the last 24h&lt;br&gt;&lt;br&gt;
&lt;code&gt;/worst7d&lt;/code&gt; – Least 5 performing currencies in the last week  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ISbVeyOe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581610233-screenshot-2020-02-13-at-16-54-28.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ISbVeyOe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581610233-screenshot-2020-02-13-at-16-54-28.png" width="880" height="957"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--InCenLsT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581610229-screenshot-2020-02-13-at-16-55-15.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--InCenLsT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581610229-screenshot-2020-02-13-at-16-55-15.png" width="880" height="957"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--432XlhFd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581610227-screenshot-2020-02-13-at-16-55-31.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--432XlhFd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581610227-screenshot-2020-02-13-at-16-55-31.png" width="880" height="957"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the crypto-currencies addicts, CryptoShark publishes every hour on a &lt;a href="https://t.me/cryptoshark_channel"&gt;channel&lt;/a&gt; the values of the top 5 crypto-currencies and the 5 best performing currencies on the last hour.&lt;br&gt;&lt;br&gt;
Curious? To try it, it's this way ➡️ &lt;a href="https://t.me/cryptoshark_channel"&gt;t.me/cryptoshark_channel&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4MCpI0MX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581157408-screenshot-2020-02-08-at-11-23-15.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4MCpI0MX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.datocms-assets.com/22029/1581157408-screenshot-2020-02-08-at-11-23-15.png" alt="" width="856" height="826"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CryptoShark is now available on Product Hunt, if you wish to support and encourage me in new projects you can upvote for it here &lt;a href="https://www.producthunt.com/posts/cryptoshark"&gt;https://www.producthunt.com/posts/cryptoshark&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.producthunt.com/posts/cryptoshark?utm_source=badge-featured&amp;amp;utm_medium=badge&amp;amp;utm_souce=badge-cryptoshark"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GXgByhhE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://api.producthunt.com/widgets/embed-image/v1/featured.svg%3Fpost_id%3D159297%26theme%3Ddark" alt="CryptoShark - Get the value of any crypto currency in real time. | Product Hunt Embed" width="250" height="54"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://henaff.io/blog/how-being-a-crypto-currencies-addict-led-me-to-develop-my-own-bot"&gt;https://henaff.io&lt;/a&gt;&lt;/p&gt;

</description>
      <category>bot</category>
      <category>cryptocurrency</category>
      <category>bitcoin</category>
      <category>telegram</category>
    </item>
    <item>
      <title>How I hacked my cats with an Arduino</title>
      <dc:creator>Cynthia HENAFF</dc:creator>
      <pubDate>Wed, 05 Feb 2020 19:19:16 +0000</pubDate>
      <link>https://dev.to/monsieur_riz/how-i-hacked-my-cats-with-an-arduino-3cn2</link>
      <guid>https://dev.to/monsieur_riz/how-i-hacked-my-cats-with-an-arduino-3cn2</guid>
      <description>&lt;p&gt;Build an automatic laser pointer for cat for 5€&lt;/p&gt;

&lt;p&gt;I have three cats and I love them… and they love chasing the uncatchable dot of a laser pointer. Playing with my three cats takes a lot of time and sometimes I don’t have much time for them 😿&lt;br&gt;
I asked myself, why couldn’t my cats play with their favorite game on their own? Because it requires a human presence. So I decided to give them this opportunity and automated this process.&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%2Fwww.datocms-assets.com%2F21735%2F1580396085-1cjkdjmzqalj7gewcttwn9q.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%2Fwww.datocms-assets.com%2F21735%2F1580396085-1cjkdjmzqalj7gewcttwn9q.gif" alt="cat laser"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I built a laser turret for my cats, programmed to move randomly and connected with Wi-Fi.&lt;/p&gt;

&lt;p&gt;I decided to use an esp8266 D1 mini because I think it’s awesome! It’s like an Arduino but it has a Wi-Fi module which allows to connect all your projects to the Internet. It’s small, cheap (2€) and compatible with the Arduino IDE.&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%2Fwww.datocms-assets.com%2F21735%2F1580396099-1rnfewor8unthxjmabx80sw.jpeg" 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%2Fwww.datocms-assets.com%2F21735%2F1580396099-1rnfewor8unthxjmabx80sw.jpeg" alt="esp8266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It allowed me to connect to Blynk. Now I can launch it remotely and program it with desired time and duration.&lt;br&gt;
Blynk is a free Platform with iOS and Android apps to control boards such as the Esp8266, Arduino, Raspberry Pi over the Internet. It’s really simple to set up and have a working app in less than 5 minutes.&lt;/p&gt;

&lt;p&gt;My Blynk 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%2Fwww.datocms-assets.com%2F21735%2F1580396093-1lxnaneivyafclxdjudczw.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%2Fwww.datocms-assets.com%2F21735%2F1580396093-1lxnaneivyafclxdjudczw.png" alt="blynk app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To build your awesome Laser Cat, you need:&lt;br&gt;
To build your awesome Laser Cat, you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A cat&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fr.aliexpress.com/item/32532784948.html?spm=a2g0s.9042311.0.0.27426c37Dwvknv" rel="noopener noreferrer"&gt;A turret&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://fr.aliexpress.com/item/32841541380.html?spm=a2g0w.search0104.3.3.24766411jHEjl5&amp;amp;ws_ab_test=searchweb0_0,searchweb201602_5_10065_10068_10843_10059_10884_10887_10696_100031_310_10084_10083_10103_451_10618_10304_10307_10820_10821_10302_526,searchweb201603_45,ppcSwitch_5&amp;amp;algo_expid=946e5d8e-be04-4643-8327-18404e7d01d1-0&amp;amp;algo_pvid=946e5d8e-be04-4643-8327-18404e7d01d1&amp;amp;priceBeautifyAB=0" rel="noopener noreferrer"&gt;2 Servo motors SG90.&lt;/a&gt; One for each axis ( X and Y).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fr.aliexpress.com/item/32820864697.html?spm=a2g0s.9042311.0.0.27426c37BEvk25" rel="noopener noreferrer"&gt;A laser module&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fr.aliexpress.com/item/32845084675.html?spm=a2g0w.search0104.3.16.3ecf5aa7Mfanue&amp;amp;ws_ab_test=searchweb0_0%2Csearchweb201602_5_10065_10068_10843_10059_10884_10887_10696_100031_310_10084_10083_10103_451_10618_10304_10307_10820_10821_10302_526%2Csearchweb201603_45%2CppcSwitch_5&amp;amp;algo_expid=29d5fe51-73b7-4bd0-997b-bd47e71e9a00-5&amp;amp;algo_pvid=29d5fe51-73b7-4bd0-997b-bd47e71e9a00&amp;amp;priceBeautifyAB=0" rel="noopener noreferrer"&gt;An Esp8266 D1 mini&lt;/a&gt;&lt;/li&gt;
&lt;/ul&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%2Fwww.datocms-assets.com%2F21735%2F1580396101-1tfbbygtivgfbcknuzemzsa.jpeg" 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%2Fwww.datocms-assets.com%2F21735%2F1580396101-1tfbbygtivgfbcknuzemzsa.jpeg" alt="laser cat"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is my electronic diagram.&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%2Fwww.datocms-assets.com%2F21735%2F1580396090-1fcs2w1r5bqbxlinchatn2w.jpeg" 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%2Fwww.datocms-assets.com%2F21735%2F1580396090-1fcs2w1r5bqbxlinchatn2w.jpeg" alt="electronic diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The “X” servo is attached to pin D5 and the “Y” servo to pin D6 and powered in 5V.&lt;br&gt;
The laser module is attached to pin D7 which allows to power it in 3.3V.&lt;br&gt;
⚠️ Powering the laser module in 5V could hurt cat eyes.&lt;/p&gt;

&lt;p&gt;The code is open source and available on  &lt;strong&gt;&lt;a href="https://github.com/cynthiahenaff/catLaser" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/strong&gt; (don’t forget to add a ⭐️).&lt;br&gt;
&lt;a href="https://github.com/cynthiahenaff/catLaser" rel="noopener noreferrer"&gt;https://github.com/cynthiahenaff/catLaser&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Enjoy your cat.&lt;/p&gt;
&lt;/blockquote&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%2Fwww.datocms-assets.com%2F21735%2F1580396095-1o4zl2u-s21epfbwzqtfboq.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%2Fwww.datocms-assets.com%2F21735%2F1580396095-1o4zl2u-s21epfbwzqtfboq.gif" alt="cat"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>arduino</category>
      <category>iot</category>
      <category>robotics</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
