<?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: Oluyemi</title>
    <description>The latest articles on DEV Community by Oluyemi (@yemiwebby).</description>
    <link>https://dev.to/yemiwebby</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%2F40322%2F50997d11-ba4e-4cf3-8aef-37a7a52cc79c.jpeg</url>
      <title>DEV Community: Oluyemi</title>
      <link>https://dev.to/yemiwebby</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yemiwebby"/>
    <language>en</language>
    <item>
      <title>Guide to server-side rendering with Deno and React</title>
      <dc:creator>Oluyemi</dc:creator>
      <pubDate>Thu, 10 Jun 2021 18:35:40 +0000</pubDate>
      <link>https://dev.to/sanity-io/guide-to-server-side-rendering-with-deno-and-react-1dbm</link>
      <guid>https://dev.to/sanity-io/guide-to-server-side-rendering-with-deno-and-react-1dbm</guid>
      <description>&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this tutorial, we will take a look at server-side rendering with Deno and React. To get a proper hang of the fundamental concepts, we will start by discovering what Deno is, and how it compares to Node in terms of security, package management, and so on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;"Using Node is like nails on a chalkboard."&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ryan Dahl, creator of Node.js at &lt;a href="https://www.youtube.com/watch?v=M3BM9TB-8yA" rel="noopener noreferrer"&gt;2018 JSConf EU&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While Node is still considered a great server-side JavaScript runtime and used by a large community of Software Engineers, even its creator admits that it leaves a lot to be desired. That's why he created &lt;a href="https://github.com/denoland/deno" rel="noopener noreferrer"&gt;Deno.js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Deno?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As stated on its &lt;a href="https://deno.land/" rel="noopener noreferrer"&gt;official website&lt;/a&gt;, Deno is a simple and secured runtime for JavaScript and TypeScript. According to Ryan, it was created to fix some of the design mistakes made when Node was created. It is gaining popularity and gradually getting adopted by the JavaScript and TypeScript community.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Deno?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are quite a few reasons to choose Deno over Node.js. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first is package management. With Node.js, packages dependencies are declared in a &lt;code&gt;package.json&lt;/code&gt; file. The packages are then downloaded to the &lt;code&gt;node_modules&lt;/code&gt; folder. This can make the project bloated, unwieldy, and sometimes difficult to manage. Deno takes a different approach to handle package dependencies. In Deno, package dependencies are installed directly from a provided URL and stored centrally. Additionally, every package is cached on the hard drive after installation which means they don’t have to be re-downloaded for subsequent projects.&lt;/li&gt;
&lt;li&gt;The second key advantage is security. By default, Deno takes an opt-in approach where you have to specify the permissions for the application. This means that Deno scripts cannot (for example) access the hard drive, environment, or open network connections without permission. This not only prevents unwanted side-effects in our application but also reduces the impact of potentially malicious packages on our application.&lt;/li&gt;
&lt;li&gt;Deno also provides TypeScript support by default which means that one can take advantage of all the benefits of static typing without any additional configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is server-side rendering?
&lt;/h2&gt;

&lt;p&gt;Server-side rendering (SSR) is the process of rendering web pages on a server and passing them to the browser instead of rendering them in the browser (client-side).&lt;/p&gt;

&lt;p&gt;This has the advantage of making applications more performant as most of the resource-intensive operations are handled server-side. It also makes Single Page Applications (SPA) more optimized for SEO as the SSR content can be crawled by search engine bots.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we will build
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we will build a movie application to show some bestselling movies and A-list actors. &lt;a href="http://sanity.io" rel="noopener noreferrer"&gt;Sanity.io&lt;/a&gt; will be used for the backend to manage contents, which includes creating, editing, and updating data for the project. While Deno and React will be used for the front end and server-side rendering respectively. &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt; will be used to style the application UI.&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%2Faq081vm057htqw75jq04.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faq081vm057htqw75jq04.gif" alt="Gif image of the movie app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To keep up with the concepts that will be introduced in this article, you will need a fair grasp of ES6. You will also need to have a basic understanding of &lt;a href="https://www.freecodecamp.org/news/start-your-journey-into-the-world-of-react-by-learning-these-basics-d6e05d3655e3/" rel="noopener noreferrer"&gt;React&lt;/a&gt; and &lt;a href="https://www.freecodecamp.org/news/learn-typescript-with-this-crash-course/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Additionally, you will also need to have the following installed locally. Please click on each one for instructions on how to download:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://deno.land/#installation" rel="noopener noreferrer"&gt;Deno&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/get-npm" rel="noopener noreferrer"&gt;Node Package Manager (NPM)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sanity.io/docs/getting-started-with-sanity-cli" rel="noopener noreferrer"&gt;Sanity CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A code editor of your choice. For example, VS Code.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;To get started, create a new directory in your terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;sanity-deno

&lt;span class="nb"&gt;cd &lt;/span&gt;sanity-deno

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

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;sanity-deno&lt;/code&gt; directory, create a new directory called &lt;code&gt;frontend&lt;/code&gt;. This will hold the components for our React UI along with the code for handling SSR using Deno.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;frontend

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

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;frontend&lt;/code&gt; directory, create two new directories, &lt;code&gt;ssr&lt;/code&gt; and &lt;code&gt;components&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;frontend/ssr frontend/components
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting up SSR
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;ssr&lt;/code&gt; directory, create a new file named &lt;code&gt;server.tsx&lt;/code&gt; to hold our server side code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;frontend/ssr

&lt;span class="nb"&gt;touch &lt;/span&gt;server.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our Deno server, we are using the &lt;a href="https://deno.land/x/oak@v7.3.0" rel="noopener noreferrer"&gt;Oak&lt;/a&gt; middleware framework, which is a framework for Deno's &lt;a href="https://doc.deno.land/https/deno.land/std/http/mod.ts" rel="noopener noreferrer"&gt;HTTP server&lt;/a&gt;. It is similar to &lt;a href="https://koajs.com/" rel="noopener noreferrer"&gt;Koa&lt;/a&gt; and &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express&lt;/a&gt; and the most popular choice for building web applications with Deno. In &lt;code&gt;server.tsx&lt;/code&gt;, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// frontend/ssr/server.tsx&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;Application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://deno.land/x/oak@v7.3.0/mod.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8000&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="s2"&gt;`&amp;lt;!DOCTYPE html&amp;gt;
                 &amp;lt;html lang="en"&amp;gt;
                 &amp;lt;head&amp;gt;
               &amp;lt;meta charset="UTF-8"&amp;gt;
               &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
                 &amp;lt;link href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css" rel="stylesheet"&amp;gt;
               &amp;lt;title&amp;gt;Sanity &amp;lt;-&amp;gt; Deno&amp;lt;/title&amp;gt;
                 &amp;lt;/head&amp;gt;
                 &amp;lt;body&amp;gt;
               &amp;lt;div id="root"&amp;gt;
           &amp;lt;h1&amp;gt; Deno and React with Sanity&amp;lt;/h1&amp;gt;
                 &amp;lt;/div&amp;gt;
                 &amp;lt;/body&amp;gt;
                 &amp;lt;/html&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allowedMethods&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`server is running on port: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the &lt;code&gt;Application&lt;/code&gt; and &lt;code&gt;Router&lt;/code&gt; modules imported from the Oak framework, we create a new application that listens to requests on port &lt;code&gt;8000&lt;/code&gt; of the local workstation. We've also added an index route that returns the HTML content to be displayed by the browser. Tailwind is added to the project via the link declared in the head of the HTML element.&lt;/p&gt;

&lt;p&gt;With this in place we can test our deno server. Run the following command &lt;strong&gt;(within the &lt;code&gt;ssr&lt;/code&gt; directory).&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deno run &lt;span class="nt"&gt;--allow-net&lt;/span&gt; server.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this command, we specify &lt;code&gt;server.ts&lt;/code&gt; as the entry point for the deno application. We also use the &lt;code&gt;--allow-net&lt;/code&gt; command to grant the application permission to access network connections.  &lt;/p&gt;

&lt;p&gt;Navigate to &lt;a href="http://localhost:8000/" rel="noopener noreferrer"&gt;http://localhost:8000&lt;/a&gt; and you will see:&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%2Fz1bn7mnx5hehy6vntmf5.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%2Fz1bn7mnx5hehy6vntmf5.png" alt="Deno application homepage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stop your application for now by pressing &lt;code&gt;Ctrl + C&lt;/code&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Adding other dependencies
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;frontend&lt;/code&gt; directory, create a file named &lt;code&gt;dep.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;touch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;frontend/dep.ts&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;dep.ts&lt;/code&gt; file will contain the frontend project dependencies. This is in line with the deno convention for &lt;a href="https://deno.land/manual@v1.9.2/examples/manage_dependencies" rel="noopener noreferrer"&gt;managing dependencies&lt;/a&gt;.  Our application will import the following packages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;React, ReactDOM and ReactDOMServer for our React UI. &lt;/li&gt;
&lt;li&gt;React Router to handle routing between components&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://www.sanity.io/docs/image-url" rel="noopener noreferrer"&gt;Sanity image-url builder&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Add the following dependencies to &lt;code&gt;dep.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @deno-types="https://denopkg.com/soremwar/deno_types/react/v16.13.1/react.d.ts"&lt;/span&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="s2"&gt;https://jspm.dev/react@17.0.2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// @deno-types="https://denopkg.com/soremwar/deno_types/react-dom/v16.13.1/server.d.ts"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOMServer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jspm.dev/react-dom@17.0.2/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// @deno-types="https://denopkg.com/soremwar/deno_types/react-dom/v16.13.1/react-dom.d.ts"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jspm.dev/react-dom@17.0.2&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;imageURLBuilder&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://cdn.skypack.dev/@sanity/image-url@0.140.22&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;BrowserRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;StaticRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Switch&lt;/span&gt;&lt;span class="p"&gt;,&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="s2"&gt;https://cdn.skypack.dev/react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ReactDOMServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;imageURLBuilder&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use the &lt;code&gt;@deno-types&lt;/code&gt; annotation to specify a URL where the React and ReactDOMServer types can be found. You can read more about providing types when importing &lt;a href="https://deno.land/manual@v1.9.2/typescript/types#providing-types-when-importing" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the app component
&lt;/h2&gt;

&lt;p&gt;Next, create the &lt;code&gt;App&lt;/code&gt; component. In the &lt;code&gt;frontend/components&lt;/code&gt; directory, create a file named &lt;code&gt;App.tsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;App.tsx&lt;/code&gt; add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// frontend/components/App.tsx&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;React&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="s2"&gt;../dep.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; App Component for Deno and React with Sanity&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we are still returning a &lt;code&gt;h1&lt;/code&gt; tag but this will serve as the entry point for React as we build further. &lt;/p&gt;

&lt;h2&gt;
  
  
  Rendering components via SSR
&lt;/h2&gt;

&lt;p&gt;At the moment, we're returning HTML from the deno server but we also need to render our react components server side. To do this, update &lt;code&gt;ssr/server.tsx&lt;/code&gt; to match the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// frontend/ssr/server.tsx&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;Application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://deno.land/x/oak@v7.3.0/mod.ts&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;ReactDOMServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;React&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="s2"&gt;../dep.ts&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;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../components/App.tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8000&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8"&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
        &amp;lt;link href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css" rel="stylesheet"&amp;gt;
    &amp;lt;title&amp;gt;Sanity &amp;lt;-&amp;gt; Deno&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body &amp;gt;
    &amp;lt;div id="root"&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ReactDOMServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;renderToString&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;)}&lt;/span&gt;&lt;span class="s2"&gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allowedMethods&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`server is running on port: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the &lt;code&gt;renderToString&lt;/code&gt; function, we are able to render our &lt;code&gt;App&lt;/code&gt; component in the body of the HTML returned by our deno server. &lt;/p&gt;

&lt;p&gt;Restart the application using the &lt;code&gt;npm run start&lt;/code&gt; command and you will see the new body is reflected. &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%2Fgenoslpy5c9mucpu170g.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%2Fgenoslpy5c9mucpu170g.png" alt="Content of AppComponent"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this in place, we actually have our SSR set up. Let's add some content to our application by building the backend with Sanity. &lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the backend
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;sanity-deno&lt;/code&gt; directory, create a new directory called &lt;code&gt;backend&lt;/code&gt;. Initialize a new Sanity project in the &lt;code&gt;backend&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;sanity-deno/backend

&lt;span class="nb"&gt;cd &lt;/span&gt;backend 

sanity init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will be  prompted to provide some information. Proceed as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select the &lt;code&gt;Create new project&lt;/code&gt; option&lt;/li&gt;
&lt;li&gt;Name the project &lt;code&gt;react_deno-backend&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use the default dataset configuration (press &lt;code&gt;Y&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Select the project output path (by default it would be the &lt;code&gt;backend&lt;/code&gt; directory)&lt;/li&gt;
&lt;li&gt;Select the movie project (schema + sample data) option. Using the arrow keys, navigate to that option and press enter when it turns blue.&lt;/li&gt;
&lt;li&gt;Upload a sampling of sci-fi movies to your dataset on the hosted backend (press &lt;code&gt;Y&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Sanity CLI will bootstrap a project from the movie template, link the needed dependencies and populate the backend with some science fiction movies. Once the process is completed, you can run your studio. By default, the studio runs at &lt;a href="http://localhost:3333/" rel="noopener noreferrer"&gt;http://localhost:3333&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Your studio will be similar to the screenshot below.&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%2Fbjbcnbyagaaz1j3z85he.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%2Fbjbcnbyagaaz1j3z85he.png" alt="Sanity studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To connect our frontend application with Sanity, we need the &lt;code&gt;projectId&lt;/code&gt; and dataset used for our Sanity project. You can find this in the &lt;code&gt;api&lt;/code&gt; node of &lt;code&gt;backend/sanity.json&lt;/code&gt;. Make a note of it as we will be using it later on. &lt;/p&gt;

&lt;p&gt;We also need to &lt;a href="https://www.sanity.io/docs/cors" rel="noopener noreferrer"&gt;enable CORS&lt;/a&gt; on our backend to ensure that it honors requests made by the application. By default, the only host that can connect to the project API is the sanity studio (&lt;a href="http://localhost:3333/" rel="noopener noreferrer"&gt;http://localhost:3333&lt;/a&gt;). Before we can make requests to the API, we need to add the host for our application (&lt;a href="http://localhost:8000/" rel="noopener noreferrer"&gt;http://localhost:8000/&lt;/a&gt;) to the permitted origins. To do this, open your &lt;a href="https://manage.sanity.io/projects" rel="noopener noreferrer"&gt;Sanity Content Studio&lt;/a&gt;. This will show you all the Sanity projects you have initialized. Select the project we are working on (&lt;code&gt;react_deno-backend&lt;/code&gt;) and click on the &lt;code&gt;Settings&lt;/code&gt; tab. Click on the &lt;code&gt;API&lt;/code&gt; menu option. In the  CORS Origins section, click the &lt;code&gt;Add new origin&lt;/code&gt; button.  In the form that is displayed, type &lt;code&gt;http://localhost:8000&lt;/code&gt; as the origin. Click the &lt;code&gt;Add new origin&lt;/code&gt; button to save the changes made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a client for sanity studio
&lt;/h2&gt;

&lt;p&gt;We need a client that will help us connect and retrieve data from our Sanity studio. In the &lt;code&gt;frontend&lt;/code&gt; directory, create a new file called &lt;code&gt;SanityAPI.ts&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;frontend/SanityAPI.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.sanity.io/exchange/community/runeb" rel="noopener noreferrer"&gt;Rune Botten&lt;/a&gt; created a sample client we can use with deno &lt;a href="https://gist.github.com/runeb/2671cac4af572751f6108f53ab926032" rel="noopener noreferrer"&gt;here&lt;/a&gt;. We will use this as a foundation and make some slight modifications to suit our use case. Add the following code to &lt;code&gt;frontend/SanityAPI.ts&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// frontend/SanityAPI.ts&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SanityClientOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;token&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;useCdn&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;QueryParameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;number&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;sanityCredentials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INSERT_YOUR_PROJECT_ID_HERE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;production&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sanityClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SanityClientOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useCdn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;apiVersion&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;options&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;hasToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&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;baseHost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useCdn&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;hasToken&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apicdn.sanity.io&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;api.sanity.io&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;endpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;baseHost&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/v&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/data/query/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Parse JSON and throw on bad responses&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;responseHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusText&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// We need to prefix groq query params with `$` and quote the strings&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transformedParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;QueryParameters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;QueryParameters&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;`$&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;QueryParameters&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;urlParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;...(&lt;/span&gt;&lt;span class="nx"&gt;parameters&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;transformedParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parameters&lt;/span&gt;&lt;span class="p"&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;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;urlParams&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;?&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;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hasToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responseHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="c1"&gt;// The query results are in the `result` property&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="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;runQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sanityClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;sanityCredentials&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;useCdn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2021-03-25&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&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;urlFor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;imageURLBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sanityCredentials&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;runQuery&lt;/code&gt; function. We provide a &lt;a href="https://www.sanity.io/docs/overview-groq" rel="noopener noreferrer"&gt;GROQ&lt;/a&gt; query as the first parameter, the second is a callback function to be executed on the response to the provided query. This function will be called anytime we need to pull data from our backend. &lt;/p&gt;

&lt;p&gt;We also added a helper function named &lt;code&gt;urlFor&lt;/code&gt; which will be used to generate image URLs for images hosted on Sanity. &lt;/p&gt;

&lt;p&gt;Lastly, don't forget to replace the &lt;code&gt;INSERT_YOUR_PROJECT_ID_HERE&lt;/code&gt; placeholder with your &lt;code&gt;projectId&lt;/code&gt; as obtained earlier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the components
&lt;/h2&gt;

&lt;p&gt;Our application will display the movies and actors saved on our Sanity Content Lake. In the &lt;code&gt;components&lt;/code&gt; directory, create a directory named &lt;code&gt;movie&lt;/code&gt; to hold movie-related components and another named &lt;code&gt;actor&lt;/code&gt; to hold actor-related components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;frontend/components/actor frontend/components/movie
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;movie&lt;/code&gt; directory, create two files named &lt;code&gt;Movies.tsx&lt;/code&gt; and &lt;code&gt;Movie.tsx&lt;/code&gt;. In the &lt;code&gt;Movies.tsx&lt;/code&gt;, add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// frontend/components/movie/Movies.tsx&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;React&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="s2"&gt;../../dep.ts&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;Movie&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Movie.tsx&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;runQuery&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="s2"&gt;../../SanityAPI.ts&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&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;Movies&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setMovies&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&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;updateMovies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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="nf"&gt;setMovies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&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;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`*[_type == 'movie']{_id, title, overview, releaseDate, poster}`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;runQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateMovies&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container mx-auto px-6"&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-gray-700 text-2xl font-medium"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Bestselling Sci-fi Movies
      &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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"p-10 grid grid-cols-1 sm:grid-cols-1 md:grid-cols-1 lg:grid-cols-1 xl:grid-cols-3 gap-5"&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;movies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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="nc"&gt;Movie&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;movie&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="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;movie&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;))&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="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Movies&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this component, we make a GROQ request to the Sanity API using the helper client we created earlier. In our query, we request for the id, title, overview, release date and poster image for all the movies on our backend.&lt;/p&gt;

&lt;p&gt;Next, add the following to &lt;code&gt;Movie.tsx&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// frontend/components/movie/Movie.tsx&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;React&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="s2"&gt;../../dep.ts&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;urlFor&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="s2"&gt;../../SanityAPI.ts&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;Movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&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;overview&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;releaseDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;poster&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"max-w-xs rounded overflow-hidden shadow-lg my-2"&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;urlFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;poster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_ref&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&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;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;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"px-6 py-4"&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-xl mb-2 text-center"&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;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;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-md justify-start"&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;overview&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="nx"&gt;children&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="nx"&gt;text&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;p&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"align-bottom"&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;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-gray text-center text-xs font-medium my-5"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Released on &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;releaseDate&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toDateString&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;p&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;Movie&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using Tailwind, we design a card that holds the poster image for the movie with the image URL generated by the &lt;code&gt;urlFor&lt;/code&gt; helper function we declared earlier. We are also displaying the other details provided by the &lt;code&gt;Movies&lt;/code&gt; component. &lt;/p&gt;

&lt;p&gt;As we did for the movies, create two files named &lt;code&gt;Actor.tsx&lt;/code&gt; and &lt;code&gt;Actors.tsx&lt;/code&gt; in the &lt;code&gt;actor&lt;/code&gt; directory. Add the following to &lt;code&gt;Actor.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// frontend/components/actor/Actor.tsx&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;React&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="s2"&gt;../../dep.ts&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;urlFor&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="s2"&gt;../../SanityAPI.ts&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;Actor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defaultImageURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://images.vexels.com/media/users/3/140384/isolated/preview/fa2513b856a0c96691ae3c5c39629f31-girl-profile-avatar-1-by-vexels.png&lt;/span&gt;&lt;span class="dl"&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;&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;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"max-w-xs rounded overflow-hidden shadow-lg my-2"&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;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"w-full"&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="s2"&gt;`&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="nf"&gt;urlFor&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="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;defaultImageURL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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;name&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;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"px-6 py-4"&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-xl mb-2 text-center"&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;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;&amp;lt;/&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;Actor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For actors, we only display their picture and name. Because we don't have pictures of all the actors in our backend, we specify an image url to be used if a picture is not available. &lt;/p&gt;

&lt;p&gt;Next, in the &lt;code&gt;Actors.tsx&lt;/code&gt; file, add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// frontend/components/actor/Actors.tsx&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;React&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="s2"&gt;../../dep.ts&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;runQuery&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="s2"&gt;../../SanityAPI.ts&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;Actor&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Actor.tsx&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&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;Actors&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setActors&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&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;updateActors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;actors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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="nf"&gt;setActors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actors&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&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;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`*[_type == 'person']{ _id, name, image}`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;runQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateActors&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container mx-auto px-6"&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-gray-700 text-2xl font-medium"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;A-List Movie Stars&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"p-10 grid grid-cols-1 sm:grid-cols-1 md:grid-cols-1 lg:grid-cols-1 xl:grid-cols-3 gap-5"&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;actor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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="nc"&gt;Actor&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;actor&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="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;actor&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;))&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="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Actors&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we make a GROQ query to retrieve all the actors in our backed and map through the returned array, rendering and &lt;code&gt;Actor&lt;/code&gt; component for each object in the array. &lt;/p&gt;

&lt;p&gt;With these in place, we can update our &lt;code&gt;App.tsx&lt;/code&gt; file as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// frontend/components/App.tsx&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;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Switch&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="s2"&gt;../dep.ts&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;Movies&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./movie/Movies.tsx&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;Actors&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./actor/Actors.tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-white"&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;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container mx-auto px-6 py-3"&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;nav&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"sm:flex sm:justify-center sm:items-center mt-4"&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;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex flex-col sm:flex-row"&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;Link&lt;/span&gt;
                &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/movies"&lt;/span&gt;
                &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mt-3 text-gray-600 hover:underline sm:mx-3 sm:mt-0"&lt;/span&gt;
              &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                Movies
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&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;Link&lt;/span&gt;
                &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/actors"&lt;/span&gt;
                &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mt-3 text-gray-600 hover:underline sm:mx-3 sm:mt-0"&lt;/span&gt;
              &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                Actors
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&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;nav&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;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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"my-8"&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;Switch&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;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt; &lt;span class="na"&gt;exact&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;Movies&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;Route&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;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/movies"&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;Movies&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;Route&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;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/actors"&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;Actors&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;Route&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;Switch&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="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;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we implement the client side routing for the React UI as well as style the container for the components. &lt;/p&gt;

&lt;h2&gt;
  
  
  Hydrating our application
&lt;/h2&gt;

&lt;p&gt;At the moment, our application HTML is generated server-side. However, our application will not have the desired functionality because our JavaScript functionality isn't loaded on our page -clicking any link will trigger another render server-side instead of the routing being handled client-side. To fix this, we need to hydrate our React application as well as provide the JavaScript to be loaded client-side. This way, once the index page is loaded, the JavaScript will take over and handle everything else. &lt;/p&gt;

&lt;p&gt;Let's start by creating the JavaScript to be used client-side. In the &lt;code&gt;ssr&lt;/code&gt; directory, create a new file called &lt;code&gt;client.tsx&lt;/code&gt;. In it, add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// frontend/ssr/client.tsx&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;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BrowserRouter&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="s2"&gt;../dep.ts&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;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../components/App.tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hydrate&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;BrowserRouter&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;App&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;BrowserRouter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice, we've also added a &lt;code&gt;BrowserRouter&lt;/code&gt; to handle client-side routing once the page is loaded. &lt;/p&gt;

&lt;p&gt;Next, we need to modify the &lt;code&gt;ssr/server.tsx&lt;/code&gt; file to include the JavaScript bundle created (by Deno) from the &lt;code&gt;ssr/client.tsx&lt;/code&gt; file. We also need to add a route that will allow the browser to download the bundled Javascript to be loaded client-side. &lt;/p&gt;

&lt;p&gt;Update &lt;code&gt;ssr/server.tsx&lt;/code&gt; to match the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// frontend/ssr/server.tsx&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;Application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://deno.land/x/oak@v7.3.0/mod.ts&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;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;ReactDOMServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;StaticRouter&lt;/span&gt;&lt;span class="p"&gt;,&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="s2"&gt;../dep.ts&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;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../components/App.tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8000&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;jsBundlePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/main.js&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;diagnostics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./ssr/client.tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;bundle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;esm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;compilerOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dom.iterable&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;esnext&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;diagnostics&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ReactDOMServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;renderToString&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;StaticRouter&lt;/span&gt; &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&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;context&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;context&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="nc"&gt;App&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;StaticRouter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text/html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8"&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
    &amp;lt;link href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css" rel="stylesheet"&amp;gt;
    &amp;lt;title&amp;gt;Sanity &amp;lt;-&amp;gt; Deno&amp;lt;/title&amp;gt;
    &amp;lt;script type="module" src="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;jsBundlePath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;div id="root"&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsBundlePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/javascript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deno:///bundle.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allowedMethods&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server is running on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We specify the bundled Javascript path as &lt;code&gt;/main.js&lt;/code&gt; and added it as a route to our oak application.&lt;/p&gt;

&lt;p&gt;Next using the &lt;code&gt;Deno.emit()&lt;/code&gt; compiler API, we transpile and bundle  our &lt;code&gt;client.tsx&lt;/code&gt; file into JavaScript that can be run on the browser. We also update the JSX for the index page to include a script tag pointing to our bundle path. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Deno.emit()&lt;/code&gt; is currently marked as unstable which means we need to give our application explicit permission to perform this operation. We do this with the &lt;code&gt;--unstable&lt;/code&gt; flag. &lt;/p&gt;

&lt;p&gt;With this in place, our server side rendered app is ready for a test run. Start your Sanity project (if you stopped it).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;backend

sanity start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run your deno application using the command below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;frontend

deno run &lt;span class="nt"&gt;--allow-net&lt;/span&gt; &lt;span class="nt"&gt;--unstable&lt;/span&gt; &lt;span class="nt"&gt;--allow-read&lt;/span&gt; ./ssr/server.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to &lt;a href="http://localhost:8000/" rel="noopener noreferrer"&gt;http://localhost:8000/&lt;/a&gt; to see your application in action. &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%2Faq081vm057htqw75jq04.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faq081vm057htqw75jq04.gif" alt="Gif image of the movie app"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Deno is relatively new in the world of web development but it is gradually gaining popularity and acceptance due to some of its advantages over Node.js. As seen in this tutorial, we learned about Deno and why it was built. We then proceeded to build a server-side rendered movie application using Deno and React. &lt;/p&gt;

&lt;p&gt;For proper content management, we leverage the existing infrastructure put in place by Sanity to build the backend of the application. I hope this tutorial has given you some insight into what Deno is, and how to combine it with a frontend framework such as React.&lt;/p&gt;

&lt;p&gt;The complete source code for the application built in this tutorial can be found &lt;a href="https://github.com/yemiwebby/sanity-deno" rel="noopener noreferrer"&gt;here on GitHub&lt;/a&gt;. Happy coding!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How To Build a Customer List Management App with React and TypeScript</title>
      <dc:creator>Oluyemi</dc:creator>
      <pubDate>Mon, 17 Jun 2019 18:47:34 +0000</pubDate>
      <link>https://dev.to/digitalocean/how-to-build-a-customer-list-management-app-with-react-and-typescript-39np</link>
      <guid>https://dev.to/digitalocean/how-to-build-a-customer-list-management-app-with-react-and-typescript-39np</guid>
      <description>&lt;p&gt;&lt;em&gt;The author selected the &lt;a href="https://www.brightfunds.org/funds/tech-education"&gt;Tech Education Fund&lt;/a&gt; to receive a donation as part of the &lt;a href="https://do.co/w4do-cta"&gt;Write for DOnations&lt;/a&gt; program.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt; has brought a lot of improvement into how &lt;a href="https://www.javascript.com/"&gt;JavaScript&lt;/a&gt; developers structure and write code for apps, especially web applications. Defined as a superset of JavaScript, TypeScript behaves identically to JavaScript but with extra features designed to help developers build larger and more complex programs with fewer or no bugs. TypeScript is increasingly gaining popularity; adopted by major companies like Google for the Angular web framework. The &lt;a href="https://nestjs.com/"&gt;Nest.js&lt;/a&gt; back-end framework was also built with TypeScript.&lt;/p&gt;

&lt;p&gt;One of the ways to improve productivity as a developer is the ability to implement new features as quickly as possible without any concern over breaking the existing app in production. To achieve this, writing statically typed code is a style adopted by many seasoned developers. Statically typed programming languages like TypeScript enforce an association for every variable with a data type; such as a string, integer, boolean, and so on. One of the major benefits of using a statically typed programming language is that type checking is completed at compile time, therefore developers can see errors in their code at a very early stage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt; is an open-source JavaScript library, which developers use to create high-end user interfaces for scalable web applications. The great performance and dynamic user interfaces built with React for single-page applications make it a popular choice among developers.&lt;/p&gt;

&lt;p&gt;In this tutorial, you will create a customer list management application with a separate REST API backend and a frontend built with React and TypeScript. You will build the backend using a fake REST API named &lt;a href="https://github.com/typicode/json-server"&gt;&lt;code&gt;json-server&lt;/code&gt;&lt;/a&gt;. You'll use it to quickly set up a CRUD (Create, Read, Update, and Delete) backend. Consequently you can focus on handling the front-end logic of an application using React and TypeScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To complete this tutorial, you will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A local installation of &lt;a href="https://nodejs.org/en/"&gt;Node.js&lt;/a&gt; (at least v6) and &lt;a href="https://www.npmjs.com/"&gt;&lt;code&gt;npm&lt;/code&gt;&lt;/a&gt; (at least v5.2). Node.js is a JavaScript run-time environment that allows you to run your code outside of the browser. It comes with a pre-installed package manager called &lt;code&gt;npm&lt;/code&gt;, which lets you install and update packages. To install these on macOS or Ubuntu 18.04, follow the steps in &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-node-js-and-create-a-local-development-environment-on-macos"&gt;How to Install Node.js and Create a Local Development Environment on macOS&lt;/a&gt; or the "Installing Using a PPA" section of &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-18-04"&gt;How To Install Node.js on Ubuntu 18.04&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A local installation of Yarn; &lt;a href="https://yarnpkg.com/en/docs/install#mac-stable"&gt;follow these steps&lt;/a&gt; to install Yarn on your operating system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A basic understanding of TypeScript and &lt;a href="https://www.digitalocean.com/community/tutorial_series/how-to-code-in-javascript"&gt;JavaScript&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A text editor installed; such as &lt;a href="https://code.visualstudio.com/"&gt;Visual Studio Code&lt;/a&gt;, &lt;a href="https://atom.io/"&gt;Atom&lt;/a&gt;, or &lt;a href="https://www.sublimetext.com/"&gt;Sublime Text&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1 — Installing TypeScript and Creating the React Application
&lt;/h2&gt;

&lt;p&gt;In this step, you will install the TypeScript package globally on your machine by using the Node Package Manager (&lt;code&gt;npm&lt;/code&gt;). After that, you will also install React and its dependencies, and check that your React app is working by running the development server.&lt;/p&gt;

&lt;p&gt;To begin, open a terminal and run the following command to install TypeScript:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g typescript
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the installation process is complete, execute the following command to check your installation of TypeScript:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tsc -v
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You will see the current version installed on your machine:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Output
Version 3.4.5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next, you will install the React application by using the &lt;a href="https://github.com/facebook/create-react-app"&gt;&lt;code&gt;create-react-app&lt;/code&gt;&lt;/a&gt; tool to set up the application with a single command. You'll use the &lt;code&gt;npx&lt;/code&gt; command, which is a package runner tool that comes with &lt;code&gt;npm&lt;/code&gt; 5.2+. The &lt;code&gt;create-react-app&lt;/code&gt; tool has built-in support for working with TypeScript without any extra configuration required. Run the following command to create and install a new React application named &lt;code&gt;typescript-react-app&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app typescript-react-app --typescript
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The preceding command will create a new React application with the name &lt;code&gt;typescript-react-app&lt;/code&gt;. The &lt;code&gt;--typescript&lt;/code&gt; flag will set the default filetype for React components to &lt;code&gt;.tsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before you complete this section, the application will require moving from one port to another. To do that, you will need to install a routing library for your React application named &lt;a href="https://www.npmjs.com/package/react-router"&gt;React Router&lt;/a&gt; and its corresponding TypeScript definitions. You will use &lt;code&gt;yarn&lt;/code&gt; to install the library and other packages for this project. This is because &lt;code&gt;yarn&lt;/code&gt; is faster, especially for installing dependencies for a React application. Move into the newly created project folder and then install React Router with the following command:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd typescript-react-app
yarn add react-router-dom
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You now have the React Router package, which will provide the routing functionality within your project. Next, run the following command to install the TypeScript definitions for React Router:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add @types/react-router-dom
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now you'll install &lt;a href="https://github.com/axios/axios"&gt;&lt;code&gt;axios&lt;/code&gt;&lt;/a&gt;, which is a promised-based HTTP client for browsers, to help with the process of performing HTTP requests from the different components that you will create within the application:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add axios
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the installation process is complete, start the development server with:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Your application will be running on &lt;code&gt;http://localhost:3000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bx3itt9K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://assets.digitalocean.com/articles/reacttypescript/step1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bx3itt9K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://assets.digitalocean.com/articles/reacttypescript/step1.png" alt="React application homepage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You have successfully installed TypeScript, created a new React application, and installed React Router in order to help with navigating from one page of the application to another. In the next section, you will set up the back-end server for the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Creating a JSON Server
&lt;/h2&gt;

&lt;p&gt;In this step, you'll create a mock server that your React application can quickly connect with, as well as use its resources. It is important to note that this back-end service is not suitable for an application in production. You can use Nest.js, Express, or any other back-end technology to build a RESTful API in production. &lt;code&gt;json-server&lt;/code&gt; is a useful tool whenever you need to create a prototype and mock a back-end server.&lt;/p&gt;

&lt;p&gt;You can use either &lt;code&gt;npm&lt;/code&gt; or &lt;code&gt;yarn&lt;/code&gt; to install &lt;code&gt;json-server&lt;/code&gt; on your machine. This will make it available from any directory of your project whenever you might need to make use of it. Open a new terminal window and run this command to install &lt;code&gt;json-server&lt;/code&gt; while you are still within the project directory:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn global add json-server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next, you will create a JSON file that will contain the data that will be exposed by the REST API. For the objects specified in this file (which you'll create), a CRUD endpoint will be generated automatically. To begin, create a new folder named &lt;code&gt;server&lt;/code&gt; and then move into it:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir server
cd server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, use &lt;code&gt;nano&lt;/code&gt; to create and open a new file named &lt;code&gt;db.json&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano db.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add the following content to the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    {
        "customers": [
            {
                "id": 1,
                "first_name": "Customer_1",
                "last_name": "Customer_11",
                "email": "customer1@mail.com",
                "phone": "00000000000",
                "address": "Customer_1 Address",
                "description": "Customer_1 description"
            },
            {
                "id": 2,
                "first_name": "Customer_2",
                "last_name": "Customer_2",
                "email": "customer2@mail.com",
                "phone": "00000000000",
                "address": "Customer_2 Adress",
                "description": "Customer_2 Description"
            }
        ]
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The JSON structure consists of a customer object, which has two datasets assigned. Each customer consists of seven properties: &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;first_name&lt;/code&gt;, &lt;code&gt;last_name&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;phone&lt;/code&gt;, and &lt;code&gt;address&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Save and exit the file.&lt;/p&gt;

&lt;p&gt;By default, the &lt;code&gt;json-server&lt;/code&gt; runs on port &lt;code&gt;3000&lt;/code&gt;—this is the same port on which your React application runs. To avoid conflict, you can change the default port for the &lt;code&gt;json-server&lt;/code&gt;. To do that, move to the root directory of the application:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ~/typescript-react-app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Open the application with your preferred text editor and create a new file named &lt;code&gt;json-server.json&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano json-server.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now insert the following to update the port number:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "port": 5000
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will act as the configuration file for the &lt;code&gt;json-server&lt;/code&gt; and it will ensure that the server runs on the port specified in it at all times.&lt;/p&gt;

&lt;p&gt;Save and exit the file.&lt;/p&gt;

&lt;p&gt;To run the server, use the following command:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;json-server --watch server/db.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will start the &lt;code&gt;json-server&lt;/code&gt; on port &lt;code&gt;5000&lt;/code&gt;. If you navigate to &lt;code&gt;http://localhost:5000/customers&lt;/code&gt; in your browser, you will see the server showing your customer list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CQYNhFGx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://assets.digitalocean.com/articles/reacttypescript/step2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CQYNhFGx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://assets.digitalocean.com/articles/reacttypescript/step2.png" alt="Customer list shown by json-server"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To streamline the process of running the &lt;code&gt;json-server&lt;/code&gt;, you can update &lt;code&gt;package.json&lt;/code&gt; with a new property named &lt;code&gt;server&lt;/code&gt; to the &lt;code&gt;scripts&lt;/code&gt; object as shown here:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
...
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "server": "json-server --watch server/db.json"
  },
...
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Save and exit the file.&lt;/p&gt;

&lt;p&gt;Now anytime you wish to start the &lt;code&gt;json-server&lt;/code&gt;, all you have to do is run &lt;code&gt;yarn server&lt;/code&gt; from the terminal.&lt;/p&gt;

&lt;p&gt;You've created a simple REST API that you will use as the back-end server for this application. You also created a customer JSON object that will be used as the default data for the REST API. Lastly, you configured an alternative port for the back-end server powered by &lt;code&gt;json-server&lt;/code&gt;. Next, you will build reusable components for your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — Creating Reusable Components
&lt;/h2&gt;

&lt;p&gt;In this section, you will create the required React components for the application. This will include components to create, display, and edit the details of a particular customer in the database respectively. You'll also build some of the TypeScript interfaces for your application.&lt;/p&gt;

&lt;p&gt;To begin, move back to the terminal where you have the React application running and stop the development server with &lt;code&gt;CTRL + C&lt;/code&gt;. Next, navigate to the &lt;code&gt;./src/&lt;/code&gt; folder:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ./src/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, create a new folder named &lt;code&gt;components&lt;/code&gt; inside of it and move into the new folder:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir components
cd components
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Within the newly created folder, create a &lt;code&gt;customer&lt;/code&gt; folder and then move into it:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir customer
cd customer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now create two new files named &lt;code&gt;Create.tsx&lt;/code&gt; and &lt;code&gt;Edit.tsx&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch Create.tsx Edit.tsx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These files are React reusable components that will render the forms and hold all the business logic for creating and editing the details of a customer respectively.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;Create.tsx&lt;/code&gt; file in your text editor and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import * as React from 'react';
    import axios from 'axios';
    import { RouteComponentProps, withRouter } from 'react-router-dom';

    export interface IValues {
        first_name: string,
        last_name: string,
        email: string,
        phone: string,
        address: string,
        description: string,
    }
    export interface IFormState {
        [key: string]: any;
        values: IValues[];
        submitSuccess: boolean;
        loading: boolean;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here you've imported &lt;code&gt;React&lt;/code&gt;, &lt;code&gt;axios&lt;/code&gt;, and other required components necessary for routing from the React Router package. After that you created two new interfaces named &lt;code&gt;IValues&lt;/code&gt; and &lt;code&gt;IFormState&lt;/code&gt;. &lt;a href="https://www.typescriptlang.org/docs/handbook/interfaces.html"&gt;TypeScript &lt;em&gt;interfaces&lt;/em&gt;&lt;/a&gt; help to define the specific type of values that should be passed to an object and enforce consistency throughout an application. This ensures that bugs are less likely to appear in your program.&lt;/p&gt;

&lt;p&gt;Next, you will build a &lt;code&gt;Create&lt;/code&gt; component that extends &lt;code&gt;React.Component&lt;/code&gt;. Add the following code to the &lt;code&gt;Create.tsx&lt;/code&gt; file immediately after the &lt;code&gt;IFormState&lt;/code&gt; interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    class Create extends React.Component&amp;lt;RouteComponentProps, IFormState&amp;gt; {
        constructor(props: RouteComponentProps) {
            super(props);
            this.state = {
                first_name: '',
                last_name: '',
                email: '',
                phone: '',
                address: '',
                description: '',
                values: [],
                loading: false,
                submitSuccess: false,
            }
        }
    }
    export default withRouter(Create)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here you've defined a React component in Typescript. In this case, the &lt;code&gt;Create&lt;/code&gt; class component accepts &lt;code&gt;props&lt;/code&gt; (short for “properties”) of type &lt;code&gt;RouteComponentProps&lt;/code&gt; and uses a state of type &lt;code&gt;IFormState&lt;/code&gt;. Then, inside the constructor, you initialized the &lt;code&gt;state&lt;/code&gt; object and defined all the variables that will represent the rendered values for a customer.&lt;/p&gt;

&lt;p&gt;Next, add these methods within the &lt;code&gt;Create&lt;/code&gt; class component, just after the constructor. You'll use these methods to process customer forms and handle all changes in the input fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              values: [],
              loading: false,
              submitSuccess: false,
          }
      }

      private processFormSubmission = (e: React.FormEvent&amp;lt;HTMLFormElement&amp;gt;): void =&amp;gt; {
              e.preventDefault();
              this.setState({ loading: true });
              const formData = {
                  first_name: this.state.first_name,
                  last_name: this.state.last_name,
                  email: this.state.email,
                  phone: this.state.phone,
                  address: this.state.address,
                  description: this.state.description,
              }
              this.setState({ submitSuccess: true, values: [...this.state.values, formData], loading: false });
              axios.post(`http://localhost:5000/customers`, formData).then(data =&amp;gt; [
                  setTimeout(() =&amp;gt; {
                      this.props.history.push('/');
                  }, 1500)
              ]);
          }

          private handleInputChanges = (e: React.FormEvent&amp;lt;HTMLInputElement&amp;gt;) =&amp;gt; {
              e.preventDefault();
              this.setState({
                  [e.currentTarget.name]: e.currentTarget.value,
          })
      }

    ...
    export default withRouter(Create)
    ...

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



&lt;p&gt;The &lt;code&gt;processFormSubmission()&lt;/code&gt; method receives the details of the customer from the application state and posts it to the database using &lt;code&gt;axios&lt;/code&gt;. The &lt;code&gt;handleInputChanges()&lt;/code&gt; uses &lt;code&gt;React.FormEvent&lt;/code&gt; to obtain the values of all input fields and calls &lt;code&gt;this.setState()&lt;/code&gt; to update the state of the application.&lt;/p&gt;

&lt;p&gt;Next, add the &lt;code&gt;render()&lt;/code&gt; method within the &lt;code&gt;Create&lt;/code&gt; class component immediately after the &lt;code&gt;handleInputchanges()&lt;/code&gt; method. This &lt;code&gt;render()&lt;/code&gt; method will display the form to create a new customer in the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      public render() {
          const { submitSuccess, loading } = this.state;
          return (
              &amp;lt;div&amp;gt;
                  &amp;lt;div className={"col-md-12 form-wrapper"}&amp;gt;
                      &amp;lt;h2&amp;gt; Create Post &amp;lt;/h2&amp;gt;
                      {!submitSuccess &amp;amp;&amp;amp; (
                          &amp;lt;div className="alert alert-info" role="alert"&amp;gt;
                              Fill the form below to create a new post
                      &amp;lt;/div&amp;gt;
                      )}
                      {submitSuccess &amp;amp;&amp;amp; (
                          &amp;lt;div className="alert alert-info" role="alert"&amp;gt;
                              The form was successfully submitted!
                              &amp;lt;/div&amp;gt;
                      )}
                      &amp;lt;form id={"create-post-form"} onSubmit={this.processFormSubmission} noValidate={true}&amp;gt;
                          &amp;lt;div className="form-group col-md-12"&amp;gt;
                              &amp;lt;label htmlFor="first_name"&amp;gt; First Name &amp;lt;/label&amp;gt;
                              &amp;lt;input type="text" id="first_name" onChange={(e) =&amp;gt; this.handleInputChanges(e)} name="first_name" className="form-control" placeholder="Enter customer's first name" /&amp;gt;
                          &amp;lt;/div&amp;gt;
                          &amp;lt;div className="form-group col-md-12"&amp;gt;
                              &amp;lt;label htmlFor="last_name"&amp;gt; Last Name &amp;lt;/label&amp;gt;
                              &amp;lt;input type="text" id="last_name" onChange={(e) =&amp;gt; this.handleInputChanges(e)} name="last_name" className="form-control" placeholder="Enter customer's last name" /&amp;gt;
                          &amp;lt;/div&amp;gt;
                          &amp;lt;div className="form-group col-md-12"&amp;gt;
                              &amp;lt;label htmlFor="email"&amp;gt; Email &amp;lt;/label&amp;gt;
                              &amp;lt;input type="email" id="email" onChange={(e) =&amp;gt; this.handleInputChanges(e)} name="email" className="form-control" placeholder="Enter customer's email address" /&amp;gt;
                          &amp;lt;/div&amp;gt;
                          &amp;lt;div className="form-group col-md-12"&amp;gt;
                              &amp;lt;label htmlFor="phone"&amp;gt; Phone &amp;lt;/label&amp;gt;
                              &amp;lt;input type="text" id="phone" onChange={(e) =&amp;gt; this.handleInputChanges(e)} name="phone" className="form-control" placeholder="Enter customer's phone number" /&amp;gt;
                          &amp;lt;/div&amp;gt;
                          &amp;lt;div className="form-group col-md-12"&amp;gt;
                              &amp;lt;label htmlFor="address"&amp;gt; Address &amp;lt;/label&amp;gt;
                              &amp;lt;input type="text" id="address" onChange={(e) =&amp;gt; this.handleInputChanges(e)} name="address" className="form-control" placeholder="Enter customer's address" /&amp;gt;
                          &amp;lt;/div&amp;gt;
                          &amp;lt;div className="form-group col-md-12"&amp;gt;
                              &amp;lt;label htmlFor="description"&amp;gt; Description &amp;lt;/label&amp;gt;
                              &amp;lt;input type="text" id="description" onChange={(e) =&amp;gt; this.handleInputChanges(e)} name="description" className="form-control" placeholder="Enter Description" /&amp;gt;
                          &amp;lt;/div&amp;gt;
                          &amp;lt;div className="form-group col-md-4 pull-right"&amp;gt;
                              &amp;lt;button className="btn btn-success" type="submit"&amp;gt;
                                  Create Customer
                              &amp;lt;/button&amp;gt;
                              {loading &amp;amp;&amp;amp;
                                  &amp;lt;span className="fa fa-circle-o-notch fa-spin" /&amp;gt;
                              }
                          &amp;lt;/div&amp;gt;
                      &amp;lt;/form&amp;gt;
                  &amp;lt;/div&amp;gt;
              &amp;lt;/div&amp;gt;
          )
      }

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



&lt;p&gt;Here, you created a form with the input fields to hold the values of the &lt;code&gt;first_name&lt;/code&gt;, &lt;code&gt;last_name&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;phone&lt;/code&gt;, &lt;code&gt;address&lt;/code&gt;, and &lt;code&gt;description&lt;/code&gt; of a customer. Each of the input fields have a method &lt;code&gt;handleInputChanges()&lt;/code&gt; that runs on every keystroke, updating the React &lt;code&gt;state&lt;/code&gt; with the value it obtains from the input field. Furthermore, depending on the state of the application, a boolean variable named &lt;code&gt;submitSuccess&lt;/code&gt; will control the message that the application will display before and after creating a new customer.&lt;/p&gt;

&lt;p&gt;You can see the complete code for this file in this &lt;a href="https://github.com/yemiwebby/typescript-react-customer-app/blob/master/src/components/customer/Create.tsx"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Save and exit &lt;code&gt;Create.tsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now that you have added the appropriate logic to the &lt;code&gt;Create&lt;/code&gt; component file for the application, you'll proceed to add contents for the &lt;code&gt;Edit&lt;/code&gt; component file.&lt;/p&gt;

&lt;p&gt;Open your &lt;code&gt;Edit.tsx&lt;/code&gt; file within the &lt;code&gt;customer&lt;/code&gt; folder, and start by adding the following content to import &lt;code&gt;React&lt;/code&gt;, &lt;code&gt;axios&lt;/code&gt;, and also define TypeScript interfaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import * as React from 'react';
    import { RouteComponentProps, withRouter } from 'react-router-dom';
    import axios from 'axios';

    export interface IValues {
        [key: string]: any;
    }
    export interface IFormState {
        id: number,
        customer: any;
        values: IValues[];
        submitSuccess: boolean;
        loading: boolean;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Similarly to the &lt;code&gt;Create&lt;/code&gt; component, you import the required modules and create &lt;code&gt;IValues&lt;/code&gt; and &lt;code&gt;IFormState&lt;/code&gt; interfaces respectively. The &lt;code&gt;IValues&lt;/code&gt; interface defines the data type for the input fields' values, while you'll use &lt;code&gt;IFormState&lt;/code&gt; to declare the expected type for the state object of the application.&lt;/p&gt;

&lt;p&gt;Next, create the &lt;code&gt;EditCustomer&lt;/code&gt; class component directly after the &lt;code&gt;IFormState&lt;/code&gt; interface block as shown here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    ...
    class EditCustomer extends React.Component&amp;lt;RouteComponentProps&amp;lt;any&amp;gt;, IFormState&amp;gt; {
        constructor(props: RouteComponentProps) {
            super(props);
            this.state = {
                id: this.props.match.params.id,
                customer: {},
                values: [],
                loading: false,
                submitSuccess: false,
            }
        }
    }
    export default withRouter(EditCustomer)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This component takes the &lt;code&gt;RouteComponentProps&amp;lt;any&amp;gt;&lt;/code&gt; and an interface of &lt;code&gt;IFormState&lt;/code&gt; as a parameter. You use the addition of &lt;code&gt;&amp;lt;any&amp;gt;&lt;/code&gt; to the &lt;code&gt;RouteComponentProps&lt;/code&gt; because whenever React Router parses path parameters, it doesn’t do any type conversion to ascertain whether the type of the data is &lt;code&gt;number&lt;/code&gt; or &lt;code&gt;string&lt;/code&gt;. Since you're expecting a parameter for &lt;code&gt;uniqueId&lt;/code&gt; of a customer, it is safer to use &lt;code&gt;any&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now add the following methods within the component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;...&lt;br&gt;
        public componentDidMount(): void {&lt;br&gt;
            axios.get(&lt;code&gt;http://localhost:5000/customers/${this.state.id}&lt;/code&gt;).then(data =&amp;gt; {&lt;br&gt;
                this.setState({ customer: data.data });&lt;br&gt;
            })&lt;br&gt;
        }&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    private processFormSubmission = async (e: React.FormEvent&amp;lt;HTMLFormElement&amp;gt;): Promise&amp;lt;void&amp;gt; =&amp;gt; {
        e.preventDefault();
        this.setState({ loading: true });
        axios.patch(`http://localhost:5000/customers/${this.state.id}`, this.state.values).then(data =&amp;gt; {
            this.setState({ submitSuccess: true, loading: false })
            setTimeout(() =&amp;gt; {
                this.props.history.push('/');
            }, 1500)
        })
    }

    private setValues = (values: IValues) =&amp;gt; {
        this.setState({ values: { ...this.state.values, ...values } });
    }
    private handleInputChanges = (e: React.FormEvent&amp;lt;HTMLInputElement&amp;gt;) =&amp;gt; {
        e.preventDefault();
        this.setValues({ [e.currentTarget.id]: e.currentTarget.value })
    }
...
}

export default withRouter(EditCustomer)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


First, you add a `componentDidMount()` method, which is a lifecycle method that is being called when the component is created. The method takes the `id` obtained from the route parameter to identify a particular customer as a parameter, uses it to retrieve their details from the database and then populates the form with it. Furthermore, you add methods to process form submission and handle changes made to the values of the input fields.

Lastly, add the `render()` method for the `Edit` component:




    ```
   ...
        public render() {
            const { submitSuccess, loading } = this.state;
            return (
                &amp;lt;div className="App"&amp;gt;
                    {this.state.customer &amp;amp;&amp;amp;
                        &amp;lt;div&amp;gt;
                            &amp;lt; h1 &amp;gt; Customer List Management App&amp;lt;/h1&amp;gt;
                            &amp;lt;p&amp;gt; Built with React.js and TypeScript &amp;lt;/p&amp;gt;

                            &amp;lt;div&amp;gt;
                                &amp;lt;div className={"col-md-12 form-wrapper"}&amp;gt;
                                    &amp;lt;h2&amp;gt; Edit Customer &amp;lt;/h2&amp;gt;
                                    {submitSuccess &amp;amp;&amp;amp; (
                                        &amp;lt;div className="alert alert-info" role="alert"&amp;gt;
                                            Customer's details has been edited successfully &amp;lt;/div&amp;gt;
                                    )}
                                    &amp;lt;form id={"create-post-form"} onSubmit={this.processFormSubmission} noValidate={true}&amp;gt;
                                        &amp;lt;div className="form-group col-md-12"&amp;gt;
                                            &amp;lt;label htmlFor="first_name"&amp;gt; First Name &amp;lt;/label&amp;gt;
                                            &amp;lt;input type="text" id="first_name" defaultValue={this.state.customer.first_name} onChange={(e) =&amp;gt; this.handleInputChanges(e)} name="first_name" className="form-control" placeholder="Enter customer's first name" /&amp;gt;
                                        &amp;lt;/div&amp;gt;
                                        &amp;lt;div className="form-group col-md-12"&amp;gt;
                                            &amp;lt;label htmlFor="last_name"&amp;gt; Last Name &amp;lt;/label&amp;gt;
                                            &amp;lt;input type="text" id="last_name" defaultValue={this.state.customer.last_name} onChange={(e) =&amp;gt; this.handleInputChanges(e)} name="last_name" className="form-control" placeholder="Enter customer's last name" /&amp;gt;
                                        &amp;lt;/div&amp;gt;
                                        &amp;lt;div className="form-group col-md-12"&amp;gt;
                                            &amp;lt;label htmlFor="email"&amp;gt; Email &amp;lt;/label&amp;gt;
                                            &amp;lt;input type="email" id="email" defaultValue={this.state.customer.email} onChange={(e) =&amp;gt; this.handleInputChanges(e)} name="email" className="form-control" placeholder="Enter customer's email address" /&amp;gt;
                                        &amp;lt;/div&amp;gt;
                                        &amp;lt;div className="form-group col-md-12"&amp;gt;
                                            &amp;lt;label htmlFor="phone"&amp;gt; Phone &amp;lt;/label&amp;gt;
                                            &amp;lt;input type="text" id="phone" defaultValue={this.state.customer.phone} onChange={(e) =&amp;gt; this.handleInputChanges(e)} name="phone" className="form-control" placeholder="Enter customer's phone number" /&amp;gt;
                                        &amp;lt;/div&amp;gt;
                                        &amp;lt;div className="form-group col-md-12"&amp;gt;
                                            &amp;lt;label htmlFor="address"&amp;gt; Address &amp;lt;/label&amp;gt;
                                            &amp;lt;input type="text" id="address" defaultValue={this.state.customer.address} onChange={(e) =&amp;gt; this.handleInputChanges(e)} name="address" className="form-control" placeholder="Enter customer's address" /&amp;gt;
                                        &amp;lt;/div&amp;gt;
                                        &amp;lt;div className="form-group col-md-12"&amp;gt;
                                            &amp;lt;label htmlFor="description"&amp;gt; Description &amp;lt;/label&amp;gt;
                                            &amp;lt;input type="text" id="description" defaultValue={this.state.customer.description} onChange={(e) =&amp;gt; this.handleInputChanges(e)} name="description" className="form-control" placeholder="Enter Description" /&amp;gt;
                                        &amp;lt;/div&amp;gt;
                                        &amp;lt;div className="form-group col-md-4 pull-right"&amp;gt;
                                            &amp;lt;button className="btn btn-success" type="submit"&amp;gt;
                                                Edit Customer &amp;lt;/button&amp;gt;
                                            {loading &amp;amp;&amp;amp;
                                                &amp;lt;span className="fa fa-circle-o-notch fa-spin" /&amp;gt;
                                            }
                                        &amp;lt;/div&amp;gt;
                                    &amp;lt;/form&amp;gt;
                                &amp;lt;/div&amp;gt;
                            &amp;lt;/div&amp;gt;
                        &amp;lt;/div&amp;gt;
                    }
                &amp;lt;/div&amp;gt;
            )
        }

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


&lt;p&gt;Here, you created a form to edit the details of a particular customer, and then populated the input fields within that form with the customer's details that your application's state obtained. Similarly to the &lt;code&gt;Create&lt;/code&gt; component, changes made to all the input fields will be handled by the &lt;code&gt;handleInputChanges()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;You can see the complete code for this file in this &lt;a href="https://github.com/yemiwebby/typescript-react-customer-app/blob/master/src/components/customer/Edit.tsx"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Save and exit &lt;code&gt;Edit.tsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To view the complete list of customers created within the application, you’ll create a new component within the &lt;code&gt;./src/components&lt;/code&gt; folder and name it &lt;code&gt;Home.tsx&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ./src/components
nano Home.tsx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import * as React from 'react';
    import { Link, RouteComponentProps } from 'react-router-dom';
    import axios from 'axios';

    interface IState {
        customers: any[];
    }

    export default class Home extends React.Component&amp;lt;RouteComponentProps, IState&amp;gt; {
        constructor(props: RouteComponentProps) {
            super(props);
            this.state = { customers: [] }
        }
        public componentDidMount(): void {
            axios.get(`http://localhost:5000/customers`).then(data =&amp;gt; {
                this.setState({ customers: data.data })
            })
        }
        public deleteCustomer(id: number) {
            axios.delete(`http://localhost:5000/customers/${id}`).then(data =&amp;gt; {
                const index = this.state.customers.findIndex(customer =&amp;gt; customer.id === id);
                this.state.customers.splice(index, 1);
                this.props.history.push('/');
            })
        }
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here, you've imported &lt;code&gt;React&lt;/code&gt;, &lt;code&gt;axios&lt;/code&gt;, and other required components from React Router. You created two new methods within the &lt;code&gt;Home&lt;/code&gt; component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;componentDidMount()&lt;/code&gt;: The application invokes this method immediately after a component is mounted. Its responsibility here is to retrieve the list of customers and update the home page with it.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;deleteCustomer()&lt;/code&gt;: This method will accept an &lt;code&gt;id&lt;/code&gt; as a parameter and will delete the details of the customer identified with that &lt;code&gt;id&lt;/code&gt; from the database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now add the &lt;code&gt;render()&lt;/code&gt; method to display the table that holds the list of customers for the &lt;code&gt;Home&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public render() {
            const customers = this.state.customers;
            return (
                &amp;lt;div&amp;gt;
                    {customers.length === 0 &amp;amp;&amp;amp; (
                        &amp;lt;div className="text-center"&amp;gt;
                            &amp;lt;h2&amp;gt;No customer found at the moment&amp;lt;/h2&amp;gt;
                        &amp;lt;/div&amp;gt;
                    )}
                    &amp;lt;div className="container"&amp;gt;
                        &amp;lt;div className="row"&amp;gt;
                            &amp;lt;table className="table table-bordered"&amp;gt;
                                &amp;lt;thead className="thead-light"&amp;gt;
                                    &amp;lt;tr&amp;gt;
                                        &amp;lt;th scope="col"&amp;gt;Firstname&amp;lt;/th&amp;gt;
                                        &amp;lt;th scope="col"&amp;gt;Lastname&amp;lt;/th&amp;gt;
                                        &amp;lt;th scope="col"&amp;gt;Email&amp;lt;/th&amp;gt;
                                        &amp;lt;th scope="col"&amp;gt;Phone&amp;lt;/th&amp;gt;
                                        &amp;lt;th scope="col"&amp;gt;Address&amp;lt;/th&amp;gt;
                                        &amp;lt;th scope="col"&amp;gt;Description&amp;lt;/th&amp;gt;
                                        &amp;lt;th scope="col"&amp;gt;Actions&amp;lt;/th&amp;gt;
                                    &amp;lt;/tr&amp;gt;
                                &amp;lt;/thead&amp;gt;
                                &amp;lt;tbody&amp;gt;
                                    {customers &amp;amp;&amp;amp; customers.map(customer =&amp;gt;
                                        &amp;lt;tr key={customer.id}&amp;gt;
                                            &amp;lt;td&amp;gt;{customer.first_name}&amp;lt;/td&amp;gt;
                                            &amp;lt;td&amp;gt;{customer.last_name}&amp;lt;/td&amp;gt;
                                            &amp;lt;td&amp;gt;{customer.email}&amp;lt;/td&amp;gt;
                                            &amp;lt;td&amp;gt;{customer.phone}&amp;lt;/td&amp;gt;
                                            &amp;lt;td&amp;gt;{customer.address}&amp;lt;/td&amp;gt;
                                            &amp;lt;td&amp;gt;{customer.description}&amp;lt;/td&amp;gt;
                                            &amp;lt;td&amp;gt;
                                                &amp;lt;div className="d-flex justify-content-between align-items-center"&amp;gt;
                                                    &amp;lt;div className="btn-group" style={{ marginBottom: "20px" }}&amp;gt;
                                                        &amp;lt;Link to={`edit/${customer.id}`} className="btn btn-sm btn-outline-secondary"&amp;gt;Edit Customer &amp;lt;/Link&amp;gt;
                                                        &amp;lt;button className="btn btn-sm btn-outline-secondary" onClick={() =&amp;gt; this.deleteCustomer(customer.id)}&amp;gt;Delete Customer&amp;lt;/button&amp;gt;
                                                    &amp;lt;/div&amp;gt;
                                                &amp;lt;/div&amp;gt;
                                            &amp;lt;/td&amp;gt;
                                        &amp;lt;/tr&amp;gt;
                                    )}
                                &amp;lt;/tbody&amp;gt;
                            &amp;lt;/table&amp;gt;
                        &amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
            )
        }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this code block, you retrieve the lists of customers from the application's state as an array, iterate over it, and display it within an HTML table. You also add the &lt;code&gt;customer.id&lt;/code&gt; parameter, which the method uses to identify and delete the details of a particular customer from the list.&lt;/p&gt;

&lt;p&gt;Save and exit &lt;code&gt;Home.tsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You've adopted a statically typed principle for all the components created with this application by defining types for the components and props through the use of interfaces. This is one of the best approaches to using TypeScript for a React application.&lt;/p&gt;

&lt;p&gt;With this, you've finished creating all the required reusable components for the application. You can now update the app component with links to all the components that you have created so far.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Setting Up Routing and Updating the Entry Point of the Application
&lt;/h2&gt;

&lt;p&gt;In this step, you will import the necessary components from the React Router package and configure the &lt;code&gt;App&lt;/code&gt; component to render different components depending on the route that is loaded. This will allow you to navigate through different pages of the application. Once a user visits a route, for example &lt;code&gt;/create&lt;/code&gt;, React Router will use the path specified to render the contents and logic within the appropriate component defined to handle such route.&lt;/p&gt;

&lt;p&gt;Navigate to &lt;code&gt;./src/App.tsx&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano App.tsx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then replace its content with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    import * as React from 'react';
    import './App.css';
    import { Switch, Route, withRouter, RouteComponentProps, Link } from 'react-router-dom';
    import Home from './components/Home';
    import Create from './components/customer/Create';
    import EditCustomer from './components/customer/Edit';

    class App extends React.Component&amp;lt;RouteComponentProps&amp;lt;any&amp;gt;&amp;gt; {
      public render() {
        return (
          &amp;lt;div&amp;gt;
            &amp;lt;nav&amp;gt;
              &amp;lt;ul&amp;gt;
                &amp;lt;li&amp;gt;
                  &amp;lt;Link to={'/'}&amp;gt; Home &amp;lt;/Link&amp;gt;
                &amp;lt;/li&amp;gt;
                &amp;lt;li&amp;gt;
                  &amp;lt;Link to={'/create'}&amp;gt; Create Customer &amp;lt;/Link&amp;gt;
                &amp;lt;/li&amp;gt;
              &amp;lt;/ul&amp;gt;
            &amp;lt;/nav&amp;gt;
            &amp;lt;Switch&amp;gt;
              &amp;lt;Route path={'/'} exact component={Home} /&amp;gt;
              &amp;lt;Route path={'/create'} exact component={Create} /&amp;gt;
              &amp;lt;Route path={'/edit/:id'} exact component={EditCustomer} /&amp;gt;
            &amp;lt;/Switch&amp;gt;
          &amp;lt;/div&amp;gt;
        );
      }
    }
    export default withRouter(App);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You imported all the necessary components from the React Router package and you also imported the reusable components for creating, editing, and viewing customers' details.&lt;/p&gt;

&lt;p&gt;Save and exit &lt;code&gt;App.tsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;./src/index.tsx&lt;/code&gt; file is the entry point for this application and renders the application. Open this file and import React Router into it, then wrap the &lt;code&gt;App&lt;/code&gt; component inside a &lt;code&gt;BrowserRouter&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import { BrowserRouter } from 'react-router-dom'; 
    import * as serviceWorker from './serviceWorker';
    ReactDOM.render(
        &amp;lt;BrowserRouter&amp;gt;
            &amp;lt;App /&amp;gt;
        &amp;lt;/BrowserRouter&amp;gt;
        , document.getElementById('root')
    );
    serviceWorker.unregister();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;React Router uses the &lt;code&gt;BrowserRouter&lt;/code&gt; component to make your application aware of the navigation, such as history and current path.&lt;/p&gt;

&lt;p&gt;Once you've finished editing &lt;code&gt;Index.tsx&lt;/code&gt;, save and exit.&lt;/p&gt;

&lt;p&gt;Lastly, you will use Bootstrap to add some style to your application. &lt;a href="https://getbootstrap.com/"&gt;Bootstrap&lt;/a&gt; is a popular HTML, CSS, and JavaScript framework for developing responsive, mobile-first projects on the web. It allows developers to build an appealing user interface without having to write too much CSS. It comes with a responsive grid system that gives a web page a finished look that works on all devices.&lt;/p&gt;

&lt;p&gt;To include Bootstrap and styling for your application, replace the contents of &lt;code&gt;./src/App.css&lt;/code&gt; with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    @import 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css';

    .form-wrapper {
      width: 500px;
      margin: 0 auto;
    }
    .App {
      text-align: center;
      margin-top: 30px;
    }
    nav {
      width: 300px;
      margin: 0 auto;
      background: #282c34;
      height: 70px;
      line-height: 70px;
    }
    nav ul li {
      display: inline;
      list-style-type: none;
      text-align: center;
      padding: 30px;
    }
    nav ul li a {
      margin: 50px 0;
      font-weight: bold;
      color: white;
      text-decoration: none;
    }
    nav ul li a:hover {
      color: white;
      text-decoration: none;
    }
    table {
      margin-top: 50px;
    }
    .App-link {
      color: #61dafb;
    }
    @keyframes App-logo-spin {
      from {
        transform: rotate(0deg);
      }
      to {
        transform: rotate(360deg);
      }
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You have used Bootstrap here to enhance the look and feel of the application by giving it a default layout, styles, and color. You have also added some custom styles, particularly to the navigation bar.&lt;/p&gt;

&lt;p&gt;Save and exit &lt;code&gt;App.css&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this section, you have configured React Router to render the appropriate component depending on the route visited by the user and also added some styling to make the application more attractive to users. Next, you will test all the functionality implemented for the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 — Running Your Application
&lt;/h2&gt;

&lt;p&gt;Now that you have set up the frontend of this application with React and TypeScript by creating several reusable components, and also built a REST API with the &lt;code&gt;json-server&lt;/code&gt;, you can run your app.&lt;/p&gt;

&lt;p&gt;Navigate back to the project’s root folder:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ~/typescript-react-app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next run the following command to start your app:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Make sure your server is still running in the other terminal window. Otherwise, start it with: &lt;code&gt;yarn server&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;Navigate to &lt;code&gt;http://localhost:3000&lt;/code&gt; to view the application from your browser. Then proceed to click on the &lt;strong&gt;Create&lt;/strong&gt; button and fill in the details of a customer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pVf7Yxbp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://assets.digitalocean.com/articles/reacttypescript/step5a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pVf7Yxbp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://assets.digitalocean.com/articles/reacttypescript/step5a.png" alt="Create customer page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After entering the appropriate values in the input fields, click on the &lt;strong&gt;Create Customer&lt;/strong&gt; button to submit the form. The application will redirect you back to your homepage once you're done creating a new customer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eagmSno3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://assets.digitalocean.com/articles/reacttypescript/step5b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eagmSno3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://assets.digitalocean.com/articles/reacttypescript/step5b.png" alt="View customers page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the &lt;strong&gt;Edit Customer&lt;/strong&gt; button for any of the rows and you will be directed to the page that hosts the editing functionality for the corresponding customer on that row.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NbybWQZO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://assets.digitalocean.com/articles/reacttypescript/step5c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NbybWQZO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://assets.digitalocean.com/articles/reacttypescript/step5c.png" alt="Edit customer page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Edit the details of the customer and then click on &lt;strong&gt;Edit Customer&lt;/strong&gt; to update the customer’s details.&lt;/p&gt;

&lt;p&gt;You've run your application to ensure all the components are working. Using the different pages of your application, you've created and edited a customer entry.&lt;/p&gt;

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

&lt;p&gt;In this tutorial you built a customer list management app with &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt; and &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt;. The process in this tutorial is a deviation from using JavaScript as the conventional way of structuring and building applications with React. You've leveraged the benefits of using TypeScript to complete this front-end focused tutorial.&lt;/p&gt;

&lt;p&gt;To continue to develop this project, you can move your mock back-end server to a production-ready back-end technology like &lt;a href="https://expressjs.com/"&gt;Express&lt;/a&gt; or &lt;a href="https://nestjs.com/"&gt;Nest.js&lt;/a&gt;. Furthermore, you can extend what you have built in this tutorial by adding more features such as authentication and authorization with different tools like the &lt;a href="http://www.passportjs.org/"&gt;Passport.js&lt;/a&gt; authentication library.&lt;/p&gt;

&lt;p&gt;You can find the complete source code for the project &lt;a href="https://github.com/yemiwebby/typescript-react-customer-app"&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;a href="http://creativecommons.org/licenses/by-nc-sa/4.0/"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jgdiKbjy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" alt="CC 4.0 License"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This work is licensed under a &lt;a href="http://creativecommons.org/licenses/by-nc-sa/4.0/"&gt;Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Add reliable voice and video chat with Vue.js and CometChat</title>
      <dc:creator>Oluyemi</dc:creator>
      <pubDate>Tue, 28 May 2019 10:57:53 +0000</pubDate>
      <link>https://dev.to/yemiwebby/add-reliable-voice-and-video-chat-with-vue-js-and-cometchat-3nj7</link>
      <guid>https://dev.to/yemiwebby/add-reliable-voice-and-video-chat-with-vue-js-and-cometchat-3nj7</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ErBZZrh_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AJawH4le3YY__TZaojzQ-5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ErBZZrh_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AJawH4le3YY__TZaojzQ-5g.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Basic knowledge of JavaScript and Vue.js will help you get the best out of this tutorial. To make it easy for everyone to follow along, I will endeavor to break down any complex implementation. In addition, you will also need to ensure that you have Node runtime and npm installed on your computer. &lt;a href="https://nodejs.org/en/"&gt;Click here to install Node&lt;/a&gt; and follow &lt;a href="https://www.npmjs.com/"&gt;this link to install npm&lt;/a&gt; if otherwise.&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Irrespective of the size of your web application, a voice, and video chat feature is an addon that will not only allow your users to communicate in real time, have a face to face interaction or meeting without necessarily being in the same location or region but also improves the engagement and interactivity of your application. While the implementation of voice and video chat might sound so cool, trust me, you don’t want to build this from scratch. This is where an awesome tool like &lt;a href="http://cometchat.com"&gt;CometChat&lt;/a&gt; really shines.&lt;/p&gt;

&lt;p&gt;So rather than build a backend for your chat application from scratch, you can easily build the entire functionalities using CometChat API which will enable you to build communication features like voice and video chat in real-time.&lt;/p&gt;

&lt;p&gt;Together in this tutorial, we will build a voice and video chat application by leveraging on some of the awesome API made available by CometChat. You will be able to run this application on two separate windows(browser) locally and have the ability to make, receive and reject a call amongst other things after a successful implementation. Once we are done, you would have built an application similar to:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0JV0hy6E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AglUuoiih2E23ALMo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0JV0hy6E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AglUuoiih2E23ALMo.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This application will be built with Vue.js and CometChat Pro SDK. The complete source code for this tutorial can be found &lt;a href="https://github.com/yemiwebby/comet-voice-video"&gt;here on GitHub&lt;/a&gt;if you will prefer to head straight into the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;To begin, we will create and install a new Vue.js application using an awesome tool named &lt;a href="https://cli.vuejs.org/"&gt;Vue CLI&lt;/a&gt;. This is a standard tool created by the team at Vue.js to help and allow developers to quickly scaffold a new project without hassle. Run the following command from the terminal to install it globally on your computer:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g @vue/cli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once the installation is complete, proceed to use the vue command to create a new Vue.js project as shown here:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vue create comet-voice-video
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Choose the “manually select features” options by pressing Enter on your keyboard and check the features you will be needing for this project by pressing space on your computer to select one. As shown below you should select Babel, Router, and Linter / Formatter:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xLJYmPt4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AgrujiJcOFDvPc6dy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xLJYmPt4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AgrujiJcOFDvPc6dy.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For other instructions, type y to use history mode for the router. Ideally, the default mode for Vue-Router is hash(#) mode as it uses the URL hash to simulate a full URL so that page won’t be reloaded when the URL changes. Choosing history mode here will help to get rid of the hash mode in order to achieve URL navigation without a page reload and add this configuration to the router file that will be generated automatically for this project. In addition, select ESLint with error prevention only in order to pick a linter / formatter config. Next, select Lint on save for additional lint features and save your configuration in a dedicated config file for future projects. Type a name for your preset, I named mine vuecomet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ybg9ffE7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AiM9lvsjv0UBP9QhC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ybg9ffE7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AiM9lvsjv0UBP9QhC.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Immediately after the configuration, Vue CLI will start the installation of the application and install all its required dependencies in a new folder named comet-voice-video.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start the application
&lt;/h3&gt;

&lt;p&gt;Now that the installation of the new application is completed, move into the new project and start the development server with:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// move into the app
cd comet-voice-video

// start the server
npm run serve
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;View the welcome page of the application on &lt;a href="http://localhost:8080"&gt;http://localhost:8080&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mol0Mt-p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2Abex-CdcSp2bJ5LN2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mol0Mt-p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2Abex-CdcSp2bJ5LN2.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition, since we will be depending on CometChat Pro to easily build our application, let’s install the SDK before proceeding with the video chat implementation. Stop the development server from running by hitting CTRL + C on your machine and run the following command from the project directory:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @cometchat-pro/chat --save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we can easily import CometChat object wherever we want to use CometChat within our application like this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { CometChat } from '@cometchat-pro/chat';
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Create the CometChat Pro account, APP ID and API Key
&lt;/h3&gt;

&lt;p&gt;Since we will be leveraging on the hosted service of CometChat to successfully build our voice and video chat application, head over to the website &lt;a href="https://app.cometchat.com/#/register"&gt;here&lt;/a&gt; and &lt;strong&gt;create a free CometChat Pro account.&lt;/strong&gt; Fill in all the required information to set up a trial account.&lt;/p&gt;

&lt;p&gt;Log in to view your &lt;a href="https://app.cometchat.com/#/apps"&gt;CometChat dashboard&lt;/a&gt; and let’s create a new project. This will give us access to a unique APP ID and an API Key&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xamazMng--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AHBgWBArv_bUUJpee.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xamazMng--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AHBgWBArv_bUUJpee.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the ‘Add New App’ dialog, enter a name and click the plus sign to create a new application. Once you are done, click on the &lt;strong&gt;Explore&lt;/strong&gt; button for the new app created. You will be redirected to a new page as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Zxuzp54o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AXwk1hzMXu9aLLyuv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Zxuzp54o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AXwk1hzMXu9aLLyuv.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, from the left side menu, go to “API Keys” tab and you will see a page similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5uANaMvy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2A2Gvaxwp_shGxabor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5uANaMvy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2A2Gvaxwp_shGxabor.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Immediately after you created a new application from your dashboard, CometChat automatically generated an API Key for the new demo application for you. You don’t need to create a new one as this will suffice and give you full access to the functionality offered by CometChat. Don’t forget to note or better still, copy the automatically-generated Full access API Key and application ID as we will need these shortly.&lt;/p&gt;

&lt;p&gt;Now that we are done setting up all the necessary tools and credentials needed to successfully create our application, we will start building properly in a bit.&lt;/p&gt;

&lt;h3&gt;
  
  
  What we want to achieve
&lt;/h3&gt;

&lt;p&gt;Before we start building the application properly, let’s quickly discuss the application structure and how we intend to structure the flow.&lt;/p&gt;

&lt;p&gt;Basically, we want users to log in from different locations and be able to chat using voice and video once we host our application on a live server, but for the sake of this tutorial, we will use two different windows locally. Once the user logs in:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ts9E-tJ2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/688/0%2AkTt2X4O8Ie6HYNQx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ts9E-tJ2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/688/0%2AkTt2X4O8Ie6HYNQx.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;we will redirect to a different page where he or she can input the UID of another user and start a video chat. Each &lt;a href="https://prodocs.cometchat.com/docs/concepts#section-users"&gt;user&lt;/a&gt; of CometChat is uniquely identified using his or her UID, you can consider this or relate it with a typical unique primary ID of the user from your database, which gives an opportunity to identify such user:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vD6EoA2Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AuqXug55-16JgZuXy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vD6EoA2Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AuqXug55-16JgZuXy.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Initialize CometChat
&lt;/h3&gt;

&lt;p&gt;To begin, the typical workflow when using CometChat requires that the settings for CometChat must be initialized by calling the init() method before any other method from CometChat. To start, create a new file named .env within the root directory of the application and paste the following code in it:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// .env
VUE_APP_COMMETCHAT_API_KEY=YOUR_API_KEY

VUE_APP_COMMETCHAT_APP_ID=YOUR_APP_ID
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will make it very easy to reference and use our application credentials within our project. Don’t forget to replace &lt;code&gt;YOUR_API_KEY&lt;/code&gt; and &lt;code&gt;YOUR_APP_ID&lt;/code&gt; placeholder with the appropriate credentials as obtained from your CometChat dashboard.&lt;/p&gt;

&lt;p&gt;Next, navigate to ./src/App.vue file which is the root component for Vue.js applications and replace its content with:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ./src/App.vue

&amp;lt;template&amp;gt;
  &amp;lt;div id="app"&amp;gt;
    &amp;lt;router-view/&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;


&amp;lt;script&amp;gt;
import { CometChat } from "@cometchat-pro/chat";

import "./App.css";

export default {
  data() {
    return {};
  },
  created() {
    this.initializeApp();
  },
  methods: {
    initializeApp() {
      var appID = process.env.VUE_APP_COMMETCHAT_APP_ID;

      CometChat.init(appID).then(
        () =&amp;gt; {
          console.log("Initialization completed successfully");
        },
        error =&amp;gt; {
          console.log("Initialization failed with error:", error);
        }
      );
    }
  }
};
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What we have done here is to include the  functional component that will render any matched component for a given path from&lt;a href="https://router.vuejs.org/"&gt;Vue Router.&lt;/a&gt; We will configure the router later in this tutorial. Next, within the  section, we imported the CometChat object and a CSS file that we will create next. Lastly, we initialize CometChat by passing the application ID as a parameter.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Now create a new file named &amp;lt;code&amp;gt;App.css&amp;lt;/code&amp;gt; within &amp;lt;code&amp;gt;./src/App.css&amp;lt;/code&amp;gt; and paste the following content in it:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;// ./src/App.css

@import 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css';
@import 'https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css';

#app {
    font-family: "Avenir", Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
  }
  #nav {
    padding: 30px;
  }

  #nav a {
    font-weight: bold;
    color: #2c3e50;
  }

  #nav a.router-link-exact-active {
    color: #42b983;
  }

  #auth {
    width: 600px;
    margin: 0 auto;
  }

  #callScreen {
    width: 500px;
    height: 500px;
  }

  .home {
    width: 600px;
    margin: 0 auto;
  }
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;We imported the CDN files for &amp;lt;a href="https://getbootstrap.com/"&amp;gt;Bootstrap&amp;lt;/a&amp;gt; and &amp;lt;a href="https://fontawesome.com/"&amp;gt;Font awesome&amp;lt;/a&amp;gt; and then proceeded to add some default style for the application. Feel free to modify this content as you deem fit.&amp;lt;/p&amp;gt;
&amp;lt;h3&amp;gt;
  &amp;lt;a name="login-component" href="#login-component" class="anchor"&amp;gt;
  &amp;lt;/a&amp;gt;
  Login component
&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;One of the key concept when building chat applications with CometChat is to ensure that users are authenticated before they can have access to use CometChat and start a chat. To ensure this, we will create a Login component that will handle the logic for authenticating a user and redirecting such user to the appropriate page for a chat.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;To begin, create a new folder named auth within the views folder and within the newly created folder, create a new file and call it &amp;lt;code&amp;gt;Login.vue&amp;lt;/code&amp;gt;. Open this new file and paste the following contents:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;// ./src/views/auth/Login.vue

    &amp;amp;lt;template&amp;amp;gt;
        &amp;amp;lt;div id="auth"&amp;amp;gt;
            &amp;amp;lt;div id="nav"&amp;amp;gt;
              &amp;amp;lt;router-link to="/login"&amp;amp;gt;Login&amp;amp;lt;/router-link&amp;amp;gt; 
            &amp;amp;lt;/div&amp;amp;gt;

            &amp;amp;lt;p&amp;amp;gt; Enter your username to start video chat &amp;amp;lt;/p&amp;amp;gt;
            &amp;amp;lt;p&amp;amp;gt;Create an account through your CometChat dashboard or login with one of our test users (superhero1, superhero2)&amp;amp;lt;/p&amp;amp;gt;
            &amp;amp;lt;form v-on:submit.prevent="authLoginUser"&amp;amp;gt;
                &amp;amp;lt;div class="form-group"&amp;amp;gt;
                    &amp;amp;lt;input name="username" id="username" class="form-control" placeholder="Enter your username" v-model="username"/&amp;amp;gt;
                &amp;amp;lt;/div&amp;amp;gt;
                &amp;amp;lt;div class="form-group"&amp;amp;gt;
                    &amp;amp;lt;button type="submit" class="btn btn-success"&amp;amp;gt; Login &amp;amp;lt;span v-if="showSpinner" class="fa fa-spin fa-spinner"&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;&amp;amp;lt;/button&amp;amp;gt;
                &amp;amp;lt;/div&amp;amp;gt;
            &amp;amp;lt;/form&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;
    &amp;amp;lt;/template&amp;amp;gt;

    &amp;amp;lt;script&amp;amp;gt;
    import { CometChat } from "[@cometchat](http://twitter.com/cometchat)-pro/chat";
    export default {
      data() {
        return {
          username: "",
          showSpinner: false
        };
      },
      methods: {
        authLoginUser() {
          var apiKey = process.env.VUE_APP_COMMETCHAT_API_KEY;
          this.showSpinner = true;
          CometChat.login(this.username, apiKey).then(
            () =&amp;amp;gt; {
              this.showSpinner = false;
              this.$router.push({ name: "home" });
            },
            error =&amp;amp;gt; {
              this.showSpinner = false;
              console.log("Login failed with error:", error.code);
            }
          );
        }
      }
    };
    &amp;amp;lt;/script&amp;amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;What we have done here is pretty simple. First, we included an HTML form and added an input field that will accept the username of a user during the authentication process. Once the form is submitted, it will be processed using a method named authLoginUser().&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Next within the &amp;lt;script&amp;gt; tag, we imported the CometChat object and created the authLoginUser() method attached to the form. Within the authLoginUser() method, we called the login() method from CometChat and passed our application API and the username to uniquely identify the user.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Once the user logs into the application, we used the &amp;lt;a href="https://router.vuejs.org/"&amp;gt;Vue Router&amp;lt;/a&amp;gt; to redirect the user to the home page which will be handled by a different component name HomeComponent. We will create that in the next section.&amp;lt;/p&amp;gt;
&amp;lt;h3&amp;gt;
  &amp;lt;a name="home-component" href="#home-component" class="anchor"&amp;gt;
  &amp;lt;/a&amp;gt;
  Home component
&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;In chronological order, what we want to achieve with this component is:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Display the &amp;lt;strong&amp;gt;UID&amp;lt;/strong&amp;gt; of the currently logged in user&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Initiate a video chat&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Accept or reject a call&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;And finally, be able to log out of the application.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;Let’s start adding these functionalities. To begin, open &amp;lt;code&amp;gt;./src/views/Home.vue&amp;lt;/code&amp;gt; and replace its content with:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;// ./src/views/Home.vue

&amp;amp;lt;template&amp;amp;gt;
  &amp;amp;lt;div class="home"&amp;amp;gt;
     &amp;amp;lt;div id="nav"&amp;amp;gt;
       &amp;amp;lt;button class="btn btn-success" [@click](http://twitter.com/click)="logoutUser"&amp;amp;gt;Logout&amp;amp;lt;/button&amp;amp;gt; 
    &amp;amp;lt;/div&amp;amp;gt;
    &amp;amp;lt;div class="form-group"&amp;amp;gt;
      &amp;amp;lt;div class="form-group"&amp;amp;gt;
        &amp;amp;lt;p&amp;amp;gt;Welcome &amp;amp;lt;b&amp;amp;gt;{{ this.username}}&amp;amp;lt;/b&amp;amp;gt;, your UID is &amp;amp;lt;b&amp;amp;gt;{{ this.uid }}&amp;amp;lt;/b&amp;amp;gt; &amp;amp;lt;br&amp;amp;gt;
        Enter the receiver Id to start a chat &amp;amp;lt;/p&amp;amp;gt;
        &amp;amp;lt;p v-if="error"&amp;amp;gt;
          &amp;amp;lt;b class="text-danger"&amp;amp;gt; Receiver ID is required &amp;amp;lt;/b&amp;amp;gt;
        &amp;amp;lt;/p&amp;amp;gt;
        &amp;amp;lt;input type="text" class="form-control" placeholder="Enter receiver UID" v-model="receiver_id"&amp;amp;gt;
      &amp;amp;lt;/div&amp;amp;gt;

        &amp;amp;lt;div v-if="incomingCall"&amp;amp;gt;
          &amp;amp;lt;button class="btn btn-success" [@click](http://twitter.com/click)="acceptCall"&amp;amp;gt;Accept Call&amp;amp;lt;/button&amp;amp;gt;  
          &amp;amp;lt;button class="btn btn-success" [@click](http://twitter.com/click)="rejectCall"&amp;amp;gt;Reject Call&amp;amp;lt;/button&amp;amp;gt; 
        &amp;amp;lt;/div&amp;amp;gt;
        &amp;amp;lt;div v-else-if="ongoingCall"&amp;amp;gt;
          &amp;amp;lt;button class="btn btn-secondary"&amp;amp;gt; Ongoing Call ... &amp;amp;lt;/button&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;
        &amp;amp;lt;div v-else&amp;amp;gt;
          &amp;amp;lt;button [@click](http://twitter.com/click)="startVideoChat" class="btn btn-secondary"&amp;amp;gt; Start Call &amp;amp;lt;span v-if="showSpinner" class="fa fa-spin fa-spinner"&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt; &amp;amp;lt;/button&amp;amp;gt;
        &amp;amp;lt;/div&amp;amp;gt;
    &amp;amp;lt;/div&amp;amp;gt;
    &amp;amp;lt;div id="callScreen"&amp;amp;gt;&amp;amp;lt;/div&amp;amp;gt;
  &amp;amp;lt;/div&amp;amp;gt;
&amp;amp;lt;/template&amp;amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Here, we added contents to display the username and the UID of the logged in user. Next, we included an input field that will accept the UID of the receiver in order to uniquely identify such user and be able to initiate or send a call request.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Once a call request has been received, the receiver has an option of either rejecting or accepting the call. We have included click events for this process and will define the methods next.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Get the logged in user&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;First, let’s retrieve the details of the currently logged in user by adding this &amp;lt;script&amp;gt; section to our code. Place the contents below within the Home.vue immediately after the closing tag of the &amp;lt;template&amp;gt; section:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;// ./src/views/Home.vue

&amp;amp;lt;script&amp;amp;gt;
import { CometChat } from "[@cometchat](http://twitter.com/cometchat)-pro/chat";
export default {
  name: "home",
  data() {
    return {
      username: "",
      uid: "",
      session_id: "",
      receiver_id: null,
      error: false,
      showSpinner: false,
      incomingCall: false,
      ongoingCall: false
    };
  },
  created() {
    this.getLoggedInUser();
  },
  methods: {
    getLoggedInUser() {
      var user = CometChat.getLoggedinUser().then(
        user =&amp;amp;gt; {
          this.username = user.name;
          this.uid = user.uid;
        },
        error =&amp;amp;gt; {
          this.$router.push({ name: "homepage" });
        }
      );
    },
  }
};
&amp;amp;lt;/script&amp;amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Basically, we imported the CometChat method, defined some properties and corresponding initial values within the data option. And finally, once the component is created, we called a method named &amp;lt;code&amp;gt;getLoggedInUser()&amp;lt;/code&amp;gt; to automatically retrieve the details of a logged in user and update the view with it.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Start video chat&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;To initiate a chat from the app, we will add this method to the function associated with the Vue instance:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;// ./src/views/Home.vue

&amp;amp;lt;script&amp;amp;gt;
import { CometChat } from "[@cometchat](http://twitter.com/cometchat)-pro/chat";
export default {
...
  methods: {
    ...
   startVideoChat() {
      if (!this.receiver_id) this.error = true;
      this.showSpinner = true;
      var receiverID = this.receiver_id;
      var callType = CometChat.CALL_TYPE.VIDEO;
      var receiverType = CometChat.RECEIVER_TYPE.USER;
      var call = new CometChat.Call(receiverID, callType, receiverType);
      CometChat.initiateCall(call).then(
        outGoingCall =&amp;amp;gt; {
          this.showSpinner = false;
          console.log("Call initiated successfully:", outGoingCall);
          // perform action on success. Like show your calling screen.
        },
        error =&amp;amp;gt; {
          console.log("Call initialization failed with exception:", error);
        }
      );
    }
  }
};
&amp;amp;lt;/script&amp;amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;This method will be used to specify the type of call and that of a receiver. For our application, this will be a &amp;lt;code&amp;gt;CALL_TYPE.VIDEO&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RECEIVER_TYPE.USER&amp;lt;/code&amp;gt; respectively. Finally, we passed these details through an object of call into the &amp;lt;code&amp;gt;initiateCall()&amp;lt;/code&amp;gt; method from the CometChat API to send a call request.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Listen and receive calls&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Once a call has been initiated, we need to listen to the call events within our application and based on the actions that will be carried out by the user to either receive or reject the call, we will call the appropriate method. To do this successfully, we need to register the CallListener listener using the &amp;lt;code&amp;gt;addCallListener()&amp;lt;/code&amp;gt; method from CometChat. Add the following contents within the created() method:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;// ./src/views/Home.vue

&amp;amp;lt;script&amp;amp;gt;
import { CometChat } from "[@cometchat](http://twitter.com/cometchat)-pro/chat";
export default {
...
  created() {
  ...
  let globalContext = this;
    var listnerID = "UNIQUE_LISTENER_ID";
    CometChat.addCallListener(
      listnerID,
      new CometChat.CallListener({
        onIncomingCallReceived(call) {
          console.log("Incoming call:", call);
          globalContext.incomingCall = true;
          globalContext.session_id = call.sessionId;
        },
        onOutgoingCallAccepted(call) {
          console.log("Outgoing call accepted:", call);
          globalContext.ongoingCall = true;
          CometChat.startCall(
            call.sessionId,
            document.getElementById("callScreen"),
            new CometChat.OngoingCallListener({
              onUserJoined: user =&amp;amp;gt; {
                /* Notification received here if another user joins the call.*/
                console.log("User joined call:", user);
                /* this method can be use to display message or perform any actions if someone joining the call */
              },
              onUserLeft: user =&amp;amp;gt; {
                /* Notification received here if another user left the call.*/
                console.log("User left call:", user);
                /* this method can be use to display message or perform any actions if someone leaving the call*/
              },
              onCallEnded: call =&amp;amp;gt; {
                globalContext.ongoingCall = false;
                globalContext.incomingCall = false;
                /* Notification received here if current ongoing call is ended.*/
                console.log("Call ended:", call);
                /* hiding/closing the call screen can be done here.*/
              }
            })
          );
          // Outgoing Call Accepted
        },
        onOutgoingCallRejected(call) {
          console.log("Outgoing call rejected:", call);
          this.incomingCall = false;
          this.ongoingCall = false;
          this.receiver_id = "";
          // Outgoing Call Rejected
        },
        onIncomingCallCancelled(call) {
          console.log("Incoming call calcelled:", call);
        }
      })
    );
  },
  methods: {
    ...
  }
};
&amp;amp;lt;/script&amp;amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Once the recipient accepts an outgoing call in the &amp;lt;code&amp;gt;onOutgoingCallAccepted()&amp;lt;/code&amp;gt; callback of the CallListener, we called another method &amp;lt;code&amp;gt;startCall()&amp;lt;/code&amp;gt; which takes the&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;sessionId: The unique session ID available in the CometChat.Call object,&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;callScreen: DOM element where you want to show the call user interface and&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;OngoingCallListener: a CometChat.OngoingCallListener where the real-time events will be received&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;as parameters.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Accept and reject calls&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Once an incoming call event is received, we will call a method named &amp;lt;code&amp;gt;acceptCall()&amp;lt;/code&amp;gt;. This method also takes the unique session ID available in the CometChat.Call object as a parameter. Add this method immediately after the &amp;lt;code&amp;gt;startVideoChat()&amp;lt;/code&amp;gt; method:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;// ./src/views/Home.vue

&amp;amp;lt;script&amp;amp;gt;
import { CometChat } from "[@cometchat](http://twitter.com/cometchat)-pro/chat";
export default {
...
  methods: {
    ...
   acceptCall() {
      let globalContext = this;
      this.ongoingCall = true;
      this.incomingCall = false;
      var sessionID = this.session_id;
      CometChat.acceptCall(sessionID).then(
        call =&amp;amp;gt; {
          console.log("Call accepted successfully:", call);
          console.log("call accepted now....");
          // start the call using the startCall() method
          console.log(globalContext.ongoingCall);
          CometChat.startCall(
            call.sessionId,
            document.getElementById("callScreen"),
            new CometChat.OngoingCallListener({
              onUserJoined: user =&amp;amp;gt; {
                /* Notification received here if another user joins the call.*/
                console.log("User joined call:", user);
                /* this method can be use to display message or perform any actions if someone joining the call*/
              },
              onUserLeft: user =&amp;amp;gt; {
                /* Notification received here if another user left the call.*/
                console.log("User left call:", user);
                /* this method can be use to display message or perform any actions if someone leaving the call*/
              },
              onCallEnded: call =&amp;amp;gt; {
                /* Notification received here if current ongoing call is ended.*/
                console.log("Call ended:", call);
                globalContext.ongoingCall = false;
                globalContext.incomingCall = false;
                /* hiding/closing the call screen can be done here.*/
              }
            })
          );
        },
        error =&amp;amp;gt; {
          console.log("Call acceptance failed with error", error);
          // handle exception
        }
      );
    }
  }
};
&amp;amp;lt;/script&amp;amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Here, once an incoming call has been accepted, we then called the startCall() method. With this in place, the sender and the recipient can start a chat. Next, add another method to reject calls:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;// ./src/views/Home.vue

&amp;amp;lt;script&amp;amp;gt;
import { CometChat } from "[@cometchat](http://twitter.com/cometchat)-pro/chat";
export default {
...
  methods: {
    ...
    rejectCall() {
      var sessionID = this.session_id;
      var globalContext = this;
      var status = CometChat.CALL_STATUS.REJECTED;
      CometChat.rejectCall(sessionID, status).then(
        call =&amp;amp;gt; {
          console.log("Call rejected successfully", call);
          globalContext.incomingCall = false;
          globalContext.ongoingCall = false;
          globalContext.receiver_id = "";
        },
        error =&amp;amp;gt; {
          console.log("Call rejection failed with error:", error);
        }
      );
    }
  }
};
&amp;amp;lt;/script&amp;amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;And lastly, add another method to Log out users from the application and redirect back to the login page:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;// ./src/views/Home.vue

&amp;amp;lt;script&amp;amp;gt;
import { CometChat } from "[@cometchat](http://twitter.com/cometchat)-pro/chat";
export default {
...
  methods: {
    ...
    logoutUser() {
      CometChat.logout().then(
        success =&amp;amp;gt; {
          console.log("Logout completed successfully");
          this.$router.push({ name: "homepage" });
          console.log(success);
        },
        error =&amp;amp;gt; {
          //Logout failed with exception
          console.log("Logout failed with exception:", { error });
        }
      );
    } 
  }
};
&amp;amp;lt;/script&amp;amp;gt;
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The &amp;lt;code&amp;gt;CometChat.logout()&amp;lt;/code&amp;gt; will log the user out of CometChat and also from our application.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;In case you miss anything, the complete contents of the Home.vue file can be &amp;lt;a href="https://github.com/yemiwebby/comet-voice-video/blob/master/src/views/Home.vue"&amp;gt;found here&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;h3&amp;gt;
  &amp;lt;a name="update-router" href="#update-router" class="anchor"&amp;gt;
  &amp;lt;/a&amp;gt;
  Update router
&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;Earlier, when we installed Vue.js, we also selected an option of installing Vue Router with it. So open &amp;lt;code&amp;gt;./src/router.js&amp;lt;/code&amp;gt; and replace the default content in it with the following:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;div class="highlight"&amp;gt;&amp;lt;pre class="highlight plaintext"&amp;gt;&amp;lt;code&amp;gt;// ./src/router.js

import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import Login from './views/auth/Login.vue'
Vue.use(Router)
export default new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/',
      redirect: 'login',
      name: 'homepage'
    },
    {
      path: '/login',
      name: 'login',
      component: Login,
    },
    {
      path: '/home',
      name: 'home',
      component: Home
    }
  ]
})
&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;What we have done here is to map each route within our application to the respective component that will handle the logic. This is a basic format of configuring Vue Router for a Vue.js application. Click &amp;lt;a href="https://router.vuejs.org/"&amp;gt;here&amp;lt;/a&amp;gt; to find out more about Vue Router.&amp;lt;/p&amp;gt;
&amp;lt;h3&amp;gt;
  &amp;lt;a name="test-the-application" href="#test-the-application" class="anchor"&amp;gt;
  &amp;lt;/a&amp;gt;
  Test the application
&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;Now that you are done adding all the required logic and components, you can now run the application and test it out. Restart the application with npm run serve and navigate to &amp;lt;a href="http://localhost:8080"&amp;gt;http://localhost:8080&amp;lt;/a&amp;gt; to view the app.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img src="https://cdn-images-1.medium.com/max/688/0*qLJzgX9dJ-ZnIB5U.png" alt=""&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Open the application in two separate windows and login with any two of the test users: superhero1, superhero2, superhero3, superhero4 or superhero5&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img src="https://cdn-images-1.medium.com/max/600/0*h2sDQ5lxWHDxWN6p.gif" alt=""&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Once you are able to log in from both window, enter the UID of one user and click on &amp;lt;strong&amp;gt;Start Call&amp;lt;/strong&amp;gt; and once the call request is received by the other user, two new action buttons will be displayed. Click &amp;lt;strong&amp;gt;Accept Call&amp;lt;/strong&amp;gt; to accept a call&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img src="https://cdn-images-1.medium.com/max/600/0*JgKRdftJdW8sg0CR.gif" alt=""&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;or &amp;lt;strong&amp;gt;Reject Call&amp;lt;/strong&amp;gt; to reject a call:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;If you have followed the tutorial diligently up until now, then you should have a functional voice and video chat application running on your computer.&amp;lt;/p&amp;gt;
&amp;lt;h3&amp;gt;
  &amp;lt;a name="conclusion" href="#conclusion" class="anchor"&amp;gt;
  &amp;lt;/a&amp;gt;
  Conclusion
&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;As seen in this tutorial, you will agree with me that it is so easy to quickly implement a video chat feature in your project. This can be easily integrated into an existing Vue.js application or a new one entirely.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Feel free to explore the source code as linked at the beginning of this tutorial and add more features as you deem fit.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;With CometChat, you can easily extend the functionalities of this application by adding more awesome features. &amp;lt;a href="https://prodocs.cometchat.com/"&amp;gt;Check the official documentation of CometChat Pro&amp;lt;/a&amp;gt; to read more about what its got to offer.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I do hope you found this tutorial quite helpful? Can’t wait to see what you will build with the knowledge that you have acquired here.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Originally published on &amp;lt;a href="https://www.cometchat.com"&amp;gt;CometChat&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&lt;/p&gt;

</description>
      <category>vue</category>
      <category>vuerouter</category>
      <category>realtime</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Building a chat bot using Nest.js and Telegram</title>
      <dc:creator>Oluyemi</dc:creator>
      <pubDate>Mon, 14 May 2018 21:46:01 +0000</pubDate>
      <link>https://dev.to/yemiwebby/building-a-chat-bot-using-nestjs-and-telegram-4i2h</link>
      <guid>https://dev.to/yemiwebby/building-a-chat-bot-using-nestjs-and-telegram-4i2h</guid>
      <description>&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%2F4zvqjm0o9r5ut2sjorsf.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4zvqjm0o9r5ut2sjorsf.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In this tutorial, I will be showing you how to build a basic chat bot for Telegram using Nest.js. This will, amongst other things, give you an overview of how Telegram bots work and what you can do with them.&lt;/p&gt;

&lt;p&gt;Telegram bots are simply accounts that do not require an additional phone number to set up. Users can interact with them via commands: opening a chat directly or sending a request directly from a chat input field by typing bot’s @username.&lt;/p&gt;

&lt;h3&gt;
  
  
  What we’ll be building
&lt;/h3&gt;

&lt;p&gt;We’ll be building a telegram bot with a username new-nest-bot, you can choose your own preferred name when registering a new telegram bot.&lt;/p&gt;

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

&lt;p&gt;This bot was built to respond to text messages sent directly to it with predefined responses from the logic implemented on the back-end of the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;A basic understanding of TypeScript and Node.js will help you get the best out of this tutorial. I assume that you already have Node and npm installed, if otherwise quickly check &lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; and &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt; for further instructions and installation steps.&lt;/p&gt;

&lt;p&gt;In addition, a Telegram account is also required to have access to Telegram services, either to start a chat or create a bot. If you don’t have an account, I recommend using the &lt;a href="https://web.telegram.org/#/login" rel="noopener noreferrer"&gt;Telegram web client&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, here is a quick overview of the technologies that we will be using in this post.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nestjs.com/" rel="noopener noreferrer"&gt;Nest.js&lt;/a&gt;: a progressive framework for building efficient and scalable server-side applications; built to take the advantage of modern JavaScript but still preserves compatibility with pure JavaScript.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3d5tb7pdc9bp480jizva.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%2F3d5tb7pdc9bp480jizva.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/yagop/node-telegram-bot-api" rel="noopener noreferrer"&gt;Node-telegram-bot-api&lt;/a&gt;: a Node.js module to interact with the official &lt;a href="https://core.telegram.org/bots/api" rel="noopener noreferrer"&gt;Telegram Bot API&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setting up the project
&lt;/h3&gt;

&lt;p&gt;First, you need to install the &lt;a href="https://nestjs.com/" rel="noopener noreferrer"&gt;Nest.js&lt;/a&gt; starter project on &lt;a href="https://github.com/nestjs/typescript-starter" rel="noopener noreferrer"&gt;Github&lt;/a&gt; using Git. To do this, let’s run a command that will clone the starter repository into a new project folder named nest-telegram-chat-bot on your machine. Open your terminal or command prompt and run the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone https://github.com/nestjs/typescript-starter.git nest-telegram-chat-bot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go ahead and change directory into the newly created folder and install all the dependencies for the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// change directory
cd nest-telegram-chat-bot

// install dependencies
npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Installing server dependencies
&lt;/h3&gt;

&lt;p&gt;The only server dependency required for this application is the &lt;a href="https://github.com/yagop/node-telegram-bot-api" rel="noopener noreferrer"&gt;node-telegram-bot-api&lt;/a&gt;. Run the command below to install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm install --save node-telegram-bot-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating a Telegram bot
&lt;/h3&gt;

&lt;p&gt;We’ll basically be interacting with Telegram bot API. To do this, you will need to obtain an access token. Open a &lt;a href="https://web.telegram.org/" rel="noopener noreferrer"&gt;Telegram app&lt;/a&gt;, search for &lt;a class="mentioned-user" href="https://dev.to/botfather"&gt;@botfather&lt;/a&gt; and start the chat. Use the /newbot command to create a new bot. The BotFather will ask you a couple of questions, like the name and username, before an access token can be generated.&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%2Fil9df3f3picjz2praf7a.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%2Fil9df3f3picjz2praf7a.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow all the instructions and once you are done, a token that is required to send requests to Telegram Bot API will be generated for you. As shown below:&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%2F7j04cr5hyjruu3xudmzs.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7j04cr5hyjruu3xudmzs.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we have successfully created a bot, but it is passive at the moment as it has not been configured to respond to chat.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making request
&lt;/h3&gt;

&lt;p&gt;Open a new tab in your browser and test the new bot by making an HTTPS request to the Telegram Bot API using this URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.telegram.org/bot\&amp;lt;YOUR\_ACCESS\_TOKEN\&amp;gt;/getMe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return a response in JSON format with the id, name, and username of the bot.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"ok":true,"result":{"id":591836832,"is\_bot":true,"first\_name":"new-nest-bot","username":"nest\_demo\_bot"}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Initialize the application controller
&lt;/h3&gt;

&lt;p&gt;When a user interacts with our bot on Telegram, the &lt;a href="https://core.telegram.org/bots/api" rel="noopener noreferrer"&gt;Telegram Bot API&lt;/a&gt; sends details about the interaction to our Nest.js application over an HTTP request and a response will be sent back with instructions on how the bot should respond. Let’s configure our application logic.&lt;/p&gt;

&lt;p&gt;Nest.js starter project comes installed with a default controller named app.controller.ts. Open this file and update it with the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ./src/app.controller.ts

import { BotService } from './bot/bot.service';
import { Get, Controller, Res, HttpStatus } from '@nestjs/common';

@Controller()
 export class AppController {
 constructor( private botService:BotService) {}

 @Get()
 getBotDialog(@Res() res) {
 this.botService.botMessage();
 res.status(HttpStatus.OK).send("Bot service started");
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we start our application, this controller handles the incoming request and returns the appropriate response. As shown above, we imported BotService and injected it into the controller through the constructor. This is to ensure that app.controller.ts handles only the HTTP requests and abstracts the complex logic to a service. We’ll set this up in the next section&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure the bot service
&lt;/h3&gt;

&lt;p&gt;Our AppController depends on a service named BotService to respond to the interaction with our Telegram bot, based on a specified logic. Let’s create this service. Create a bot folder within the src and proceed to create a new file named bot.service.ts within it. Next, open the newly created file and paste the code below into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ./src/bot/bot.service.ts

import { Component} from '@nestjs/common';

@Component()
 export class BotService {

 botMessage() { 
 process.env.NTBA\_FIX\_319 = "1";
 const TelegramBot = require('node-telegram-bot-api');

const token = 'YOUR\_ACCESS\_TOKEN';

const bot = new TelegramBot(token, { polling: true });

 bot.on('message', (msg) =\&amp;gt; {
let Hi = "hi";
if (msg.text.toString().toLowerCase().indexOf(Hi) === 0) {
 bot.sendMessage(msg.from.id, "Hello " + msg.from.first\_name + " what would you like to know about me ?");
 }
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we created a method named botMessage() and within it, we required the node-telegram-bot-api module and then assigned the access_token received from BotFather to a token variable. This token was later used as an argument to create a new TelegramBot(). Notice the second argument passed to the new TelegramBot()? What we have done here is to create our bot with the &lt;a href="https://en.wikipedia.org/wiki/Push_technology#Long_polling" rel="noopener noreferrer"&gt;long polling&lt;/a&gt; configuration by setting it to true.&lt;/p&gt;

&lt;p&gt;It is worth mentioning that, you can actually interact with a server in two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://sendgrid.com/blog/whats-webhook/" rel="noopener noreferrer"&gt;Webhook&lt;/a&gt;: A dedicated URL or can also be referred to as a web callback.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Push_technology#Long_polling" rel="noopener noreferrer"&gt;Long Polling&lt;/a&gt;: This allows us to run our application locally without the need for a dedicated server or external address.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Register the component
&lt;/h3&gt;

&lt;p&gt;At the moment, our application doesn’t recognize the newly created service. Let’s change this by editing our module file app.module.ts. To do this, put the service into the ‘components’ array of the @Module() decorator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ./src/app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { BotService } from 'bot/bot.service';

@Module({
 imports: [],
 controllers: [AppController],
 components: [BotService],
})
export class AppModule {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running the application
&lt;/h3&gt;

&lt;p&gt;Start the application with :&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This will start the application on the default port used by Nest.js. Open your browser and navigate to &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7kcg0w2n42dfe33uu93r.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%2F7kcg0w2n42dfe33uu93r.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, open a &lt;a href="https://web.telegram.org/#/im" rel="noopener noreferrer"&gt;Telegram app&lt;/a&gt; and search for new-nest-bot or the name of your Telegram bot if you happen to choose a different name.&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%2F6fsuv87c8q4gtbhp5lij.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%2F6fsuv87c8q4gtbhp5lij.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, you can click on the start button to start a chat.&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%2Ff3wl06h2us15sri8tyuc.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%2Ff3wl06h2us15sri8tyuc.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;if you don’t get a response at the moment, don’t worry, just refresh the application if you have it open in a different tab.&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%2Fopo300612z2pz84vowif.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%2Fopo300612z2pz84vowif.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Update the service
&lt;/h3&gt;

&lt;p&gt;In order to avoid refreshing the page all the time, we will use a life-cycle event named OnModuleInit from Nest.js within our component to initialize the botMessage method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ./src/bot/bot.service.ts

import { Component, OnModuleInit } from '@nestjs/common';

@Component()
 export class BotService implements OnModuleInit {

 onModuleInit() {
 this.botMessage();
 }

 botMessage() { 
 ...
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart the development server if it is currently running, then proceed to try out the new-nest-bot&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%2Fv7sbzufmwmucfe3908hd.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%2Fv7sbzufmwmucfe3908hd.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the complete bot.service.ts file &lt;a href="https://github.com/yemiwebby/nest-telegram-chat-bot/blob/master/src/bot/bot.service.ts" rel="noopener noreferrer"&gt;here&lt;/a&gt; with the complete dialog on GitHub.&lt;/p&gt;

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

&lt;p&gt;Here, we have been able to build a telegram chatbot with a predefined response to chat from other users. The intention was to give you a general building block that can be improved and build amazing chatbot that can do much more.&lt;/p&gt;

&lt;p&gt;I hope this tutorial was helpful and gave you enough information required to start building bots tailored for other use cases, as you deem fit, in your organization.&lt;/p&gt;

&lt;p&gt;The source code for this tutorial can be found &lt;a href="https://github.com/yemiwebby/nest-telegram-chat-bot" rel="noopener noreferrer"&gt;here&lt;/a&gt; on Github. Feel free to explore.&lt;/p&gt;




</description>
      <category>nestjsandtelegram</category>
      <category>telegrambot</category>
      <category>buildingachatbot</category>
      <category>bots</category>
    </item>
    <item>
      <title>Bad Permissions writeable by group — Laravel</title>
      <dc:creator>Oluyemi</dc:creator>
      <pubDate>Tue, 03 Apr 2018 20:50:19 +0000</pubDate>
      <link>https://dev.to/yemiwebby/bad-permissions-writeable-by-group--laravel-fm5</link>
      <guid>https://dev.to/yemiwebby/bad-permissions-writeable-by-group--laravel-fm5</guid>
      <description>&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%2Fcdn-images-1.medium.com%2Fmax%2F844%2F1%2AgUG4hDtn-Qvi5nMDcnJmMQ.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%2Fcdn-images-1.medium.com%2Fmax%2F844%2F1%2AgUG4hDtn-Qvi5nMDcnJmMQ.jpeg"&gt;&lt;/a&gt;Internal Server Error&lt;/p&gt;

&lt;p&gt;If you have ever come across this error while deploying applications especially Laravel applications to shared hosting, then you just got for yourself the right post.&lt;/p&gt;

&lt;p&gt;So you just deployed your application to the server and instead of the contents being rendered, you were greeted with internal server error .&lt;/p&gt;

&lt;p&gt;A (500) Internal Server Error can be caused by many instances, including but not limited to invalid permissions, invalid ownership, errors in php.ini or .htaccess file, invalid requests in the script and others.&lt;/p&gt;

&lt;p&gt;Generally, this is not a problem with the server itself and can often be rectified by modifying something in your site’s configuration. The best approach is to check the Error logs in cPanel for the particular information.&lt;/p&gt;

&lt;p&gt;So if the error log says Directory is writeable by group:&lt;/p&gt;

&lt;p&gt;This is an indication that the folder had permissions for a folder set too high. To correct this, the permissions need to be changed from 777 to 755.&lt;/p&gt;

&lt;p&gt;Directories and folders should be 755. Executable scripts within the cgi-bin folder must be 755. Images, media, and text files like HTML should be 644.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Files — 644&lt;/li&gt;
&lt;li&gt;CGI Scripts — 755&lt;/li&gt;
&lt;li&gt;Directories — 755&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can modify permissions with the File Manager, located in the “Files” category of the cPanel, an FTP client, or using the &lt;strong&gt;chmod&lt;/strong&gt; command in SSH/Bash.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Final Note&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This error is not in anyway specific to Laravel Applications, I only used that as my title because I encounter this while uploading an application built with Laravel.&lt;/p&gt;

&lt;p&gt;I hope you found this post useful and if you have a different or other approach to resolving an issue like this, kindly share your thoughts and comments below.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>permission</category>
      <category>ftp</category>
    </item>
    <item>
      <title>Building Real-Time Web Applications Using Nest.js and Ably</title>
      <dc:creator>Oluyemi</dc:creator>
      <pubDate>Thu, 22 Mar 2018 15:36:59 +0000</pubDate>
      <link>https://dev.to/yemiwebby/building-real-time-web-applications-using-nestjs-and-ably-1i8e</link>
      <guid>https://dev.to/yemiwebby/building-real-time-web-applications-using-nestjs-and-ably-1i8e</guid>
      <description>&lt;p&gt;Realtime everywhere! If you are an ardent follower of the trends in the industry, especially the web development ecosystem, you will agree with me that a larger percentage of users appreciate realtime responses from web applications.&lt;/p&gt;

&lt;p&gt;This may be in the form of notifications, events, alerts, instant messaging or anything similar to these. Only a few platforms offer realtime technologies applicable for use in realtime digital experiences like Gaming and Gambling, Chat and Social, Data Content, Notifications and Alert and so on. This is where &lt;a href="https://www.ably.io/" rel="noopener noreferrer"&gt;Ably&lt;/a&gt; as a company shines.&lt;/p&gt;

&lt;p&gt;To explore the realtime technology, I have always wanted to try out &lt;a href="https://www.ably.io/" rel="noopener noreferrer"&gt;Ably&lt;/a&gt; and after reading this &lt;a href="https://blog.ably.io/news-flash-ably-is-no-longer-a-pub-sub-messaging-platform-long-live-pub-sub-ee767f29d71a" rel="noopener noreferrer"&gt;post&lt;/a&gt; I had to get down to work. So when I finally got the chance, I was able to explore the awesomeness of realtime functionality as offered by &lt;a href="https://www.ably.io/" rel="noopener noreferrer"&gt;Ably&lt;/a&gt; by building the following application:&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%2Fo8xuq6zcrwclmous28rs.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8xuq6zcrwclmous28rs.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a realtime opinion poll built with Nest.js and powered by &lt;a href="https://www.ably.io/" rel="noopener noreferrer"&gt;Ably&lt;/a&gt;. In this article, I am going to document the stage by stage process of how I was able to build the demo shown above.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pre-requisites
&lt;/h3&gt;

&lt;p&gt;To get the most out of this tutorial, a basic understanding of TypeScript and Node.js is advised.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tools
&lt;/h3&gt;

&lt;p&gt;we will use the following tools to build this app :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nestjs.com/" rel="noopener noreferrer"&gt;Nest.js&lt;/a&gt; : A progressive Node.js framework for building efficient and scalable server-side applications. It leverages on TypeScript to create reliable and well structured server-side application. If you are quite conversant with Angular, Nest.js gives you similar experience of building an Angular app, but on the backend. Despite using modern JavaScript (Typescript), it’s quite compatible with vanilla JavaScript which makes it very easy to get started with. You can read more about it &lt;a href="https://docs.nestjs.com/" rel="noopener noreferrer"&gt;here&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxqflrmh7sdum3snrnto9.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%2Fxqflrmh7sdum3snrnto9.png"&gt;&lt;/a&gt;Nest.js&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ably : An excellent realtime messaging platform that makes it easy to add realtime functionality to applications.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft10v2lqntrcks8yyic02.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%2Ft10v2lqntrcks8yyic02.png"&gt;&lt;/a&gt;Ably Realtime&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Axios : A promise-based HTTP client that works both in the browser and in a node.js environment.&lt;/li&gt;
&lt;li&gt;CanvasJS: A responsive HTML5 Charting library for data visualisation.&lt;/li&gt;
&lt;li&gt;Lastly, we will also need to install few modules using npm&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setting up the Application
&lt;/h3&gt;

&lt;p&gt;Its super easy to setup a new application using Nest.js, but before we proceed, it is assumed that you already have node and npm installed. If not, kindly check the &lt;a href="https://nodejs.org/en/download/" rel="noopener noreferrer"&gt;node.js&lt;/a&gt; and &lt;a href="https://www.npmjs.com/get-npm" rel="noopener noreferrer"&gt;npm&lt;/a&gt; websites for installation steps.&lt;/p&gt;

&lt;p&gt;To begin, use the commands below to clone a new starter repository, change directory into the newly created project folder and finally install all the required dependencies for Nest.js application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone https://github.com/nestjs/typescript-starter.git ably-nest-poll

$ cd ably-nest-poll

$ npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run the Application
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;This will start the application on the default port used by Nest.js (3000). Head over to &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp8tg3tk8ookhnctzc94n.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%2Fp8tg3tk8ookhnctzc94n.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Ably Account Setup
&lt;/h3&gt;

&lt;p&gt;If you don’t already have an ably account, head over to &lt;a href="https://www.ably.io/" rel="noopener noreferrer"&gt;their website&lt;/a&gt; and create one.&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%2Fl7vwpfm629fgn0dr59oi.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%2Fl7vwpfm629fgn0dr59oi.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow the remaining process and once you are done, you should have a free account with a private key. You will see an ‘API key’ on your account dashboard, this is of importance to us as we’ll use it later in the tutorial to connect to &lt;a href="https://www.ably.io/" rel="noopener noreferrer"&gt;Ably&lt;/a&gt; using the Basic Authentication scheme.&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%2F417kwfa4w9kuprsvdobl.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%2F417kwfa4w9kuprsvdobl.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will see that by default, &lt;a href="https://www.ably.io/" rel="noopener noreferrer"&gt;Ably&lt;/a&gt; creates an app for you which you can readily start using. However, you can also create a new application and configure it according to your needs.&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%2Fogg9bwyg5pduj1j9ub2r.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%2Fogg9bwyg5pduj1j9ub2r.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have named mine 'ably-nest-poll' . Feel free to choose any name that suits your purpose.&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%2F7pqb42ay3stssujupyxi.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%2F7pqb42ay3stssujupyxi.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependencies
&lt;/h3&gt;

&lt;p&gt;Use the &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;Node Package Manager&lt;/a&gt; to install dependencies for the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install ejs ably --save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bootstrap application
&lt;/h3&gt;

&lt;p&gt;One of the core files in Nest.js is 'main.ts’ This file contains the necessary functions with the responsibility of bootstrapping our application. Nest favours the popular MVC pattern and therefore allows the usage of template engine. Open '.src/main.ts’ and fill with :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**import** { NestFactory } **from**'@nestjs/core'; **import** { ApplicationModule } **from**'./app.module';

**//** import express module **import** \* **as** express **from**'express';

// path **import** \* **as** path **from**'path'; **async function** bootstrap() { **const** app = **await** NestFactory.create(ApplicationModule); // A public folder to serve static files **app**.use(express.static(path.join(\_\_dirname, 'public')));

**app**.set('views', \_\_dirname + '/views');

// set ejs as the view engine **app**.set('view engine', 'ejs'); **await** app.listen(3000); } bootstrap();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only addition I have made to the default configuration of this file is to import Express module, path and finally set &lt;a href="http://ejs.co/" rel="noopener noreferrer"&gt;ejs&lt;/a&gt; as the view engine for the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set Up the View
&lt;/h3&gt;

&lt;p&gt;In order to render the HTML output and display the application to users, we will create a folder called views within the src folder. Now, within this newly created folder, create a new file and name it index.ejs&lt;/p&gt;

&lt;p&gt;Then add the following code to your 'index.ejs' file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\&amp;lt;!DOCTYPE html\&amp;gt; \&amp;lt;html lang="en"\&amp;gt; \&amp;lt;head\&amp;gt; \&amp;lt;meta charset="UTF-8"\&amp;gt; \&amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"\&amp;gt; \&amp;lt;meta http-equiv="X-UA-Compatible" content="ie=edge"\&amp;gt; \&amp;lt;link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css"\&amp;gt; \&amp;lt;title\&amp;gt;Realtime Poll\&amp;lt;/title\&amp;gt; \&amp;lt;/head\&amp;gt; \&amp;lt;body\&amp;gt; \&amp;lt;div class="container"\&amp;gt; \&amp;lt;h1\&amp;gt; Marvel Movies \&amp;lt;/h1\&amp;gt; \&amp;lt;p\&amp;gt; Select your favorite Marvel Movie \&amp;lt;/p\&amp;gt; \&amp;lt;form id="opinion-form"\&amp;gt; \&amp;lt;p\&amp;gt; \&amp;lt;input type="radio" name="movie" id="avengers" value="The Avengers"\&amp;gt; \&amp;lt;label for="avengers"\&amp;gt;The Avengers\&amp;lt;/label\&amp;gt; \&amp;lt;/p\&amp;gt; \&amp;lt;p\&amp;gt; \&amp;lt;input type="radio" name="movie" id="black-panther" value="Black Panther"\&amp;gt; \&amp;lt;label for="black-panther"\&amp;gt;Black Panther\&amp;lt;/label\&amp;gt; \&amp;lt;/p\&amp;gt; \&amp;lt;p\&amp;gt; \&amp;lt;input type="radio" name="movie" id="captain-america" value="Captain America"\&amp;gt; \&amp;lt;label for="captain-america"\&amp;gt;Captain America\&amp;lt;/label\&amp;gt; \&amp;lt;/p\&amp;gt; \&amp;lt;p\&amp;gt; \&amp;lt;input type="radio" name="movie" id="other" value="Other"\&amp;gt; \&amp;lt;label for="other"\&amp;gt;Something Else \&amp;lt;/label\&amp;gt; \&amp;lt;/p\&amp;gt; \&amp;lt;input type="submit" value="Vote" class="btn btn-success"/\&amp;gt; \&amp;lt;/form\&amp;gt; \&amp;lt;br\&amp;gt;\&amp;lt;br\&amp;gt; \&amp;lt;div id="chart-container" style="height:300px;width:100%;"\&amp;gt; \&amp;lt;/div\&amp;gt; \&amp;lt;/div\&amp;gt; \&amp;lt;script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"\&amp;gt;\&amp;lt;/script\&amp;gt; \&amp;lt;script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"\&amp;gt;\&amp;lt;/script\&amp;gt; \&amp;lt;script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.1/axios.js"\&amp;gt;\&amp;lt;/script\&amp;gt; \&amp;lt;script src="http://cdn.ably.io/lib/ably.min-1.0.js"\&amp;gt;\&amp;lt;/script\&amp;gt; \&amp;lt;script src="https://cdnjs.cloudflare.com/ajax/libs/canvasjs/1.7.0/canvasjs.min.js"\&amp;gt;\&amp;lt;/script\&amp;gt; \&amp;lt;script src="/main.js"\&amp;gt;\&amp;lt;/script\&amp;gt; \&amp;lt;/body\&amp;gt; \&amp;lt;/html\&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will serve as the homepage for our realtime poll application. In order to make this page look presentable, I included a CDN file each for Materialize, Ably, CanvasJS and JQuery. Further, I’ve included a form with radio-button input fields and finally linked a custom script named main.js that we’ll visit later on in this tutorial.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling Route
&lt;/h3&gt;

&lt;p&gt;Route is handled within Nest.js by the controller layer. This receives the incoming requests and returns a response to the client. Nest uses a Controller metadata '@Controller' to map routes to a specific controller. For now, we will make use of the default controller to set up the homepage for our demo app. So edit '.src/app.controller.ts' and add the code shown below :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**import** { Get, Controller, Res } **from**'@nestjs/common'; @Controller() **export class** AppController { @Get() root(@Res() res) { res.render('index'); } }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code lets us manipulate the response by injecting the response object using the @Res() decorator. This will ensure that Nest maps every '/' route to the 'index.ejs' file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Controller
&lt;/h3&gt;

&lt;p&gt;The next thing we need to build is the controller for poll. This will handle every request once a user selects a choice and submit votes. So go ahead and create a new folder named &lt;strong&gt;poll&lt;/strong&gt; in your 'src' folder and then create a file 'poll.controller.ts' within it. Paste the following code in the newly created file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**import** { Controller, Post, Res, Body } **from**'@nestjs/common';

// import pollService **import** { PollService } **from**'./poll.service'; @Controller('poll') **export class** PollController {

// inject service **constructor** ( **private** pollService: PollService) {} @Post() submitVote(@Res() res, @Body() poll: **string** ) { **this**.pollService.create(poll); res.render('index'); } }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A quick peek into the code above, you will realize that we imported a service and injected it into the controller through the constructor, this is recommended by Nest in order to ensure controllers handles only HTTP requests. This service will perform a task of publishing payload to &lt;a href="https://www.ably.io/" rel="noopener noreferrer"&gt;Ably&lt;/a&gt;. We will create this service PollService in a bit.&lt;/p&gt;

&lt;p&gt;In addition, the &lt;strong&gt;@Controller(‘poll’)&lt;/strong&gt; tells the framework that we expect this controller to respond to requests posted to *&lt;em&gt;/poll *&lt;/em&gt; route.&lt;/p&gt;

&lt;h3&gt;
  
  
  Realtime Service
&lt;/h3&gt;

&lt;p&gt;Basically, we want to utilize one of the core functionalities of &lt;a href="https://www.ably.io/" rel="noopener noreferrer"&gt;Ably&lt;/a&gt;, which is publishing messages or payload to &lt;a href="https://www.ably.io/" rel="noopener noreferrer"&gt;Ably&lt;/a&gt; and ensure that every connected client or device on that channel receives them in realtime by means of subscription. This is where &lt;a href="https://www.ably.io/" rel="noopener noreferrer"&gt;Ably&lt;/a&gt; really shines; you get to focus on building apps and allow the platform to use their internal infrastructure to manage communication without you having to worry about it&lt;/p&gt;

&lt;p&gt;Lets create a component as a service within Nest.js . This will be used to publish a payload to &lt;a href="https://www.ably.io/" rel="noopener noreferrer"&gt;Ably&lt;/a&gt; on a specified channel.&lt;/p&gt;

&lt;p&gt;Controllers in Nest.js only handle HTTP requests and delegate complex tasks to components. Components here are plain TypeScript classes with @Component decorator. So create a new file within &lt;strong&gt;poll&lt;/strong&gt; folder named poll.service.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**import** { Component } **from**'@nestjs/common'; @Component() **export class** PollService { **private** poll: **string** ; create(poll) { **const** Ably = require('ably');

// replace with your API Key **var** ably = **new** Ably.Realtime('YOUR\_KEY');

**var** channel = ably.channels.get('ably-nest'); **const** data = { points: 1, movie: poll.movie }; channel.publish('vote', data); } }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, I required the ably module that was installed earlier and passed in the required API key. Also, I created a unique channel ably-nest for clients to subscribe to. I also have the publish method which takes in two parameters, one is an optional message event name and the other is a payload to be published.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connecting the dots
&lt;/h3&gt;

&lt;p&gt;At the moment, our application doesn’t recognise any newly created controller and service. We need to change this by editing our module file 'app.module.ts' and put controller into the 'controller' array and service into 'components' array of the '@Module() decorator respectively.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**import** { PollController } **from**'./poll/poll.controller'; **import** { Module } **from**'@nestjs/common'; **import** { AppController } **from**'./app.controller'; **import** { PollService } **from**'./poll/poll.service'; @Module({ imports: [], controllers: [AppController, PollController], components: [PollService], }) **export class** ApplicationModule {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Plug in Ably client-side and update UI
&lt;/h3&gt;

&lt;p&gt;Just a quick recap before the final stage. So far, in this tutorial, we have&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Created a form with radio buttons for users to cast and submit polls.&lt;/li&gt;
&lt;li&gt;We went further to create an account on &lt;a href="https://www.ably.io/" rel="noopener noreferrer"&gt;Ably&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Set up an homepage&lt;/li&gt;
&lt;li&gt;Created a controller to handle post route.&lt;/li&gt;
&lt;li&gt;Setup a service to publish payloads to a named channel ably-nest on &lt;a href="https://www.ably.io/" rel="noopener noreferrer"&gt;Ably&lt;/a&gt; and&lt;/li&gt;
&lt;li&gt;Lastly, we registered the newly created controller and service within our application module.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember that we included a custom 'main.js' file in our index.ejs file? Go ahead a create a new folder called public within the src folder then create the main.js file within it. Further, add the following code to the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**const** form = document.getElementById('opinion-form'); // form submit event form.addEventListener('submit', (e) =\&amp;gt; { **const** choice = document.querySelector('input[name=movie]:checked').value; **const** data = {movie: choice}; axios.post('/poll', data).then( (data) =\&amp;gt; { console.log(data); }); e.preventDefault(); }); let dataPoints = [{label: 'The Avengers', y: 0}, {label: 'Black Panther', y: 0}, {label: 'Captain America', y: 0}, {label: 'Other', y: 0},]; **const** chartContainer = document.querySelector('#chart-container'); **if** (chartContainer) { **const** chart = **new** CanvasJS.Chart('chart-container', { animationEnabled: **true** , theme: 'theme1', title: { text: 'Favorite Movies' }, data: [{ type: 'column', dataPoints: dataPoints }] }); chart.render(); **var** ably = **new** Ably.Realtime('YOUR\_KEY'); **var** channel = ably.channels.get('ably-nest'); channel.subscribe('vote', **function** (poll) { dataPoints = dataPoints.map(x =\&amp;gt; { **if** (x.label == poll.data.movie) { x.y += poll.data.points; **return** x; } **else** { **return** x; } }); chart.render(); }); }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This content of this file is self explanatory, we handle form submission and post to the poll route using  &lt;strong&gt;axios&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We also set a default dataPoints for our chart and finally subscribe to the payload posted from the server.&lt;/p&gt;

&lt;p&gt;Don’t forget to replace the YOUR_KEY with the appropriate API KEY from your dashboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bringing it all together
&lt;/h3&gt;

&lt;p&gt;Restart the development server again if it is currently running and navigate to &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; or &lt;a href="http://127.0.0.1:3000" rel="noopener noreferrer"&gt;http://127.0.0.1:3000&lt;/a&gt; to check it out.&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%2F7fqipze1uyvzi6zef0dc.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7fqipze1uyvzi6zef0dc.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that is it.&lt;/p&gt;

&lt;p&gt;If you miss any of the steps, you can find the code for this demo &lt;a href="https://github.com/yemiwebby/ably-nest-poll" rel="noopener noreferrer"&gt;here&lt;/a&gt; on github&lt;/p&gt;

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

&lt;p&gt;We have successfully achieved two things in this tutorial:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get introduced to building web applications using Nest.js&lt;/li&gt;
&lt;li&gt;Explore the realtime functionality offered by &lt;a href="https://www.ably.io/" rel="noopener noreferrer"&gt;Ably&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you would like to find out more about how channels, publishing and subscribing works, see the &lt;a href="https://www.ably.io/documentation/realtime/channels-messages" rel="noopener noreferrer"&gt;Realtime channels &amp;amp; messages documentation&lt;/a&gt; or better still learn more about the complete set of &lt;a href="https://www.ably.io/features" rel="noopener noreferrer"&gt;Ably features&lt;/a&gt;.&lt;/p&gt;




</description>
      <category>webapplications</category>
      <category>realtime</category>
      <category>javascript</category>
    </item>
    <item>
      <title>2017 In Review: Journey to greatness</title>
      <dc:creator>Oluyemi</dc:creator>
      <pubDate>Sun, 31 Dec 2017 20:15:47 +0000</pubDate>
      <link>https://dev.to/yemiwebby/2017-in-review-journey-to-greatness-42ep</link>
      <guid>https://dev.to/yemiwebby/2017-in-review-journey-to-greatness-42ep</guid>
      <description>

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2gi-hpZr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AcUzL9KagWS4iveaNHmb3Wg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2gi-hpZr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AcUzL9KagWS4iveaNHmb3Wg.jpeg" alt=""&gt;&lt;/a&gt;ForLoop Meet-up held at switch.ng&lt;/p&gt;

&lt;p&gt;Personally, its been an amazing year for me, major reason why this review was aptly titled “ &lt;strong&gt;Journey to greatness&lt;/strong&gt; ”. Reminiscing on some of the mind blowing events and memories from this year and I thought it fit to write about it. As this might inspire someone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Community Involvement
&lt;/h3&gt;

&lt;p&gt;I was more active in the Tech community this year than I have ever been. This has not only inspire me to keep learning but also offered me an opportunity of meeting lot of experienced developers. I literarily attended all kind of meetups and met the likes of &lt;a href="https://medium.com/u/8fc90bb17acf"&gt;Christian Nwamba&lt;/a&gt; (who has been a super duper mentor and a good friend till date), &lt;a href="https://medium.com/u/9e13edbcb55f"&gt;Prosper Otemuyiwa&lt;/a&gt;, &lt;a href="https://medium.com/u/e5c31749bfaa"&gt;Chuks El-Gran Opia&lt;/a&gt;, &lt;a href="https://medium.com/u/189f2e01cb0b"&gt;Chuloo&lt;/a&gt;, &lt;a href="https://medium.com/u/dd9f2ed9f7b6"&gt;Elijah Valentine Troy Abako&lt;/a&gt;, &lt;a href="https://medium.com/u/c95f1478f80d"&gt;Neo Ighodaro&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5RSTEUeN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A8gyU_qghVIbVuNDi2mx0ig.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5RSTEUeN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A8gyU_qghVIbVuNDi2mx0ig.jpeg" alt=""&gt;&lt;/a&gt;Angular Nigeria Meetup&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fItpppST--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AAb3_M5Cd82R1B53yGZRr6A.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fItpppST--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AAb3_M5Cd82R1B53yGZRr6A.jpeg" alt=""&gt;&lt;/a&gt;Laravel Nigeria Meetup&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pDtUOvaB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ALNJaw3uN9HtMKjle8nyzpA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pDtUOvaB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ALNJaw3uN9HtMKjle8nyzpA.jpeg" alt=""&gt;&lt;/a&gt;Frontstack Meetup&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing
&lt;/h3&gt;

&lt;p&gt;This is one of the main highlights of the year for me. Inspired by &lt;a href="https://medium.com/u/8fc90bb17acf"&gt;Christian Nwamba&lt;/a&gt;, &lt;a href="https://medium.com/u/9e13edbcb55f"&gt;Prosper Otemuyiwa&lt;/a&gt; and &lt;a href="https://medium.com/u/3197a2cc5a44"&gt;Chris Sevilleja&lt;/a&gt;, I ventured into the world of technical writing.&lt;/p&gt;

&lt;p&gt;I applied to become an author on one of the platforms that I have learnt a lot from (i.e &lt;a href="https://scotch.io/"&gt;scotch.io&lt;/a&gt;). I was super excited when my account was approved for author status.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EJgRvN5A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A2Bn7eubBG9arDgtM9Cmbcw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EJgRvN5A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A2Bn7eubBG9arDgtM9Cmbcw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Despite the fact that I worked for a company, before the end of the year, I was able to come up with 3 published article and few others still under review :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://scotch.io/tutorials/understanding-and-using-laravel-eloquent-macros"&gt;Understanding and Using Laravel Eloquent Macros&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://scotch.io/bar-talk/automate-tasks-by-creating-custom-artisan-command-in-laravel"&gt;Automate Tasks by Creating Custom Artisan command in Laravel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://scotch.io/tutorials/a-zero-configuration-module-bundler-meet-parcel"&gt;A Zero Configuration Module Bundler -- Meet Parcel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To crown it up, I emerged one of the top authors for the month of december&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uMabcmZM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AFUo4IGcTruZymqhkOkFhuA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uMabcmZM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AFUo4IGcTruZymqhkOkFhuA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Other Articles
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/yemiwebby/build-a-quote-application-using-laravel-and-vue-part-1-3apg"&gt;Build a Quote Application Using Laravel and Vue: Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yemiwebby/handling-ajax-request-in-vue-applications-using-axios-3baj-temp-slug-8301770"&gt;Handling Ajax Request in Vue Applications Using Axios.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/yemiwebby/send-sms-from-laravel-application-k4l-temp-slug-5219740"&gt;Send SMS From Laravel Application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@yemiwebby/replace-some-characters-with-asterisks-in-php-using-str-repeat-2c78b3899bad"&gt;Replace some characters with Asterisks in PHP using str_repeat().&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This has really helped mould me into becoming a better software developer, code writer, including my ability to share knowledge and contribute my quota towards the progress of other developers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Projects and Work
&lt;/h3&gt;

&lt;p&gt;Started working for a different company called &lt;a href="http://taxtech.com.ng/"&gt;Taxaide Technologies&lt;/a&gt; this year. Its amazing and a great opportunity to contribute and learn when you work with a company whose vision resonate with yours.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IK4upJ4Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/608/1%2AmNmv2sSGEYB_zTWVY83vUQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IK4upJ4Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/608/1%2AmNmv2sSGEYB_zTWVY83vUQ.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Taxaide Technologies Limited (TaxTech) was conceived to develop and deploy easy to use technology in the management of taxes, whether by the tax payer, the tax collector or the tax professional.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iDf2IJg_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AgsQez-W1mC0UjDuTqBTi_g.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iDf2IJg_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AgsQez-W1mC0UjDuTqBTi_g.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was appointed a position where I had to maintain few existing web applications and also build new ones. Thank you Taxtech.&lt;/p&gt;

&lt;h3&gt;
  
  
  Open Source Projects
&lt;/h3&gt;

&lt;p&gt;Contributed to few open source projects this year&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vIE6pkqd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/314/1%2AagRJbtHA-KiqeodEqKNzkQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vIE6pkqd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/314/1%2AagRJbtHA-KiqeodEqKNzkQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8aaUJ2Or--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/745/1%2AmoELu5tT7kWI7UBFjYCARQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8aaUJ2Or--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/745/1%2AmoELu5tT7kWI7UBFjYCARQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Won an Hackathon (Angular Nigeria)
&lt;/h3&gt;

&lt;p&gt;I successfully led a team of programmers and we won the very first Angular Nigeria Hackathon sometimes in May this year.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://startupsventurecapital.com/how-my-team-won-the-first-angular-nigeria-hackathon-eee9b9f468a7"&gt;How My Team Won The First Angular Nigeria Hackathon&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iv85Phey--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A2otDCVj2HTbYOaVoVKpD9g.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iv85Phey--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A2otDCVj2HTbYOaVoVKpD9g.jpeg" alt=""&gt;&lt;/a&gt;Team Hack Brad Green&lt;/p&gt;

&lt;h3&gt;
  
  
  On Speaking
&lt;/h3&gt;

&lt;p&gt;I was opportuned to visit students of Federal College of Education(Technical) Akoka and got them fired up to explore the world of programming. Despite busy schedules at work, I am excited that I made this happen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8X038psj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AwI0yxTh_pFwQ2EM36x87bg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8X038psj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AwI0yxTh_pFwQ2EM36x87bg.jpeg" alt=""&gt;&lt;/a&gt;Speaking at FCE Akoka&lt;/p&gt;

&lt;h3&gt;
  
  
  Life
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Read a lot of technical Articles this year.&lt;/li&gt;
&lt;li&gt;I met a lot of amazing people this year both techies and non techies 😄. &lt;a href="https://medium.com/u/8fc90bb17acf"&gt;Christian Nwamba&lt;/a&gt; such an amazing guy, &lt;a href="https://medium.com/u/4c4c1f1f15fb"&gt;Fidelia Unifoh&lt;/a&gt;, &lt;a href="https://medium.com/u/c7d49b710a18"&gt;Bidemi Daniel Olumide&lt;/a&gt;, &lt;a href="https://medium.com/u/be20b2119e75"&gt;oyeyemi oke&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Bought a MacBook Pro this year.&lt;/li&gt;
&lt;li&gt;Got a new Avatar this year. Its cool to have some sort of identity right? 😏&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B92Iids6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/417/1%2AkFA85l6oM9QjjHpKK3Bhag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B92Iids6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/417/1%2AkFA85l6oM9QjjHpKK3Bhag.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;And finally, just when it seems nothing serious will come out of this year as regards relationship, I met a young beautiful lady whose passion, dedication and support has been beyond expectation. Lucky to have you in my life &lt;a href="https://web.facebook.com/Elyno14"&gt;Funmilayo&lt;/a&gt; 😘.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2018 Resolution
&lt;/h3&gt;

&lt;p&gt;Looking into the new year with great expectations and more territories to conquer. I will like to hold myself accountable by the end of the year&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Writing :&lt;/strong&gt; I want to write more articles in 2018, improve on my writing skills 🔥 🔥 💪&lt;/li&gt;
&lt;li&gt;Become one of the top authors on scotch.io&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speak&lt;/strong&gt; and participate in more events and conferences&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kudos to everyone that made this year amazing for me. Lets do this again in 2018. #SpreadTheFire&lt;/p&gt;


</description>
      <category>review</category>
      <category>opensource</category>
      <category>javascript</category>
      <category>journey</category>
    </item>
    <item>
      <title>Build a Quote Application Using Laravel and Vue: Part 2</title>
      <dc:creator>Oluyemi</dc:creator>
      <pubDate>Thu, 14 Dec 2017 03:18:05 +0000</pubDate>
      <link>https://dev.to/yemiwebby/build-a-quote-application-using-laravel-and-vue-part-2-56kj</link>
      <guid>https://dev.to/yemiwebby/build-a-quote-application-using-laravel-and-vue-part-2-56kj</guid>
      <description>

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZhAtxSf2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/625/1%2AL9ZGzB55ZHhXYG-VV4Uz9A.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZhAtxSf2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/625/1%2AL9ZGzB55ZHhXYG-VV4Uz9A.jpeg" alt=""&gt;&lt;/a&gt;Quote Application Part 2&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/yemiwebby/build-a-quote-application-using-laravel-and-vue-part-1-3apg"&gt;first part&lt;/a&gt; of this series, we were able to successfully build the backend of our Quote Application using Laravel. We went ahead to also set up endpoints to post, fetch, update, and delete quote from our database. And lastly, we tested the functionality of our API by using a tool called &lt;a href="https://www.getpostman.com/"&gt;Postman&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we will complete the Quote application, by building the frontend with Vue.js. Here, we want to be able to achieve the following :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Post a new quote to the server&lt;/li&gt;
&lt;li&gt;Retrieve all quotes after they have been saved&lt;/li&gt;
&lt;li&gt;And finally, edit and delete quotes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Just before we proceed, open up the source code from the first part of the series in a code editor of your choice and run the application. It is important to keep this running as one of the objective of this tutorial is to ensure smooth communication between the Backend and Frontend on separate domains. The complete code for both application can be found on Github, scroll to the end of this tutorial to access the links.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let’s Build the Frontend
&lt;/h3&gt;

&lt;p&gt;An HTTP call will be required to access all the resources from the backend. For this, we will make use of &lt;a href="https://github.com/axios/axios"&gt;Axios&lt;/a&gt; which is a Promised based HTTP Client for the browser and node.js, but first, let’s install Vue. &lt;a href="https://github.com/vuejs/vue-cli"&gt;Vue-cli&lt;/a&gt; will be used here, as it will help us to rapidly scaffold Single Page Application in no time.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# install vue-cli
$ npm install -g vue-cli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, we’ll set up our Vue app with the CLI.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# create a new project using the "webpack" template
$ vue init webpack-simple frontend-quote-app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You will be prompted to enter a project name, description, author and others. This should initialize our app, all we have to do now is, change directory into our project folder and install the required dependencies.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#change directory
$ cd frontend-quote-app

#install dependencies
$ npm install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, to serve the application, run&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# run the application
$ npm run dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A similar page like the image below should open up in your browser by now&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7-uuEjFs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AQMg6M5k869x8FMJ14yVEng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7-uuEjFs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AQMg6M5k869x8FMJ14yVEng.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;p&gt;Since Vue offers developers the ability to use components driven approach when building web apps, we will create more components for our quote application. Vue CLI already generated a main component that can be found in src/App.vue, this will be used as the top level component for our application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Component
&lt;/h3&gt;

&lt;p&gt;Apart from the default component generated by Vue CLI, we will need more component, namely, 'new-quote.vue', quotes.vue', quote.vue' . These components will be used to add a new quote, display all quotes and moreso, be able to edit and delete quote.&lt;/p&gt;

&lt;p&gt;Ready? Let’s get to work!.&lt;/p&gt;

&lt;p&gt;Proceed to create a ./src/components folder, which will hold all the components that we will create soon.&lt;/p&gt;

&lt;p&gt;Create more component JS files such as quote.vue , quotes.vue , new-quote.vue within the components folder.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install NPM Modules
&lt;/h3&gt;

&lt;p&gt;As we are required to make web requests (API calls) within all the components created above, install &lt;a href="https://github.com/axios/axios"&gt;Axios&lt;/a&gt;).&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install axios --save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And for routing purposes, let’s also install &lt;a href="https://github.com/vuejs/vue-router"&gt;Vue-router&lt;/a&gt;&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install vue-router --save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure Components
&lt;/h3&gt;

&lt;p&gt;The required tools and components files have just been created, next is to start configuring these files by creating individual template, logic and style.&lt;/p&gt;

&lt;p&gt;First of all, clean up the default contents within ./src/App.vue . This will be filled later.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;

&amp;lt;div id="app"&amp;gt;
...
&amp;lt;/div&amp;gt;

&amp;lt;/template&amp;gt;

&amp;lt;script type="text/babel"&amp;gt;

export default {

data () {

return {

}
  }
}
&amp;lt;/script&amp;gt;

&amp;lt;style lang="scss"&amp;gt;
...
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  New-quote.vue
&lt;/h3&gt;

&lt;p&gt;This component is responsible for adding new quote(s). Whenever the form for posting a new quote is submitted, a function 'onSubmitted will be called and executed.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
   &amp;lt;div&amp;gt;
        &amp;lt;div class="col-lg-6 col-md-6 col-sm-6 col-xs-12"&amp;gt;
            &amp;lt;form @submit.prevent="onSubmitted"&amp;gt;
                &amp;lt;div class="form-group"&amp;gt;
                    &amp;lt;label for="content"&amp;gt;
                        &amp;lt;b&amp;gt;Quote&amp;lt;/b&amp;gt;
                        &amp;lt;/label&amp;gt;
                        &amp;lt;br&amp;gt;
                    &amp;lt;i&amp;gt; Write your quote&amp;lt;/i&amp;gt;

                    &amp;lt;textarea name="" id="content" class="form-control" v-model="quoteContent" cols="80" rows="6"&amp;gt;&amp;lt;/textarea&amp;gt;
                &amp;lt;/div&amp;gt;

                &amp;lt;div class="form-group"&amp;gt;
                    &amp;lt;button type="submit" class="btn btn-success"&amp;gt;
                        Submit
                    &amp;lt;/button&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/form&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script type="text/babel"&amp;gt;
    ...
&amp;lt;/script&amp;gt;

&amp;lt;style scoped&amp;gt;
...
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This function sends an HTTP request to the server (Laravel backend) with the quote data and stores it in the database. This pattern is similar to what we have in other components as will be revealed very soon.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
...
&amp;lt;/template&amp;gt;
&amp;lt;script type="text/babel"&amp;gt;
    import axios from 'axios';
    export default {
        data() {
            return {
                quoteContent: ''
            }
        },
        methods: {
            onSubmitted() {
                axios.post('http://localhost:8000/api/quote',
                        {content: this.quoteContent})
                        .then((response) =&amp;gt; {
                        window.location.href = "/";
                        })
            .catch ((error) =&amp;gt; console.log(error)
            )}
        }
    }
&amp;lt;/script&amp;gt;

&amp;lt;style scoped&amp;gt;
...
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Notice the URL and endpoint being called by axios within the onSubmitted() method &lt;a href="http://localhost:8000/api/quote"&gt;http://localhost:8000/api/quote&lt;/a&gt;? Remember the Laravel backend was started at the beginning of this tutorial, it is assumed that this application is running on localhost port 8000. Kindly change this URL if your backend is running on a different port.&lt;/p&gt;

&lt;p&gt;And style&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;style scoped&amp;gt;
#content {
    margin-top: 40px;
}
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Quotes.vue
&lt;/h3&gt;

&lt;p&gt;This is the parent component for quote component. Props defined here are are used to passed down information to the child component.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- quotes.vue --&amp;gt;
&amp;lt;template&amp;gt;
    &amp;lt;div&amp;gt;
        &amp;lt;div class="text-center"&amp;gt;
            &amp;lt;button class="btn btn-success" @click="onGetQuotes"&amp;gt;
            Get Quotes
             &amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;hr&amp;gt;

&amp;lt;app-quote v-for="quote in quotes" :qt="quote" :key="quote.id" @quoteDeleted="onQuoteDeleted($event)"&amp;gt;&amp;lt;/app-quote&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script type="text/babel"&amp;gt;
    ...
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;onGetQuotes() will initiate a call to the API backend and return all the posted quote(s) as response. This is being called after the instance has been mounted.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script type="text/babel"&amp;gt;
    import Quote from './quote.vue';
    import axios from 'axios';

export default {
        data() {
            return {
                quotes: []
            }
        },
        methods: {
            onGetQuotes() {
                axios.get('http://localhost:8000/api/quotes')
                        .then(
                                response =&amp;gt; {
                    this.quotes = response.data.quotes;
                }
                        )
                .catch(
                        error =&amp;gt; console.log(error)
                );
            },
            onQuoteDeleted(id) {
                const position = this.quotes.findIndex((element) =&amp;gt; {
                            return element.id == id;
                        });
                this.quotes.splice(position, 1);
            }
        },
        mounted: function () {
           this.onGetQuotes();
        },
        components: {
            'app-quote':Quote
        }
    }
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Quote.vue
&lt;/h3&gt;

&lt;p&gt;This is the child component of quotes component. Conditional declaration is used to toggle the editing mode, when the edit button is clicked, an onEdit() method is called and editing property from the vue instance is set to true. on the other hand, the onCancel() and onUpdtae() methods will set editing property to true after the specified login for this function are carried out.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- quote.vue --&amp;gt;
&amp;lt;template&amp;gt;
&amp;lt;div&amp;gt;
    &amp;lt;div v-if="editing"&amp;gt;
        &amp;lt;div class="col-lg-3 col-md-4 col-sm-6 col-xs-12"&amp;gt;
            &amp;lt;div class="form-group" id="form__group"&amp;gt;
                &amp;lt;label for="content"&amp;gt;&amp;lt;b&amp;gt;Edit Quote&amp;lt;/b&amp;gt;&amp;lt;/label&amp;gt;&amp;lt;br&amp;gt;
                &amp;lt;textarea id="content" v-model="editValue" rows="10" cols="30" class="form-control"&amp;gt;&amp;lt;/textarea&amp;gt;
                &amp;lt;div class="control_1"&amp;gt;
                    &amp;lt;button @click="onUpdate" class="btn btn-success"&amp;gt;Save&amp;lt;/button&amp;gt;
                    &amp;lt;button @click="onCancel" class="btn btn-danger"&amp;gt;Cancel&amp;lt;/button&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;

&amp;lt;div v-if="!editing"&amp;gt;
        &amp;lt;div class="col-lg-3 col-md-4 col-sm-6 col-xs-12"&amp;gt;
            &amp;lt;div class="quote-holder"&amp;gt;
                &amp;lt;div class="quote"&amp;gt;
                    {{ qt.content }}
                &amp;lt;/div&amp;gt;

&amp;lt;div class="quote_control"&amp;gt;
                    &amp;lt;div&amp;gt;
                        &amp;lt;div class="control_1"&amp;gt;
                            &amp;lt;button @click="onEdit" class="btn btn-primary"&amp;gt;
                                Edit
                            &amp;lt;/button&amp;gt;
                            &amp;lt;button @click="onDelete" class="btn btn-danger"&amp;gt;
                                Delete
                            &amp;lt;/button&amp;gt;
                        &amp;lt;/div&amp;gt;

&amp;lt;div class="control_2"&amp;gt;
                        &amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;/template&amp;gt;

&amp;lt;script type="text/babel"&amp;gt;
   ...
&amp;lt;/script&amp;gt;

&amp;lt;style scoped&amp;gt;
   ...
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The expected information, in this case, quote are declared and received using the props option :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script type="text/babel"&amp;gt;
    import axios from 'axios';

export default {
        props: ['qt'],
        data() {
            return {
                editing: false,
                editValue: this.qt.content
            }
        },
        methods: {
            onEdit() {
                this.editing = true;
                this.editValue = this.qt.content
            },
            onCancel() {
                this.editing = false;
            },
            onDelete() {
                this.$emit('quoteDeleted', this.qt.id);
                axios.delete('http://localhost:8000/api/quote/' + this.qt.id)
                        .then(
                                response =&amp;gt; console.log(response)
            )
            .catch (
                        error =&amp;gt; console.log(error)
            )
            },
            onUpdate() {
                this.editing = false;
                this.qt.content = this.editValue;
                axios.put('http://localhost:8000/api/quote/' + this.qt.id,
                        {content: this.editValue})
                        .then(
                                response =&amp;gt; console.log(response)
            )
            .catch (
                        error =&amp;gt; console.log(error)
            )
                ;
            }
        }
    }
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Style&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;style scoped&amp;gt;
a {
        cursor: pointer;
    }

.quote {
        display: block;
        margin-left: auto;
        margin-right: auto;
        /*min-height: 125px;*/
    }

.quote-holder {
        background: #ffffff;
        margin-bottom: 30px;
        position: relative;
        overflow: hidden;
        padding: 20px;
        min-height: 250px;
    }
    .quote_btn {
        border-radius: 0;
        width: 100%;
        display: block;
        cursor: pointer;
    }

.quote_control {
        width: 100%;
        display: flex;
        padding: 20px 20px 15px;
        background: #FFF;
    }

.control_1 {
        flex: 2;
    }
    .control_2 {
        flex: 1;
        /*display: flex;*/
        justify-content: flex-end;
        align-items: center;
        font-size: 20px;
        font-weight: bold;
        color: #51D2B7;
    }

#form__group{
        box-sizing: border-box;
        overflow: hidden;
    }

textarea {
        margin: 10px 0;
    }
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  index.html
&lt;/h3&gt;

&lt;p&gt;Bootstrap classes are used to improve the styling in this application. Don’t forget to include stylesheet in index.html file :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Vue + laravel&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"&lt;/span&gt; &lt;span class="na"&gt;integrity=&lt;/span&gt;&lt;span class="s"&gt;"sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"&lt;/span&gt; &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/dist/build.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  App.vue
&lt;/h3&gt;

&lt;p&gt;Earlier we cleaned up this file by getting rid of the default contents. Now, fill it with :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- App.vue --&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div id="app"&amp;gt;
    &amp;lt;div class="container"&amp;gt;
      &amp;lt;div class="row"&amp;gt;
        &amp;lt;div class="col-xs-12"&amp;gt;
         &amp;lt;nav class="navbar navbar-default navbar-fixed-top"&amp;gt;
            &amp;lt;div class="container"&amp;gt;
              &amp;lt;ul class="nav navbar-nav navbar-center links"&amp;gt;
                &amp;lt;li&amp;gt;&amp;lt;router-link to="/"&amp;gt;Quotes&amp;lt;/router-link&amp;gt;&amp;lt;/li&amp;gt;
                &amp;lt;li&amp;gt;&amp;lt;router-link to="/new-quote"&amp;gt; New Quotes&amp;lt;/router-link&amp;gt;&amp;lt;/li&amp;gt;
              &amp;lt;/ul&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/nav&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;hr&amp;gt;
      &amp;lt;div class="row"&amp;gt;
        &amp;lt;div class="col-xs-12"&amp;gt;
          &amp;lt;div id="view"&amp;gt;
            &amp;lt;router-view&amp;gt;&amp;lt;/router-view&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script type="text/babel"&amp;gt;
export default {
  data () {
    return {

}
  }
}
&amp;lt;/script&amp;gt;

&amp;lt;style lang="scss"&amp;gt;
#app {
  margin: 30px 0 0 0;
  background: #F7F8FB;
  min-height: 800px;
}

#view {
    margin-top: 80px;
  }

.navbar {
    background: #333333;
    min-height: 70px;
    font-weight: bold;
  }
  .links {
   margin-top: 10px;
  }

.links li a {
    color: #ffffff !important;
    font-weight: bold;
    font-size: 20px;
  }
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Don’t forget that we have made use of custom html tags within our vue' files. All these component tag and routes will be managed by src/main.js . So open the file and fill in the content below :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- src/main.js --&amp;gt;
import Vue from 'vue'
import VueRouter from 'vue-router';

import App from './App.vue'
import Quotes from './components/quotes.vue';
import NewQuote from './components/new-quote.vue';

Vue.use(VueRouter);

const routes = [
  { path: '', component: Quotes},
  { path: '/new-quote', component: NewQuote },
];

const router = new VueRouter({
  node: 'history',
  routes: routes
});
new Vue({
  el: '#app',
      router: router,
  render: h =&amp;gt; h(App)
})
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  CORS (Cross-Origin Resource Sharing)
&lt;/h3&gt;

&lt;p&gt;Now if we attempt to post a quote from our frontend-quote-app, we will be redirected to the homepage but the quote will not be saved. Inspecting the browser will reveal what the error is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EgFywcSO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2APWK-01xS5UJu3Jv9jON9Mg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EgFywcSO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2APWK-01xS5UJu3Jv9jON9Mg.gif" alt=""&gt;&lt;/a&gt;Check the console&lt;/p&gt;

&lt;p&gt;Just before you get scared, it is interesting to affirm that we had this error coming. In this application, we are trying to create a direct connection between two different domains. Technically, It is generally not allowed to have two different applications, with different domain name exchanging data. This is by default a form of security measure, but since we are building an API backend, we will have to turn off this protection in order to allow our frontend communicate effectively with the backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Back to the Backend Application
&lt;/h3&gt;

&lt;p&gt;Earlier on, I stated that we need to keep our server on, just incase you haven’t done that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mission
&lt;/h3&gt;

&lt;p&gt;Our goal, is to be able to target all API route from a different domain. In order to achieve this, we must create a new middleware, register it and eventually attach this middleware to our routes. You can read more about Laravel middlewares &lt;a href="https://laravel.com/docs/5.5/middleware"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Middleware
&lt;/h3&gt;

&lt;p&gt;Creating a middleware in Laravel application is quite easy. A middleware named Cors will be created for the purpose of this article, and all we have to do is run this command. So open your terminal and go ahead :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:middleware Cors
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will create a middleware in app/Http/middleware/Cors.php . Now is the convenient moment to open the newly created middleware and add the logic to accept incoming HTTP request from the frontend-quote-app'.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nx"&gt;App\Http\Middleware&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;Closure&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Cors&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Closure&lt;/span&gt; &lt;span class="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Access-Control-Allow-Origin'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&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="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Access-Control-Allow-Methods'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'GET, POST, PUT, PATCH, DELETE, OPTIONS'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Access-Control-Allow-Headers'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type, Authorization'&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;Here, HTTP headers were set to allow the frontend-application gain permission to access resources from the backend app.&lt;/p&gt;

&lt;p&gt;Now that we have added the required Logic into the created middleware, Laravel needs to know that a new middleware exists and then be able to use it. Go to app/Http/Kernel.php and add to kernel class :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;protected $middleware = [
       ...
        \App\Http\Middleware\Cors::class,
    ];
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With this, we should be able to successfully communicate with our backend application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SIGKgpGl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AFivIY_jsF9gMZahKTbkumw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SIGKgpGl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AFivIY_jsF9gMZahKTbkumw.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please feel free to try out the demo &lt;a href="http://demo.yemiwebby.com.ng/"&gt;here&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;So in this series, we have learnt to :&lt;br&gt;&lt;br&gt;
* Build API using Laravel&lt;br&gt;&lt;br&gt;
* Use a frontend library (VueJs) to consume the API built with Laravel&lt;br&gt;&lt;br&gt;
* Ensure smooth communication between two separate domains.&lt;/p&gt;

&lt;p&gt;I hope you have seen how you can conveniently connect Vuejs with a Laravel API backend.&lt;/p&gt;

&lt;p&gt;In a subsequent post, we will learn how to add authentication to this application and allow only user with the right access to be able to carry out certain actions like editing and deleting a particular quote.&lt;br&gt;&lt;br&gt;
If you found this tutorial helpful, have any suggestions or encounter any issues, kindly leave a comment below.&lt;/p&gt;

&lt;p&gt;Here are the links to the source code in both series can be found on github, &lt;a href="https://github.com/yemiwebby/backend-quote-app"&gt;Backend&lt;/a&gt; and &lt;a href="https://github.com/yemiwebby/frontend-quote-app"&gt;Frontend&lt;/a&gt;.&lt;/p&gt;


</description>
      <category>vue</category>
      <category>laravel</category>
      <category>webdev</category>
      <category>webpack</category>
    </item>
    <item>
      <title>Build a Quote Application Using Laravel and Vue: Part 1</title>
      <dc:creator>Oluyemi</dc:creator>
      <pubDate>Mon, 11 Dec 2017 02:33:24 +0000</pubDate>
      <link>https://dev.to/yemiwebby/build-a-quote-application-using-laravel-and-vue-part-1-3apg</link>
      <guid>https://dev.to/yemiwebby/build-a-quote-application-using-laravel-and-vue-part-1-3apg</guid>
      <description>

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3T1uCODb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/640/1%2Am5oBrqMwPIdQk7blG8lrPQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3T1uCODb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/640/1%2Am5oBrqMwPIdQk7blG8lrPQ.png" alt=""&gt;&lt;/a&gt;Laravel and Vuejs&lt;/p&gt;

&lt;p&gt;Have you ever thought of the best way to structure your application and split up your backend and frontend into the separate domains? Then you are in the right place and this tutorial is just for you!&lt;/p&gt;

&lt;p&gt;We are in the era of a client-server model architecture of building web applications, where the backend is built as an API and a frontend is built to consume it.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will build an application where we will ensure a smooth communication between a backend (API) and a frontend(Vue) on a separate domain. Laravel will be used to expose some API endpoints or URL to which Vue application can connect to and carry out different actions or requests.&lt;/p&gt;

&lt;p&gt;This tutorial assumes you have a basic knowledge of object oriented programming in PHP and javaScript. And even-though we will be going through the basics of Laravel and Vue.js, a basic understanding of their concepts is recommended. Now that we have that cleared, lets build something awesome together.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Consuming web services are where JavaScript library like Vue really shines.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="http://vuejs.org"&gt;&lt;strong&gt;Vue&lt;/strong&gt;&lt;/a&gt; is a progressive JavaScript framework for building user interfaces on the web. It can easily be used to build a single page application(SPA), and can also scale up to be used for a large scale enterprise application.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://laravel.com"&gt;&lt;strong&gt;Laravel&lt;/strong&gt;&lt;/a&gt; on another hand, is a powerful MVC PHP web application framework with expressive, elegant syntax, and it is designed for developers who need a simple and elegant toolkit to create full-featured web applications.&lt;/p&gt;

&lt;p&gt;There are two different ways of connecting Laravel to a library like Vue.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You could either simply add some widget to your Laravel application, that is, you can still render some views with Laravel but using Vue to power the DOM, this enhances the ability to edit the DOM at runtime&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build both Laravel backend and Vue on separate domains and connect them to each other via HTTP calls.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the sake of this tutorial, we’ll choose the second option.&lt;/p&gt;

&lt;p&gt;Since Vue cannot be used to connect to a server for a dynamic web experience, we will employ and use Laravel as our backend application.&lt;br&gt;&lt;br&gt;
Laravel will not be used here to render multiple views but instead, it will provide the API that will be connected to by Vue via Ajax HTTP Request. This covers all the request required when reaching out to the backend of any application.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What We’ll Build&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To better demonstrate this connection between Vue and Laravel, together, we’ll build a simple quote Application. Vue will be used to post a quote to the backend for it to be saved and also fetch the quote, for it to be displayed on the homepage. You can checkout the demo &lt;a href="http://demo.yemiwebby.com.ng/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SIGKgpGl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AFivIY_jsF9gMZahKTbkumw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SIGKgpGl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AFivIY_jsF9gMZahKTbkumw.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will be a single page application powered fully by Vue, with the ability to switch between pages, and re-render contents on the pages based on the data fetched from the backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let’s Get Started
&lt;/h3&gt;

&lt;p&gt;As mentioned earlier, our Laravel backend will make available some API endpoint that will eventually be consumed by Vue. To create this, we will start by building all the required API endpoint necessary for interacting with our frontend App.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set Up Backend
&lt;/h3&gt;

&lt;p&gt;Laravel utilizes &lt;a href="https://getcomposer.org/"&gt;Composer&lt;/a&gt; to manage its dependencies. So before using Laravel, make sure you have Composer installed on your machine.&lt;/p&gt;

&lt;p&gt;You can download and install Laravel via:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Laravel installer
&lt;/li&gt;
&lt;li&gt;Composer create-project.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We’ll start by creating a new Laravel project called 'backend-quote-app'&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer create-project --prefer-dist laravel/laravel backend-quote-app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And if you have &lt;a href="https://laravel.com/docs/5.5#installing-laravel"&gt;Laravel installer&lt;/a&gt; already installed on your computer, you can simply proceed to run the command below&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;laravel new backend-quote-app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now change directory to the newly created project folder backend-quote-app and start the PHP’s built-in development server to serve the application like this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## change directory
cd backend-quote-app

## start the server
php artisan serve
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By now, you should have your Laravel application set up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--75x7ILvw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A5bFIUo6j9PG0p3fDA2R7lw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--75x7ILvw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A5bFIUo6j9PG0p3fDA2R7lw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your homepage should look similar to what we have above if you open your Laravel application on your local server. What I have done differently was to edit the resources/views/welcome.blade.php as shown below.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- resources/views/welcome.blade.php --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"{{ app()-&amp;gt;getLocale() }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
      ...
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"title m-b-md"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                   // this was edited
                    Scotch Demo Quote App
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"links"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                   ...
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Up Your Route
&lt;/h3&gt;

&lt;p&gt;For a normal Laravel application, it is conventional for us to setup our route by using routes/web.php file, but for the purpose of this tutorial, we will be using routes/api.php. This is a group of route specifically made for API endpoints. The routes in routes/api.php are stateless and are assigned the api middleware group.&lt;br&gt;&lt;br&gt;
For this sample application, we will need the routes below&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/quote'&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;
        &lt;span class="s1"&gt;'uses'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'QuoteController@postQuote'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'as'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'post-quote'&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/quotes'&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;
        &lt;span class="s1"&gt;'uses'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'QuoteController@getQuotes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'as'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'get-quotes'&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/quote/{id}'&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;
        &lt;span class="s1"&gt;'uses'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'QuoteController@putQuote'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'as'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'update-quote'&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/quote/{id}'&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;
        &lt;span class="s1"&gt;'uses'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'QuoteController@deleteQuote'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'as'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'delete-quote'&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We are basically using the HTTP verbs POST, GET, PUT, and DELETE to post, fetch, update and delete the quote from our database respectively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Model and Controller
&lt;/h3&gt;

&lt;p&gt;Create a model in order to access quotes(i.e fetching and storing quotes in the database) by running the command below :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:model Quote -m
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will create a model Quote and a migration file to build the application’s database schema.&lt;/p&gt;

&lt;p&gt;Now that we have both model and migration file ready. We won’t be adding much content to app\Quote.php, but we will need to edit the contents of the migration file within database\migrations directory to reflect our database schema :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;Illuminate\Support\Facades\Schema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;Illuminate\Database\Schema\Blueprint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;Illuminate\Database\Migrations\Migration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateQuotesTable&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Migration&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;up&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'quotes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Blueprint&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;increments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;timestamps&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;down&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;dropIfExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'quotes'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

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



&lt;h3&gt;
  
  
  Database Set Up
&lt;/h3&gt;

&lt;p&gt;Open the .env file and add your database details&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_CONNECTION=mysql

DB_HOST=127.0.0.1

DB_PORT=3306

DB_DATABASE=Your-database-name

DB_USERNAME=Your-database-username

DB_PASSWORD=Your-database-password
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Migrating and Creating Table
&lt;/h3&gt;

&lt;p&gt;You can go ahead and run the migration with :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan migrate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you hit this error when trying to run the migration command,&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[PDOException]                                                               
  SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;this is because you are running an older version of MySQL. You can read more about it &lt;a href="https://laravel-news.com/laravel-5-4-key-too-long-error"&gt;here&lt;/a&gt;. But a quick fix is to drop the database and re-create it. Then you will have to edit your AppServiceProvider file and set a default string length inside the boot method:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can now re-run the migration command and all should be fine by now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Controller
&lt;/h3&gt;

&lt;p&gt;The next step is to create Controller and quickly set up the required logic for our application&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:controller QuoteController
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The command above will create a new file called QuoteController.php stored in the app/Http/Controllers. Here, we want to be able to handle requests to postQuote, getQuotes, putQuote and deleteQuote. We will need to create a couple of functions for all these requests :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nx"&gt;App\Http\Controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;App\Quote&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;Illuminate\Http\Request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QuoteController&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;postQuote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getQuotes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;putQuote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;deleteQuote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="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 that the functions have been created, we need to start implementing their functionalities.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public function postQuote(Request $request)
    {
        $quote = new Quote();
        $quote-&amp;gt;content = $request-&amp;gt;input('content');
        $quote-&amp;gt;save();
        return response()-&amp;gt;json(['quote' =&amp;gt; $quote], 201);
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;First of all, in order to create a new quote and persist into the database, we instantiate the Quote model, use Laravel’s input()method to retrieve the value passed in from the input field content and then save it. A response was also returned with the newly created quote and a status code of &lt;a href="https://httpstatuses.com/201"&gt;201&lt;/a&gt;.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public function getQuotes()
    {
        $quotes = Quote::all();
        $response = [
            'quotes' =&amp;gt; $quotes
        ];
        return response()-&amp;gt;json($response, 200);
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The created quotes need to be fetched and returned for it to be displayed to users, this method above handles that. It retrieves all the quotes from the database and return it in json format.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public function putQuote(Request $request, $id)
    {
        $quote = Quote::find($id);

// check if quote is not found
        if(!$quote)
        {
            return response()-&amp;gt;json(['message' =&amp;gt; 'Quote not found'], 404);
        }

$quote-&amp;gt;content = $request-&amp;gt;input('content');

$quote-&amp;gt;save();
        return response()-&amp;gt;json(['quote' =&amp;gt; $quote], 200);
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We added another functionality to update any created quote within our application. This method takes in an extra argument, which is the id of the quote we wish to update. It retrieves the quote, update it and then persist into the database.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public function deleteQuote($id)
    {
        $quote = Quote::find($id);
        $quote-&amp;gt;delete();
        return response()-&amp;gt;json(['message' =&amp;gt; 'Quote deleted'], 200);
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To finally complete the CRUD(Create, Read, Update and Delete) operation, the deleteQuote($id) uses the find() method to fetch the quote and then delete.&lt;/p&gt;

&lt;p&gt;A close look at all the functions in this controller, you will noticed the use of a json()method all through. It is a Laravel helper method that takes in two arguments, the first one is an associative array which will be transferred to json format by Laravel and the second is a status code. This method comes handy and useful when developing especially a micro service-based application.&lt;/p&gt;

&lt;p&gt;All setup? Great!!.&lt;/p&gt;

&lt;p&gt;You can quickly test the API endpoints by using a tool called Postman.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fsixWHG_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A9FLmcV55GRveJPCsv4cIow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fsixWHG_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A9FLmcV55GRveJPCsv4cIow.png" alt=""&gt;&lt;/a&gt;Post a Quote&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mb-iyxF5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A6pLOhHUViWJXNTkZsNvzhw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mb-iyxF5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A6pLOhHUViWJXNTkZsNvzhw.png" alt=""&gt;&lt;/a&gt;Get Quotes&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kkOgzycx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AecdfPHu6mo-ZqrFPjIJoow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kkOgzycx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AecdfPHu6mo-ZqrFPjIJoow.png" alt=""&gt;&lt;/a&gt;Get quotes using the browser&lt;/p&gt;

&lt;p&gt;If you have followed along up until now, you should celebrate&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ywoDT-qg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/644/1%2AN2dboiW9YZabgqfozzoSxQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ywoDT-qg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/644/1%2AN2dboiW9YZabgqfozzoSxQ.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! you have successfully set up the backend for our Quote application.&lt;/p&gt;

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

&lt;p&gt;So far, we have been able to set up the backend required for the quote Application. In the next part, we will build the frontend with Vue, this will consume the API created. In order to ensure a smooth communication between the frontend and backend, we will also enable CORS (Cross-origin resource sharing). See you then.&lt;/p&gt;

&lt;p&gt;PART 2 : &lt;a href="https://dev.to/yemiwebby/build-a-quote-application-using-laravel-and-vue-part-2-56kj"&gt;Here&lt;/a&gt;&lt;/p&gt;


</description>
      <category>webdev</category>
      <category>laravel</category>
      <category>composer</category>
      <category>cors</category>
    </item>
    <item>
      <title>Handling Ajax Request in Vue Applications Using Axios.</title>
      <dc:creator>Oluyemi</dc:creator>
      <pubDate>Sat, 09 Dec 2017 19:02:57 +0000</pubDate>
      <link>https://dev.to/yemiwebby/handling-ajax-request-in-vue-applications-using-axios-30cm</link>
      <guid>https://dev.to/yemiwebby/handling-ajax-request-in-vue-applications-using-axios-30cm</guid>
      <description>

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CWClkbj2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AmiB-YGBcasaouoRP4rovng.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CWClkbj2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AmiB-YGBcasaouoRP4rovng.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Contemporarily, the prevalent Architecture for building web applications is a client-server model. This makes it very easy to build, especially, JavaScript Applications by fetching data from a remote source or consume an &lt;a href="https://en.wikipedia.org/wiki/Application_programming_interface"&gt;API&lt;/a&gt;. It can either be Publicly available APIs or the ones you personally built using frameworks like &lt;a href="https://laravel.com/"&gt;Laravel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vuejs.org/"&gt;Vue&lt;/a&gt; offers the flexibility to build applications using data fetched from any API and conveniently serve content to the users of your applications.&lt;/p&gt;

&lt;p&gt;For the purpose of this tutorial, we are going to explore one of the publicly available API &lt;a href="http://www.icndb.com/api/"&gt;ICNDB&lt;/a&gt;. Its basically a database of chuck norris jokes on the internet. Fetching data from this API will give us an overview of how to successfully communicate with information from a remote source using Axios.&lt;/p&gt;

&lt;p&gt;A basic understanding of the concept of Vue will be a plus in order to be able to follow along properly in this tutorial.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making Ajax Request and Handling Responses
&lt;/h3&gt;

&lt;p&gt;Handling Ajax request within a Vue application was previously made easy by using &lt;a href="https://github.com/pagekit/vue-resource"&gt;vue-resource&lt;/a&gt;, which has now been &lt;a href="https://medium.com/the-vue-point/retiring-vue-resource-871a82880af4"&gt;retired&lt;/a&gt;. This means any 3rd party libraries can be used for the purpose of making Ajax request, but as recommended by &lt;a href="https://twitter.com/youyuxi"&gt;Evan&lt;/a&gt;, we will use Axios. Axios is a commendable promise-based HTTP client library that runs on both the client and the server.&lt;/p&gt;

&lt;p&gt;Now that we are conversant with the tools and what we intend to build, let’s get right into it.&lt;/p&gt;

&lt;h3&gt;
  
  
  What we will Build
&lt;/h3&gt;

&lt;p&gt;A sneak peek into what we will build in this tutorial.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--l7-QpQcR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A6edx8b79WySFBSLdj3wUBQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l7-QpQcR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A6edx8b79WySFBSLdj3wUBQ.gif" alt=""&gt;&lt;/a&gt;What we will Build&lt;/p&gt;

&lt;p&gt;Ready? Lets build it!&lt;/p&gt;

&lt;h3&gt;
  
  
  Set Up Application
&lt;/h3&gt;

&lt;p&gt;Vue CLI will be used here to quickly set up the application. This command line interface(Vue-CLI) provides a means of rapidly generating a Single Page Application in no time, we will install it in a bit. Before installing vue-cli globally on your system, I assume that you already have Node and npm installed, if otherwise quickly download them &lt;a href="https://nodejs.org/en/"&gt;here&lt;/a&gt;. Once you are done, you can verify Node and npm from the terminal with :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node -v

npm -v
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now install Vue-CLI :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g vue-cli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Having installed the CLI, vue command becomes available for scaffolding our application. Lets use it to create a project for this tutorial&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vue init webpack-simple vue-axios
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We used webpack-simple template instead of starting out with a blank page.&lt;/p&gt;

&lt;p&gt;Next, change directory into the newly created project and install all the dependencies.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd vue-axios

npm install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This might take few minutes to get all the necessary files installed, once the process is completed, start the application with :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will start the application on your default browser on port 8080, as shown below :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0EkbCScm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AfN6a_CpUh3ymfhFkryFcBw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0EkbCScm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AfN6a_CpUh3ymfhFkryFcBw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Axios
&lt;/h3&gt;

&lt;p&gt;One of the main objective of this tutorial is to learn how to seamlessly use axios in our application. Lets install it using npm :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install axios --save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Axios will be installed and save into the package.json file in our application.&lt;/p&gt;

&lt;p&gt;Now that the necessary dependencies and tools have been installed. We will then build a component that will be used to make the API call described earlier and also render the fetched contents. Using Vue-CLI to scaffold an application will also generate a default component ./src/App.vue Open this file and clear the contents in there&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;

&amp;lt;div id="app"&amp;gt;
...

&amp;lt;/div&amp;gt;

&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;

export default {

name: 'app',

data () {

return {

}

}

}

&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;

&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will result in an empty page if you check your browser now. Let the filling commence.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div id="app"&amp;gt;
    &amp;lt;header&amp;gt;
      &amp;lt;span&amp;gt;Handling Ajax Request with Axios in Vue&amp;lt;/span&amp;gt;
    &amp;lt;/header&amp;gt;
    &amp;lt;main&amp;gt;
        &amp;lt;h2&amp;gt;Click the button to get Random jokes&amp;lt;/h2&amp;gt;
        &amp;lt;button id="btn" class="" v-on:click="getJokes"&amp;gt;Get Jokes&amp;lt;/button&amp;gt;

        &amp;lt;div v-if="loading"&amp;gt;
          &amp;lt;img src="../src/assets/loader.gif"/&amp;gt;
          Loading.....
        &amp;lt;/div&amp;gt;

      &amp;lt;div class="wrapper"&amp;gt;
        ... 
      &amp;lt;/div&amp;gt;
    &amp;lt;/main&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
...
&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;
...
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So far, within this file, we have added a header in order to display the title of the application. And within the '&amp;lt;main&amp;gt;&amp;lt;/main&amp;gt;' tag, we have a button that will call a function 'getJokes()’ once clicked. This function will be defined very soon.&lt;/p&gt;

&lt;p&gt;Furthermore, we added a loader image that will be displayed once API call is initiated. This loader image will be hidden once our content has been received from the remote source.&lt;/p&gt;

&lt;p&gt;Next we will set up the script to make the calls, loop through the data within our component in order to display the results and then add a little bit of styling.&lt;/p&gt;

&lt;p&gt;Edit the 'App.vue' file :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
...
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
  import axios from 'axios';

export default {
  name: 'app',
  data () {
    return {
      jokes: [],
      loading: false
    }
  }, 
  methods: {
    getJokes: function () {
      this.loading = true;
      axios.get("http://api.icndb.com/jokes/random/10")
      .then((response) =&amp;gt; {
        this.loading = false;
        this.jokes = response.data.value;
      }, (error) =&amp;gt; {
        this.loading = false;
      })
    }
  },
}
&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;
...
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;First of all, we imported axios into our component as we already have it installed. Then we setup the 'getJokes()' function and make API to '&lt;a href="http://api.icndb.com/jokes/random/10"&gt;http://api.icndb.com/jokes/random/10&lt;/a&gt;', this will return 10 random jokes to be rendered. And lastly, we also set a condition for loading and hiding the image loader.&lt;/p&gt;

&lt;p&gt;To view the content from our API calls, lets go back to the our component and set up the view:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div id="app"&amp;gt;
        ...
        &amp;lt;div v-if="loading"&amp;gt;
          ...
        &amp;lt;/div&amp;gt;

      &amp;lt;div class="wrapper"&amp;gt;
        &amp;lt;div class="row"&amp;gt;
          &amp;lt;div v-for="joke in jokes" :key="joke.id"&amp;gt;
          &amp;lt;div class="col-md-4 cards"&amp;gt;
             &amp;lt;img src="https://placeimg.com/300/300/nature" class="img-responsive" alt="Random images placeholder"&amp;gt; 
            &amp;lt;div&amp;gt;
              &amp;lt;h3&amp;gt;{{ joke.id }}&amp;lt;/h3&amp;gt;
              &amp;lt;p&amp;gt;{{ joke.joke }}&amp;lt;/p&amp;gt;
              &amp;lt;p&amp;gt;{{ joke.category }}&amp;lt;/p&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/main&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
...
&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;
...
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here, we used the v-for directive to render a list of items based on the array fetched from the API.&lt;/p&gt;

&lt;p&gt;In addition to the bootstrap framework used to style the application, we will also add a little bit of custom style :&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  ...
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
   ...
&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;
  body {
  margin: 0;
}

#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
}

main {
  text-align: center;
  margin-top: 40px;
}

header {
  margin: 0;
  height: 56px;
  padding: 0 16px 0 24px;
  background-color: #35495E;
  color: #ffffff;
}

header span {
  display: block;
  position: relative;
  font-size: 20px;
  line-height: 1;
  letter-spacing: .02em;
  font-weight: 400;
  box-sizing: border-box;
  padding-top: 16px;
}

button {
  background: #51B767;
  color: #ffffff;
  padding: 15px;
  border-radius: 0;
  font-weight: bold;
  font-size: 15px;
  border: 0;
}

.cards {
  background: #F5F5F5;
  height:400px;
}
 .cards:hover {
  transform: translateY(-0.5em);
  background: #EBEBEB;
}

.cards {
   column-count: 1;
  column-gap: 1em;
    margin-top: 70px;

} 
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Download the loader image loader.gif from &lt;a href="https://github.com/yemiwebby/vue-axios/blob/master/src/assets/loader.gif"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And refresh your browser :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nUCj3UW2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AShgzy9U2qMR1heYg5uKbLA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nUCj3UW2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AShgzy9U2qMR1heYg5uKbLA.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And don’t forget to include the link tag for bootstrap in the application’s index.html file.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By now, your page should look properly aligned&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EXImejMM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AxihoDGuq10sMcbwBtUKxYg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EXImejMM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AxihoDGuq10sMcbwBtUKxYg.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;In this post, we have only used Axios to make a GET request and obtain contents from an API. Axios is powerful enough to handle other HTTP request methods such as POST, PUT, PATCH and DELETE anywhere in our application. Feel free to improve on this and if you found this post useful, show some love with claps. The code can also be found &lt;a href="https://github.com/yemiwebby/vue-axios"&gt;on github&lt;/a&gt;.&lt;/p&gt;





</description>
      <category>webdev</category>
      <category>axios</category>
      <category>vue</category>
      <category>httprequest</category>
    </item>
    <item>
      <title>Send SMS From Laravel Application</title>
      <dc:creator>Oluyemi</dc:creator>
      <pubDate>Sun, 08 Oct 2017 17:52:53 +0000</pubDate>
      <link>https://dev.to/yemiwebby/send-sms-from-laravel-application-21oa</link>
      <guid>https://dev.to/yemiwebby/send-sms-from-laravel-application-21oa</guid>
      <description>

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MApoqgxh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/555/1%2AZHBlfqQ44YXy1OeVc0k67g.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MApoqgxh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/555/1%2AZHBlfqQ44YXy1OeVc0k67g.jpeg" alt=""&gt;&lt;/a&gt;&lt;a href="http://pngtree.com/do/envelope"&gt;http://pngtree.com/do/envelope&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is always a need to send a message to users from your web application. It could be to verify details such as phone number or send a &lt;code&gt;**_one time password_**&lt;/code&gt; popularly called OTP before a transaction can be completed. Most users don’t have the luxury of patience, waiting for messages to arrive, they want it Asap!!!.&lt;/p&gt;

&lt;p&gt;I used this on a particular project recently, so I thought the need to share how I was able to put this together. My application was built using &lt;a href="https://laravel.com/"&gt;Laravel&lt;/a&gt; and an API provided by one of the best bulk SMS platforms in Nigeria (&lt;a href="https://www.bulksmsnigeria.net/"&gt;https://www.bulksmsnigeria.net/&lt;/a&gt;).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;** Disclamer:- I am not in any way affiliated with BulkSMSNigeria and this is not a sponsored post.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since this post is not really about how you can get started with Laravel. I will suggest that you follow this link &lt;a href="https://laravel.com"&gt;https://laravel.com&lt;/a&gt; and learn more about laravel and how to quickly set it up.&lt;/p&gt;

&lt;p&gt;Alright, there is a lot to do, so I will suggest we quickly get into it&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Let’s Begin&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I assume that you already have &lt;a href="https://getcomposer.org/"&gt;composer&lt;/a&gt; setup on your system. Else, quickly follow that link and get composer now.&lt;/p&gt;

&lt;p&gt;You can download and install Laravel via:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Laravel installer
&lt;/li&gt;
&lt;li&gt;Composer create-project.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the purpose of this tutorial, I will use the second option which is proven to be more straightforward.&lt;/p&gt;

&lt;p&gt;So, run the following command in your terminal.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer create-project — prefer-dist laravel/laravel send-sms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The command above will create a new directory (folder) called &lt;code&gt;**send-sms**&lt;/code&gt; in your preferred development folder or whenever local folder you run the command from.&lt;/p&gt;

&lt;p&gt;By now, you should have a new laravel project called &lt;code&gt;**_send-sms_**&lt;/code&gt;, obviously, this is the name of our simple project, but please feel free to name it whatever you like.&lt;/p&gt;

&lt;p&gt;change directory into your new project&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd send-sms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And start the PHP’s built-in development server to serve your application with the Artisan command below:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan serve
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This command will start a development server at &lt;a href="http://localhost:8000"&gt;http://localhost:8000&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;check it out&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QJKV2md7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AC2R4JrIMCo3RIzll2fMZXw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QJKV2md7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AC2R4JrIMCo3RIzll2fMZXw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;WHAT WE WILL BUILD&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now that we are fully set up with laravel. Don’t forget that the main aim of this tutorial is to be able to send SMS from our laravel application. So we are just going to build a very simple form that takes in the phone number of a user and send SMS to him/her.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nNaDJQKR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AHQbDUxkcRuuKHynXJCYVng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nNaDJQKR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AHQbDUxkcRuuKHynXJCYVng.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quickly create a controller that will handle the SMS action for us&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:controller SmsController
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will generate a new controller for you. Fill in the following : -&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nx"&gt;App\Http\Controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;Illuminate\Http\Request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;GuzzleHttp\Exception\GuzzleException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;GuzzleHttp\Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SmsController&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$SMS_SENDER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Sample"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$RESPONSE_TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'json'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$SMS_USERNAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Your username'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$SMS_PASSWORD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Your password'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$phone_number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'phone_number'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"A message has been sent to you"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;initiateSmsActivation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$phone_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// $this-&amp;gt;initiateSmsGuzzle($phone_number, $message);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;back&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Message has been sent successfully'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;initiateSmsActivation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$phone_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nv"&gt;$isError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$errorMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;//Preparing post parameters&lt;/span&gt;
        &lt;span class="nv"&gt;$postData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'username'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;SMS_USERNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;SMS_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'message'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'sender'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;SMS_SENDER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'mobiles'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$phone_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'response'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;RESPONSE_TYPE&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http://portal.bulksmsnigeria.net/api/"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nv"&gt;$ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nb"&gt;curl_setopt_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;CURLOPT_URL&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;CURLOPT_RETURNTRANSFER&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;CURLOPT_POST&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;CURLOPT_POSTFIELDS&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$postData&lt;/span&gt;
        &lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="c1"&gt;//Ignore SSL certificate verification&lt;/span&gt;
        &lt;span class="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CURLOPT_SSL_VERIFYHOST&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="nb"&gt;curl_setopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CURLOPT_SSL_VERIFYPEER&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="c1"&gt;//get response&lt;/span&gt;
        &lt;span class="nv"&gt;$output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;//Print error if any&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;curl_errno&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$isError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nv"&gt;$errorMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;curl_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nb"&gt;curl_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ch&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="nv"&gt;$isError&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'error'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'message'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$errorMessage&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="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'error'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;initiateSmsGuzzle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$phone_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'http://portal.bulksmsnigeria.net/api/?'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'verify'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'form_params'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s1"&gt;'username'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;SMS_USERNAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;SMS_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'message'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'sender'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;SMS_SENDER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'mobiles'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$phone_number&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="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getBody&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What I have done here is to create a function that will accept the user’s phone number and send SMS, but before we can use this, you will need to create an account on &lt;a href="https://www.bulksmsnigeria.net/"&gt;https://www.bulksmsnigeria.net/&lt;/a&gt; if don’t have one already. Once you are set, proceed and recharge your account.&lt;/p&gt;

&lt;p&gt;Don’t forget to use your credentials here&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private $SMS_USERNAME = 'Your username';
private $SMS_PASSWORD = 'Your password';
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What I have also done here is to add two separate functions,&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public function initiateSmsActivation($phone_number, $message){
    $isError = 0;
    $errorMessage = true;

    //Preparing post parameters
    $postData = array(
        'username' =&amp;gt; $this-&amp;gt;SMS_USERNAME,
        'password' =&amp;gt; $this-&amp;gt;SMS_PASSWORD,
        'message' =&amp;gt; $message,
        'sender' =&amp;gt; $this-&amp;gt;SMS_SENDER,
        'mobiles' =&amp;gt; $phone_number,
        'response' =&amp;gt; $this-&amp;gt;RESPONSE_TYPE
    );

    $url = "http://portal.bulksmsnigeria.net/api/";

    $ch = curl_init();
    curl_setopt_array($ch, array(
        CURLOPT_URL =&amp;gt; $url,
        CURLOPT_RETURNTRANSFER =&amp;gt; true,
        CURLOPT_POST =&amp;gt; true,
        CURLOPT_POSTFIELDS =&amp;gt; $postData
    ));

    //Ignore SSL certificate verification
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

    //get response
    $output = curl_exec($ch);

    //Print error if any
    if (curl_errno($ch)) {
        $isError = true;
        $errorMessage = curl_error($ch);
    }
    curl_close($ch);

    if($isError){
        return array('error' =&amp;gt; 1 , 'message' =&amp;gt; $errorMessage);
    }else{
        return array('error' =&amp;gt; 0 );
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public function initiateSmsGuzzle($phone_number, $message)
{
    $client = new Client();

    $response = $client-&amp;gt;post('http://portal.bulksmsnigeria.net/api/?', [
        'verify' =&amp;gt; false,
        'form_params' =&amp;gt; [
            'username' =&amp;gt; $this-&amp;gt;SMS_USERNAME,
            'password' =&amp;gt; $this-&amp;gt;SMS_PASSWORD,
            'message' =&amp;gt; $message,
            'sender' =&amp;gt; $this-&amp;gt;SMS_SENDER,
            'mobiles' =&amp;gt; $phone_number,
        ],
    ]);

    $response = json_decode($response-&amp;gt;getBody(), true);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can use the first one if you prefer to use &lt;a href="http://php.net/manual/en/book.curl.php"&gt;cURL&lt;/a&gt;, while the second one is to make API calls using &lt;a href="http://docs.guzzlephp.org/en/stable/"&gt;guzzleClient&lt;/a&gt; (you will have to install guzzle client in order to be able to use it ).&lt;/p&gt;

&lt;p&gt;Now open &lt;code&gt;_send_-_sms_/_routes_/_web_._php&lt;/code&gt;_ and add a route as shown below : -&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="cm"&gt;/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/&lt;/span&gt;

&lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'welcome'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/send-sms'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
   &lt;span class="s1"&gt;'uses'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'SmsController@getUserNumber'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="s1"&gt;'as'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'sendSms'&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Lastly, to add our view and style the page appropriately. Locate &lt;code&gt;**_send-sms/resources/views&lt;/code&gt;_** folder and clear the default html files, then replace it with this:-&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"{{ config('app.locale') }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"X-UA-Compatible"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"IE=edge"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Latest compiled and minified CSS --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"&lt;/span&gt; &lt;span class="na"&gt;integrity=&lt;/span&gt;&lt;span class="s"&gt;"sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"&lt;/span&gt; &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{{ asset('css/style.css') }}"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- CSRF Token --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"csrf-token"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"{{ csrf_token() }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;SEND SMS&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"homepage"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar navbar-inverse navbar-fixed-top"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar-header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar-toggle collapsed"&lt;/span&gt; &lt;span class="na"&gt;data-toggle=&lt;/span&gt;&lt;span class="s"&gt;"collapse"&lt;/span&gt; &lt;span class="na"&gt;data-target=&lt;/span&gt;&lt;span class="s"&gt;"#navbar"&lt;/span&gt; &lt;span class="na"&gt;aria-expanded=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="na"&gt;aria-controls=&lt;/span&gt;&lt;span class="s"&gt;"navbar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sr-only"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Toggle navigation&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"icon-bar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"icon-bar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"icon-bar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar-brand"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;SEND SMS&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"navbar"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"collapse navbar-collapse"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"nav navbar-nav"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"active"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{{ url('/') }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!--/.nav-collapse --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"row"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col-md-4 col-md-offset-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"panel panel-default"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

                    @if(session()-&amp;gt;has('message'))
                        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"alert alert-success"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                            {{ session()-&amp;gt;get('message') }}
                        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                    @endif

                    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"panel-heading"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;h3&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"panel-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Welcome to my site&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"panel-body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"myForm"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"{{ route('sendSms') }}"&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"form"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                            {{csrf_field()}}
                            &lt;span class="nt"&gt;&amp;lt;fieldset&amp;gt;&lt;/span&gt;
                                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-group"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                                    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"form-control"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Your Phone Number"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"phone_number"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt; &lt;span class="na"&gt;autofocus&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                                &lt;span class="c"&gt;&amp;lt;!-- Change this to a button or input when using this as a form --&amp;gt;&lt;/span&gt;
                                &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"submitBtn"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn btn-success btn-block"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Send Message&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;/fieldset&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!-- /.container --&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Latest compiled and minified JavaScript --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"&lt;/span&gt; &lt;span class="na"&gt;integrity=&lt;/span&gt;&lt;span class="s"&gt;"sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"&lt;/span&gt; &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'#myForm'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'#submitBtn'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Sending...'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For styling:-&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* send-sms/public/css/style.css */
#homepage {
    margin-top: 100px;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Your page should look like this now:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X3te42b5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AJPwYoBuOrG8X-gZ_bsbUwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X3te42b5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AJPwYoBuOrG8X-gZ_bsbUwg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can try to send SMS to your own phone number or anyone.&lt;/p&gt;

&lt;p&gt;You could also check this out on G&lt;a href="https://github.com/yemiwebby/sendSms-laravel"&gt;ithub&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;CONCLUSION&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;I believe this tutorial has shown you a very simple way of sending SMS from your Laravel application without much hassle. Needless to say this, the same process can be followed to implement sending of SMS using any other sms API.&lt;/p&gt;

&lt;p&gt;Moving forwards, you can create a separate class for sending SMS as you might need to use this within any of your controller.&lt;/p&gt;

&lt;p&gt;Furthermore, you can build on this and improve the structure as you deem fit. If you have found this useful, kindly show some love, share with others and post your comments below. Happy coding!!!!&lt;/p&gt;





</description>
      <category>php</category>
      <category>webdev</category>
      <category>laravel5</category>
      <category>sms</category>
    </item>
  </channel>
</rss>
