<?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>Forem: Nacho Iacovino ⚡</title>
    <description>The latest articles on Forem by Nacho Iacovino ⚡ (@nacho).</description>
    <link>https://forem.com/nacho</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%2F551431%2Ffe81e77c-d0f2-4d0e-8a98-45bf7788362d.jpg</url>
      <title>Forem: Nacho Iacovino ⚡</title>
      <link>https://forem.com/nacho</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nacho"/>
    <language>en</language>
    <item>
      <title>Add a connect wallet button to your website</title>
      <dc:creator>Nacho Iacovino ⚡</dc:creator>
      <pubDate>Mon, 21 Mar 2022 15:28:18 +0000</pubDate>
      <link>https://forem.com/thirdweb/add-a-connect-wallet-button-to-your-website-5ggb</link>
      <guid>https://forem.com/thirdweb/add-a-connect-wallet-button-to-your-website-5ggb</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Setting up web3 on your website and letting your users connect their wallet is essential for any web3 web app, and yet the process of integrating these features is often complex and nuanced. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://thirdweb.com?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=add_connect_wallet"&gt;thirdweb&lt;/a&gt; is a platform that lets you deploy smart contracts without having to know Solidity, you can do it by using TypeScript, Python or Go or even without writing any code.&lt;/p&gt;

&lt;p&gt;Instead of spending time trying to configure a complex web3 setup, you can use the &lt;strong&gt;thirdweb React library&lt;/strong&gt; to easily add web3 to your applications.&lt;/p&gt;

&lt;p&gt;You can check the full code for this guide in this &lt;a href="https://github.com/thirdweb-dev/examples/tree/main/typescript/add-connect-wallet"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Check out the full docs for our React package &lt;a href="https://docs.thirdweb.com/react?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=add_connect_wallet"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;p&gt;To get started with the Thirdweb Component Library, you can run the following to install our packages:&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="c"&gt;# Run this to install with npm&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; @thirdweb-dev/react @thirdweb-dev/sdk ethers

&lt;span class="c"&gt;# Or run this to install with yarn&lt;/span&gt;
yarn add @thirdweb-dev/react @thirdweb-dev/sdk ethers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you've installed the necessary package, you just need to setup the &lt;code&gt;ThirdwebProvider&lt;/code&gt; that provides all the context consumed by your app. With this context, you will have a standard web3 provider that you can use throughout your app.&lt;/p&gt;

&lt;p&gt;Setting up this context is as easy as wrapping your app with the following setup, on the &lt;code&gt;pages/_app.tsx&lt;/code&gt; file:&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="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppProps&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;next/app&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;ThirdwebProvider&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;@thirdweb-dev/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageProps&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;AppProps&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;desiredChainId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80001&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * Make sure that your app is wrapped with these contexts.
   * If you're using React, you'll have to replace the Component setup with {children}
   */&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ThirdwebProvider&lt;/span&gt; &lt;span class="na"&gt;desiredChainId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;desiredChainId&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;Component&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&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;ThirdwebProvider&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;MyApp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Connect Wallet &amp;amp; Web3 Setup
&lt;/h2&gt;

&lt;p&gt;Currently, we provide you with hooks to easily integrate web3 into your app and setup an app wide context without having to deal with the complexity of lower level web3 configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using custom hooks
&lt;/h3&gt;

&lt;p&gt;If you want to create your own custom component instead of using ours, you can build it with our &lt;code&gt;useWeb3&lt;/code&gt; and &lt;code&gt;useSwitchNetwork&lt;/code&gt; hooks. On the &lt;code&gt;components/ConnectWallet.js&lt;/code&gt; file:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;useMetamask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useWalletConnect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useCoinbaseWallet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useNetwork&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useDisconnect&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="s1"&gt;@thirdweb-dev/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ConnectWallet&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="nx"&gt;connectWithCoinbaseWallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useCoinbaseWallet&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;connectWithMetamask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMetamask&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;connectWithWalletConnect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useWalletConnect&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;disconnectWallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useDisconnect&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;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useAddress&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;network&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useNetwork&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// If a wallet is connected, show address, chainId and disconnect button&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;address&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="p"&gt;&amp;gt;&lt;/span&gt;
        Address: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;address&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;br&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        Chain ID: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;network&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;network&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;disconnectWallet&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Disconnect&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// If no wallet is connected, show connect wallet options&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;connectWithCoinbaseWallet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Connect Coinbase Wallet
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;connectWithMetamask&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Connect MetaMask&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;connectWithWalletConnect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Connect WalletConnect
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we need to import this component on our &lt;code&gt;index.tsx&lt;/code&gt; 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 type { NextPage } from 'next'
import { ConnectWallet } from '../components/ConnectWallet';

const Home: NextPage = () =&amp;gt; {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;ConnectWallet /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default Home
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The code
&lt;/h3&gt;

&lt;p&gt;Remember, you can check the full code for this example in this &lt;a href="https://github.com/thirdweb-dev/examples/tree/main/typescript/add-connect-wallet"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;This article was originally posted on &lt;a href="https://portal.thirdweb.com/guides/add-connectwallet-to-your-website?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=add_connect_wallet"&gt;thirdweb.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>thirdweb</category>
      <category>connectwallet</category>
      <category>react</category>
    </item>
    <item>
      <title>Top 10 Best Free Icon Packs for Developers and Designers</title>
      <dc:creator>Nacho Iacovino ⚡</dc:creator>
      <pubDate>Fri, 20 Aug 2021 10:29:42 +0000</pubDate>
      <link>https://forem.com/nacho/top-10-best-free-icon-packs-for-developers-and-designers-4ajb</link>
      <guid>https://forem.com/nacho/top-10-best-free-icon-packs-for-developers-and-designers-4ajb</guid>
      <description>&lt;p&gt;&lt;strong&gt;Icons&lt;/strong&gt; are an essential part of any website, you'll need them to illustrate your point better, give more personality to your app or make it easy to navigate your website, especially on mobile devices when some words might be too long and an icon fits much better.&lt;/p&gt;

&lt;p&gt;In this article, I compiled what I considered the &lt;strong&gt;10 best free icon packs&lt;/strong&gt;, for both developers and designers to use, some of them have options to import to different formats, like &lt;em&gt;png&lt;/em&gt; or &lt;em&gt;svg&lt;/em&gt;, and some of them you can install them and import them directly into your projects, which makes them much more convenient if you are working with a framework like &lt;strong&gt;React&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's begin!&lt;/p&gt;

&lt;h2&gt;
  
  
  Heroicons
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629454936386%2FxQMyhPAvX8.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.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629454936386%2FxQMyhPAvX8.jpeg" alt="heroicons.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Made by the team behind &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt;, and more specifically by &lt;a href="https://twitter.com/steveschoger" rel="noopener noreferrer"&gt;Steve Schoger&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Export to SVG/JSX.&lt;/li&gt;
&lt;li&gt;Outline/Solid versions available.&lt;/li&gt;
&lt;li&gt;Very modern designs.&lt;/li&gt;
&lt;li&gt;React and Vue library available for easy imports.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No social icons.&lt;/li&gt;
&lt;li&gt;Only 230 icons total.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Check Heroicons &lt;a href="https://heroicons.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple Icons
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629454957118%2FFUutA-v0tI.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629454957118%2FFUutA-v0tI.png" alt="simple-icons.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thousands of free SVG icons for popular brands (and not so popular). If you need an icon for any brand or service, this is the place to go, they are really easy to use, they have packages for many different frameworks and languages and one distintive thing they do is that they give you the main brand color of the icon.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Export to SVG/PDF.&lt;/li&gt;
&lt;li&gt;Brand color of the icon.&lt;/li&gt;
&lt;li&gt;Use by CDN, NPM package, or Framework/Language-specific packages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only con is that it's so good that I wish that it had common icons so I wouldn't need to use anything else.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Check Simple Icons &lt;a href="https://simpleicons.org/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bootstrap Icons
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629454967233%2FUIqsKGXXx.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629454967233%2FUIqsKGXXx.png" alt="bootstrap-icons.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Built by &lt;a href="https://twitter.com/" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, one of the most extensive packs with over 1300 icons, they have a real personality that you might or might not like, but the collection is very complete.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Export to SVG or use as a font.&lt;/li&gt;
&lt;li&gt;Outline/Solid versions available.&lt;/li&gt;
&lt;li&gt;NPM package available.&lt;/li&gt;
&lt;li&gt;Main social icons available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No React or Vue library.&lt;/li&gt;
&lt;li&gt;Some social icons missing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Check Bootstrap Icons &lt;a href="https://icons.getbootstrap.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ionicons
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629454976178%2FVzTMnd9YV.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629454976178%2FVzTMnd9YV.png" alt="ionicons.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Built by the team behind &lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic&lt;/a&gt;, it's an icon pack designed for mobile devices and apps, it's probably what you want to use in an Ionic application, but you can also export to SVG to use it in any project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Export to SVG.&lt;/li&gt;
&lt;li&gt;Outline/Solid/Sharp versions available.&lt;/li&gt;
&lt;li&gt;Main social icons available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small collection.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Check Ionicons &lt;a href="https://ionic.io/ionicons" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Octicons
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629454986387%2FeHXLgO8V7.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629454986387%2FeHXLgO8V7.png" alt="octicons.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Built by &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, used to emphasize meaning, not replace entire words (no menu icon for example). The biggest advantage of this one is the many different packages that they offer for Ruby, Rails, Jekyll, JavaScript and React.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Export to SVG/PDF.&lt;/li&gt;
&lt;li&gt;Good documentation with UI examples on how to use.&lt;/li&gt;
&lt;li&gt;Many different packages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Outline/Solid versions only for some icons.&lt;/li&gt;
&lt;li&gt;Small collection.&lt;/li&gt;
&lt;li&gt;No social icons.&lt;/li&gt;
&lt;li&gt;Some common icons like hamburger menu are missing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Check Octicons &lt;a href="https://octicons-primer.vercel.app/octicons/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ant Design Icons
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629454993680%2FRR5-QdIIW.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629454993680%2FRR5-QdIIW.png" alt="ant-design-icons.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Built for React, no export to SVG available, the only way to use them is to install the package and import them into your project. It also offers a Two-Tone version of the icons, which is rare and it looks great.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Outline/Filled/Two-tone versions available.&lt;/li&gt;
&lt;li&gt;Really easy to add custom icons with their &lt;code&gt;&amp;lt;Icon /&amp;gt;&lt;/code&gt; component.&lt;/li&gt;
&lt;li&gt;Some attributes available like rotate/spin to customize your icons or create loading icons.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only available for React.&lt;/li&gt;
&lt;li&gt;Small collection.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Check Ant Design Icons &lt;a href="https://ant.design/components/icon/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Feather Icons
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629455003167%2F5N_x-bs1q.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629455003167%2F5N_x-bs1q.png" alt="feather-icons.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Built by &lt;a href="https://twitter.com/colebemis" rel="noopener noreferrer"&gt;Cole Bemis&lt;/a&gt;, my favorite part is that you can customize the size, the stroke width, and the color before exporting the icon as SVG.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy customization.&lt;/li&gt;
&lt;li&gt;Export to SVG.&lt;/li&gt;
&lt;li&gt;Main social icons.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only 286 icons available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Check Feather Icons &lt;a href="https://feathericons.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Material Design Icons
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629455009993%2FWjA_sIv3y.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629455009993%2FWjA_sIv3y.png" alt="material-design-icons.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also called Google Fonts Icons, it's built by Google. This one is really complete, with a lot of icons, you can customize the density, the size, and the color directly on the page. You can use it as an Icon font too, and if you are using Angular, it's the best choice by far. It also has easy instructions on how to use the icons in Android, iOS, and Flutter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy customization.&lt;/li&gt;
&lt;li&gt;Export to SVG/PNG or use it as a font.&lt;/li&gt;
&lt;li&gt;Big collection.&lt;/li&gt;
&lt;li&gt;Outlined, Filled, Rounded, Sharp, and Two-tone versions available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No social icons.&lt;/li&gt;
&lt;li&gt;Color customization is only black/white.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Check Material Design Icons &lt;a href="https://fonts.google.com/icons?selected=Material+Icons" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Entypo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629455019397%2FmL8Vr_2lq.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629455019397%2FmL8Vr_2lq.png" alt="entypo-icons.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Built by &lt;a href="https://twitter.com/danielbruce_" rel="noopener noreferrer"&gt;Daniel Bruce&lt;/a&gt;, more than 400 icons. More of an enterprise look than a modern look, but sometimes that's exactly what you need!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple designs.&lt;/li&gt;
&lt;li&gt;A lot of personality.&lt;/li&gt;
&lt;li&gt;React library available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not many icons.&lt;/li&gt;
&lt;li&gt;It hasn't been updated in a bit, some social icons are outdated.&lt;/li&gt;
&lt;li&gt;No button to export to SVG, you have to right-click and save it yourself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Check Entypo &lt;a href="http://www.entypo.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Fontisto
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629455028985%2F6qbTasWzF.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1629455028985%2F6qbTasWzF.png" alt="fontisto.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you were looking for Font Awesome on this list, you are not going to find it, Fontisto is just a superior version. It's CSS-based, it offers an npm package to install it. It offers a lot of customization, you can add borders or background to your icons, animate them, flip them or rotate them. Super easy to create loading icons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CSS-based.&lt;/li&gt;
&lt;li&gt;Easy customization.&lt;/li&gt;
&lt;li&gt;Very good loading icons.&lt;/li&gt;
&lt;li&gt;Main social icons available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No SVG export.&lt;/li&gt;
&lt;li&gt;A little harder to implement than other solutions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Check Fontisto &lt;a href="https://www.fontisto.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;You reached the end of the article! This article was inspired by a Twitter Thread I created some months ago, you can check it out &lt;a href="https://twitter.com/nachoiacovino/status/1367903586395578377" rel="noopener noreferrer"&gt;here&lt;/a&gt;. I post daily content on Twitter so if you have enjoyed this, consider following me &lt;a href="https://twitter.com/nachoiacovino" rel="noopener noreferrer"&gt;@nachoiacovino&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have any suggestions to improve this list, don't hesitate to contact me on Twitter, I'll be happy to improve this list over time.&lt;/p&gt;

&lt;p&gt;See you on the next one!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on my personal blog, &lt;a href="https://nachoiacovino.com/blog/top-10-best-free-icon-packs-for-developers-and-designers?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=icon_packs" rel="noopener noreferrer"&gt;nachoiacovino.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>resources</category>
      <category>react</category>
      <category>design</category>
      <category>icons</category>
    </item>
    <item>
      <title>How to Setup Tailwind CSS in your Vanilla HTML Project</title>
      <dc:creator>Nacho Iacovino ⚡</dc:creator>
      <pubDate>Tue, 10 Aug 2021 11:45:55 +0000</pubDate>
      <link>https://forem.com/nacho/how-to-setup-tailwind-css-in-your-vanilla-html-project-47d8</link>
      <guid>https://forem.com/nacho/how-to-setup-tailwind-css-in-your-vanilla-html-project-47d8</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this tutorial, I'm gonna explain how to setup Tailwind in the easiest way possible into your static HTML project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Required tools
&lt;/h2&gt;

&lt;p&gt;We are gonna need Node.js for this tutorial, if you don't have it, you can download it &lt;a href="https://nodejs.org/en/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You should get the "Recommended" version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Create a folder for your project, open a terminal inside and do&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; tailwindcss autoprefixer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, you initialize a new node project (the -y flag is to say yes to all prompts automatically) and install the required dependencies, in this case, Tailwind CSS and Autoprefixer, which is a dependency of Tailwind itself.&lt;/p&gt;

&lt;p&gt;After that, we're gonna create a new folder called &lt;code&gt;src&lt;/code&gt; and add a new file called &lt;code&gt;tailwind.css&lt;/code&gt; inside of it.&lt;/p&gt;

&lt;p&gt;Then, we'll add these three lines to the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we need to add a couple of scripts to our &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;dev&lt;/code&gt; and &lt;code&gt;build&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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;tailwind-css-in-vanilla-html&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;version&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;1.0.0&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;description&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="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&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;index.js&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;scripts&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev&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;tailwindcss build -i ./src/tailwind.css -o ./public/tailwind.css&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;build&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;NODE_ENV=production npm run dev&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;test&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;echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1&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;keywords&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;author&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="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;license&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;ISC&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;devDependencies&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;autoprefixer&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;^10.3.1&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;tailwindcss&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;^2.2.7&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;Let's explain what's going on here, in the &lt;code&gt;dev&lt;/code&gt; script, we're calling tailwindcss to build, and we're giving it an input file with -i, the &lt;code&gt;.src/tailwind.css&lt;/code&gt; we just created in the previous step. Then, we're giving it an output file with -o, and that's gonna be &lt;code&gt;.public/tailwind.css&lt;/code&gt;, which would be all Tailwind CSS classes after the build process.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;build&lt;/code&gt; script, we're calling the &lt;code&gt;dev&lt;/code&gt; but with &lt;code&gt;NODE_ENV=production&lt;/code&gt; in front of it, we're gonna use this to create an optimized version of our Tailwind CSS file with only the classes we need for our project.&lt;/p&gt;

&lt;p&gt;We can now run this command to generate the Tailwind CSS file in development mode, which will include all classes that Tailwind has available.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This also creates a &lt;code&gt;public&lt;/code&gt; folder for us. Now let's create an &lt;code&gt;index.html&lt;/code&gt; file inside that same folder.&lt;/p&gt;

&lt;p&gt;Inside, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;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.0"&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;Tailwind CSS in Vanilla HTML!&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;"tailwind.css"&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;class=&lt;/span&gt;&lt;span class="s"&gt;"text-blue-600"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;hello!&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;p&gt;This is a basic HTML structure but take important notice on line 8, where we're linking our &lt;code&gt;tailwind.css&lt;/code&gt; file, it's important to realize this file is the one inside &lt;code&gt;public&lt;/code&gt;, and not the one inside &lt;code&gt;src&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So we can customize Tailwind a little bit better, we need to create a &lt;code&gt;tailwind.config.js&lt;/code&gt;, we can do it automatically with this command:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;And then, to know exactly which files Tailwind need to look at to create an optimized version of the output in the build process, we need to tell it where to look. Go to &lt;code&gt;tailwind.config.js&lt;/code&gt; and modify the &lt;code&gt;purge&lt;/code&gt; line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;purge&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="s1"&gt;./public/**/*.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;darkMode&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="c1"&gt;// or 'media' or 'class'&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And with this, you're set! You have successfully setup Tailwind CSS in your project and you're ready to create your amazing app.&lt;/p&gt;

&lt;p&gt;If you have enjoyed this tutorial and you would like to learn more, I'm creating a Tailwind CSS course called Windcourse, in which I have a video of this exact process and I'll be also going deep into how to use Tailwind with React and Next.js.&lt;/p&gt;

&lt;p&gt;If you are interested, &lt;a href="https://app.slip.so/presale/windcourse"&gt;you can pre-order it here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Feel free to follow me on Twitter for daily tech-related content &lt;a href="https://twitter.com/nachoiacovino"&gt;@nachoiacovino&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was originally published in my blog,  &lt;a href="https://nachoiacovino.com/blog/how-to-setup-tailwind-css-in-a-vanilla-html-project?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=tailwind_vanilla"&gt;nachoiacovino.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>html</category>
      <category>tailwindcss</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Create a Next.js app with authentication in 5 minutes</title>
      <dc:creator>Nacho Iacovino ⚡</dc:creator>
      <pubDate>Thu, 10 Jun 2021 16:37:20 +0000</pubDate>
      <link>https://forem.com/clerk/create-a-next-js-app-with-authentication-in-5-minutes-3nn8</link>
      <guid>https://forem.com/clerk/create-a-next-js-app-with-authentication-in-5-minutes-3nn8</guid>
      <description>&lt;p&gt;Hi! My name is Nacho Iacovino (&lt;a href="https://twitter.com/nachoiacovino" rel="noopener noreferrer"&gt;@nachoiacovino&lt;/a&gt;), and I'm the Developer Advocate at Clerk. In this guide, I will teach you how to deploy Clerk using Vercel. This is the fastest and easiest way to set up a new application, complete with all the auth features provided by Clerk. In just a few minutes, you’ll create an app, deploy it, and set up your local environment.&lt;/p&gt;

&lt;p&gt;If you prefer to follow this tutorial on video, you can watch it &lt;a href="https://www.youtube.com/watch?v=6kXKaQVv-k4" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;

&lt;p&gt;To get started, go to  &lt;a href="https://www.clerk.dev/?utm_source=blog&amp;amp;utm_medium=devto&amp;amp;utm_campaign=nextjs_oneclick" rel="noopener noreferrer"&gt;clerk.dev&lt;/a&gt;  and sign into your account. If you don’t have an account yet, click “Get started for free” and create an account.&lt;/p&gt;

&lt;p&gt;Once signed in, you’ll land your Applications page. Let's click &lt;strong&gt;Create application&lt;/strong&gt; to create a new 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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341677820%2F2ZC3MEyzP.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341677820%2F2ZC3MEyzP.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When prompted, choose &lt;strong&gt;Quick start with Next.js and Vercel&lt;/strong&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341709968%2Fw2inKkk5eR.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341709968%2Fw2inKkk5eR.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be directed to Vercel. Sign into your Vercel account, or create an account if you don’t have one. Choose a project name then click &lt;strong&gt;Continue&lt;/strong&gt; to import the clerk-nextjs-starter repository.&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341719623%2FOSRY2Oed6.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341719623%2FOSRY2Oed6.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Clerk
&lt;/h2&gt;

&lt;p&gt;Next, let's install the Clerk integration to connect Clerk to Vercel. When prompted, click &lt;strong&gt;Install&lt;/strong&gt;. A new window will pop up. Follow the instructions to create a new Clerk application to connect to this Vercel project. Choose an application name and a brand color for your app. By default, the Clerk application name is the same as the Vercel project.&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341739812%2FFNpQ-0Eij.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341739812%2FFNpQ-0Eij.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, you will create a Git repository for your project. You can choose to use GitHub, GitLab, or BitBucket. For this tutorial, we'll use GitHub. Choose a repository name and click &lt;strong&gt;Continue&lt;/strong&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623342070990%2FfkKAuvumj.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623342070990%2FfkKAuvumj.png" alt="image (2).png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy the project
&lt;/h2&gt;

&lt;p&gt;On the Import Project screen, Clerk sets the necessary environment variables for you, so you don't have to do anything. Simply click &lt;strong&gt;Deploy&lt;/strong&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341770947%2FTbeSAmgd_.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341770947%2FTbeSAmgd_.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vercel will create and deploy the new Git repository. This step may take a few minutes. After the process is complete, you should see a congratulatory screen.&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341849421%2FeqGWyI1Yv.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341849421%2FeqGWyI1Yv.png" alt="image (1).png"&gt;&lt;/a&gt;&lt;br&gt;
You can visit your deployed application by clicking Visit. You can see mine  &lt;a href="https://clerk-nextjs-vercel.vercel.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt;!&lt;/p&gt;
&lt;h2&gt;
  
  
  Clone the project locally
&lt;/h2&gt;

&lt;p&gt;The next step is to clone the newly-deployed repository to your local machine. Go to your Git provider, open the repository, and find the URL to clone the repository.&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341893831%2FPbh1OVvd0.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341893831%2FPbh1OVvd0.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open your local machine’s command line interface and navigate to the folder where you want to install your project, then paste the following code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;repo_url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, open the project and run &lt;code&gt;yarn install&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After the installation process completes, run &lt;code&gt;yarn dev&lt;/code&gt;. This is where the magic happens!&lt;/p&gt;

&lt;p&gt;Note: If you haven’t previously used Vercel on your local machine, you’ll have to sign in using a link sent to your email before running &lt;code&gt;yarn dev&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You will be prompted to set up link this local project with the Vercel project. Respond Y to each prompt.&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341933066%2FlgQVNpFYi.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341933066%2FlgQVNpFYi.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And voilà! Your app is now running on  &lt;a href="https://dev.tolocalhost:3000"&gt;localhost:3000&lt;/a&gt; —you can open it and see everything already working. Create an account on your app and take a minute to explore its features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modify settings
&lt;/h2&gt;

&lt;p&gt;Now that your app is up and running, you can configure user management and theme settings provided by Clerk at  &lt;a href="https://dashboard.clerk.dev/?utm_source=blog&amp;amp;utm_medium=devto&amp;amp;utm_campaign=nextjs_oneclick" rel="noopener noreferrer"&gt;https://dashboard.clerk.dev/&lt;/a&gt; . Navigate to your application and choose which instance you would like to work on. Each Clerk project has 3 instances: Development, Staging, and Production. Instances are independent and do not share users or settings between them, so you can try different configurations before pushing them live.&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341986561%2FGOIBQALgM.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341986561%2FGOIBQALgM.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Any changes made will be applied to your project without the need to modify code or re-deploy.&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341994888%2FDOn7i6o6z.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623341994888%2FDOn7i6o6z.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try different configurations and find what works best for your application!&lt;/p&gt;

&lt;p&gt;You can also modify theme settings to match the look and feel of Clerk components with the rest of your app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623342001665%2F9BEnm6s-A.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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1623342001665%2F9BEnm6s-A.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it! You just created a new application, deployed it with Vercel, and set up your local environment. No need to mess with complex backend configurations or worry about painful security customizations.&lt;/p&gt;

&lt;p&gt;If you run into any problems, don't hesitate to contact me! I’m here to help. Check out my profile on Twitter and DM me at  &lt;a href="https://twitter.com/nachoiacovino" rel="noopener noreferrer"&gt;@nachoiacovino&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;Any feedback is appreciated!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Build a Fullstack to-do app without any backend code</title>
      <dc:creator>Nacho Iacovino ⚡</dc:creator>
      <pubDate>Thu, 03 Jun 2021 12:06:55 +0000</pubDate>
      <link>https://forem.com/nacho/build-a-to-do-app-with-clerk-and-hasura-and-no-backend-code-2mde</link>
      <guid>https://forem.com/nacho/build-a-to-do-app-with-clerk-and-hasura-and-no-backend-code-2mde</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;While traditional applications require both frontend and backend developers, new technologies like Clerk and Hasura are making it possible to build robust backends without writing backend code.&lt;/p&gt;

&lt;p&gt;In this tutorial, we'll leverage these new technologies to build a simple to-do list application without writing any backend code. The primary tools we'll use are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://hasura.io/cloud/" rel="noopener noreferrer"&gt;Hasura Cloud&lt;/a&gt;, for creating a frontend-accessible GraphQL API&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.heroku.com/postgres" rel="noopener noreferrer"&gt;Heroku Postgres&lt;/a&gt;, for storing to-do list data&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.clerk.dev/?utm_source=nacho&amp;amp;utm_medium=devto&amp;amp;utm_campaign=heroku_guide" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt;, for authentication&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt;, for frontend development&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt;, for styling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before we get started, you can see the final result here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://clerk-hasura-todos-zeta.vercel.app/" rel="noopener noreferrer"&gt;Demo of the to-do app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nachoiacovino/clerk-hasura-todos" rel="noopener noreferrer"&gt;Completed codebase&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's begin!&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Hasura project
&lt;/h3&gt;

&lt;p&gt;Start by &lt;a href="https://hasura.io/cloud/" rel="noopener noreferrer"&gt;signing up for Hasura Cloud&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you already have a Hasura Cloud account, you will need to manually create a New Project. If this is your first time, a new project will automatically be created for you.&lt;/p&gt;

&lt;p&gt;After your project initializes, you will see something like this (with a different name), go ahead and click the cog wheel to go to the project settings:&lt;/p&gt;

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

&lt;p&gt;From here, you will need our project's GraphQL API URL. Please copy it, you will need it in a second:&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%2Ftsfgga7kwegb50jjaz73.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%2Ftsfgga7kwegb50jjaz73.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy the starter project
&lt;/h3&gt;

&lt;p&gt;We prepared a starter project for this tutorial, the easiest way to get started is with the following "Deploy" button. The button will prompt you through cloning the repo, initializing &lt;a href="https://www.clerk.dev/?utm_source=nacho&amp;amp;utm_medium=devto&amp;amp;utm_campaign=heroku_guide" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt;, and deploying the app live on Vercel. The starter project uses Next.js, Tailwind CSS and &lt;a href="https://www.clerk.dev/?utm_source=nacho&amp;amp;utm_medium=devto&amp;amp;utm_campaign=heroku_guide" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt;. It's already setup with some styles using Next.js and Tailwind CSS but you don't have to be proficient in either of these to follow the tutorial.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Fnachoiacovino%2Fclerk-hasura-todos-starter&amp;amp;integration-ids=oac_7uYNbc9CdDAZmNqbt3LEkO3a&amp;amp;env=NEXT_PUBLIC_HASURA_GRAPHQL_API" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fvercel.com%2Fbutton" alt="Deploy with Vercel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This button will first prompt you to create a Vercel account if you do not have one. When signing up, Vercel may ask you to grant access to all of your repositories or just selected ones - feel free to choose either option.&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%2Fjwgwn0wmbrtdhtzqbrru.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%2Fjwgwn0wmbrtdhtzqbrru.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Next step will prompt you to integrate &lt;a href="https://www.clerk.dev/?utm_source=nacho&amp;amp;utm_medium=devto&amp;amp;utm_campaign=heroku_guide" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt; into your project, click &lt;strong&gt;Install&lt;/strong&gt; and then &lt;strong&gt;Continue&lt;/strong&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%2Fa4824mjn4eft416si4bd.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%2Fa4824mjn4eft416si4bd.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you do not have a &lt;a href="https://www.clerk.dev/?utm_source=nacho&amp;amp;utm_medium=devto&amp;amp;utm_campaign=heroku_guide" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt; account already, you will be asked to create one now.&lt;/p&gt;

&lt;p&gt;Next, you will be asked to select an application name and a brand color. Then, click &lt;strong&gt;"Create application"&lt;/strong&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%2F3xexiyi90suhlzzt60e4.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%2F3xexiyi90suhlzzt60e4.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the window closes, click Continue and you will be prompted to pick a Git provider. In this tutorial, we will use &lt;strong&gt;GitHub&lt;/strong&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%2F7aeg5216pnqnh8vpdj1c.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%2F7aeg5216pnqnh8vpdj1c.png" alt="image"&gt;&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%2Fspqqt5zx3txqu8h0dgcj.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%2Fspqqt5zx3txqu8h0dgcj.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is where you will use Hasura Cloud's &lt;strong&gt;GraphQL API URL&lt;/strong&gt; you copied earlier. Add it below and click &lt;strong&gt;Deploy&lt;/strong&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%2Fzrp4tr9akgdewsa7e9p4.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%2Fzrp4tr9akgdewsa7e9p4.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While you wait for Vercel to deploy our project, you can move to GitHub, where Vercel has created a new repository on your behalf. Go ahead and clone it locally.&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%2Fosgzg325edy4gs4lud4g.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%2Fosgzg325edy4gs4lud4g.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To clone, go to your desired folder, open a terminal and paste:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;repository-url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, go inside the project folder and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn
// or
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install the necessary dependencies.&lt;/p&gt;

&lt;p&gt;After this, go ahead and launch your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn dev
// or
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you haven’t previously used Vercel on your computer, you will be asked to sign in when you launch the project.&lt;/p&gt;

&lt;p&gt;You will be prompted to set up link this local project with the Vercel project. Respond &lt;strong&gt;Y&lt;/strong&gt; to each prompt.&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%2Fcdelegv7sobwzgai9fpr.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%2Fcdelegv7sobwzgai9fpr.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, you will see your project running on &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  File structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;├── components
│   ├── AddTodo.js &lt;span class="o"&gt;(&lt;/span&gt;Form to Add todo&lt;span class="o"&gt;)&lt;/span&gt;
│   ├── Header.js &lt;span class="o"&gt;(&lt;/span&gt;Header of our app with UserButton&lt;span class="o"&gt;)&lt;/span&gt;
│   ├── Layout.js
│   ├── SingleTodo.js &lt;span class="o"&gt;(&lt;/span&gt;One todo with toggle/delete methods&lt;span class="o"&gt;)&lt;/span&gt;
│   └── TodoList.js &lt;span class="o"&gt;(&lt;/span&gt;List to render all todos with get method&lt;span class="o"&gt;)&lt;/span&gt;
├── lib
│   └── apolloClient.js &lt;span class="o"&gt;(&lt;/span&gt;Apollo configuration wrapper&lt;span class="o"&gt;)&lt;/span&gt;
├── pages
│   ├── sign-in &lt;span class="o"&gt;(&lt;/span&gt;Clerk-powered sign &lt;span class="k"&gt;in &lt;/span&gt;page&lt;span class="o"&gt;)&lt;/span&gt;
│   │   └── &lt;span class="o"&gt;[[&lt;/span&gt;...index]].js
│   ├── sign-up &lt;span class="o"&gt;(&lt;/span&gt;Clerk-powered sign up page&lt;span class="o"&gt;)&lt;/span&gt;
│   │   └── &lt;span class="o"&gt;[[&lt;/span&gt;...index]].js
│   ├── user &lt;span class="o"&gt;(&lt;/span&gt;Clerk-powered user profile page&lt;span class="o"&gt;)&lt;/span&gt;
│   │   └── &lt;span class="o"&gt;[[&lt;/span&gt;...index]].js
│   ├── _app.js &lt;span class="o"&gt;(&lt;/span&gt;where Clerk is configured&lt;span class="o"&gt;)&lt;/span&gt;
│   ├── index.js &lt;span class="o"&gt;(&lt;/span&gt;first page you see&lt;span class="o"&gt;)&lt;/span&gt;
│   └── todos.js &lt;span class="o"&gt;(&lt;/span&gt;page we will work on&lt;span class="o"&gt;)&lt;/span&gt;
├── public &lt;span class="o"&gt;(&lt;/span&gt;images&lt;span class="o"&gt;)&lt;/span&gt;
├── styles &lt;span class="o"&gt;(&lt;/span&gt;all css styles &lt;span class="k"&gt;for &lt;/span&gt;our app&lt;span class="o"&gt;)&lt;/span&gt;
│   ├── globals.css
│   ├── Header.module.css
│   └── Home.module.css
├── .env.local &lt;span class="o"&gt;(&lt;/span&gt;environmental variables pulled from Vercel&lt;span class="o"&gt;)&lt;/span&gt;
├── postcss.config.js &lt;span class="o"&gt;(&lt;/span&gt;postcss config, needed &lt;span class="k"&gt;for &lt;/span&gt;Tailwind&lt;span class="o"&gt;)&lt;/span&gt;
├── package.json &lt;span class="o"&gt;(&lt;/span&gt;where your packages live&lt;span class="o"&gt;)&lt;/span&gt;
├── README.md
├── tailwind.config.js
└── yarn.lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Activate Hasura integration
&lt;/h3&gt;

&lt;p&gt;Hasura is one of the integrations that &lt;a href="https://www.clerk.dev/?utm_source=nacho&amp;amp;utm_medium=devto&amp;amp;utm_campaign=heroku_guide" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt; offers, with many more coming the future. To use it, you need to enable it. Go to your &lt;a href="https://dashboard.clerk.dev/applications?utm_source=nacho&amp;amp;utm_medium=devto&amp;amp;utm_campaign=heroku_guide" rel="noopener noreferrer"&gt;Clerk Dashboard&lt;/a&gt;, click on your application -&amp;gt; Development -&amp;gt; Integrations and activate Hasura.&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%2Fw2hwnfxyfxfekq694fxi.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%2Fw2hwnfxyfxfekq694fxi.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before leaving the dashboard, go to Home and copy your Frontend API, you'll need to to create the link between &lt;a href="https://www.clerk.dev/?utm_source=nacho&amp;amp;utm_medium=devto&amp;amp;utm_campaign=heroku_guide" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt; and &lt;a href="https://cloud.hasura.io/" rel="noopener noreferrer"&gt;Hasura&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%2Fse9n6py188njazrlnydy.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%2Fse9n6py188njazrlnydy.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With your project already running, it's time to go back to Hasura and start setting up the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up Hasura Cloud
&lt;/h2&gt;

&lt;p&gt;Go back to Hasura, click the cog wheel, click &lt;strong&gt;"Env vars"&lt;/strong&gt; and then &lt;strong&gt;"New Env Var"&lt;/strong&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%2Fmfcdeilj6q2v9devoq5g.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%2Fmfcdeilj6q2v9devoq5g.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pick HASURA_GRAPHQL_JWT_SECRET from the list and then add this, replacing &lt;strong&gt;%FRONTEND_API%&lt;/strong&gt; with the Frontend API you copied from &lt;a href="https://www.clerk.dev/?utm_source=nacho&amp;amp;utm_medium=devto&amp;amp;utm_campaign=heroku_guide" rel="noopener noreferrer"&gt;Clerk&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;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"jwk_url"&lt;/span&gt;:&lt;span class="s2"&gt;"https://%FRONTEND_API%/v1/.well-known/jwks.json"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Click "Add" and then, click "Launch Console".&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%2Fhaczm6w9a1327279flwx.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%2Fhaczm6w9a1327279flwx.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will bring us to GraphiQL. GraphiQL is the GraphQL integrated development environment (IDE). It's a powerful tool you can use to interact with the API.&lt;/p&gt;

&lt;p&gt;After GraphiQL opens, the first thing you need to do is to create a table. Start by clicking Data on the top navbar:&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%2Fxfrxnb15c24gp7sl5m63.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%2Fxfrxnb15c24gp7sl5m63.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this tutorial, we recommend creating a Heroku database for free:&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%2F2ufp7iygti0vfuscihla.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%2F2ufp7iygti0vfuscihla.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you don't have a Heroku account, now is the time to create one.&lt;/p&gt;

&lt;p&gt;Follow the steps and the database will automatically be created and linked for you.&lt;/p&gt;

&lt;p&gt;After the database is created, click &lt;strong&gt;"Public"&lt;/strong&gt; and then &lt;strong&gt;"Create Table"&lt;/strong&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%2Figln5pmbfndizctepsrv.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%2Figln5pmbfndizctepsrv.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fill the table like this and "Add Table".&lt;/p&gt;

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

&lt;p&gt;This not only creates our table, but also triggers Hasura to create a GraphQL backend.&lt;/p&gt;

&lt;p&gt;After creating the table, the next step is to restrict who can access the data. By default, Hasura is configured for all fields to be public. You need to set permissions and fix that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set table permissions
&lt;/h3&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%2Fccwt1be4fed8vce5x8hc.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%2Fccwt1be4fed8vce5x8hc.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You need to create a new role called "user" and edit each of the four possible permissions they have. If you are familiar with &lt;strong&gt;CRUD&lt;/strong&gt; (Create, Read, Update, Delete), this is basically the same thing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Insert (Create)
&lt;/h3&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%2F3dzxnnsg15jsns5c9szp.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%2F3dzxnnsg15jsns5c9szp.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;Insert&lt;/strong&gt; permissions, choose that the user can only set the &lt;code&gt;title&lt;/code&gt; of a to-do when a new one is created. There others all have default values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt; is autogenerated (set during table creation)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;completed&lt;/code&gt; starts as &lt;code&gt;false&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;created_at&lt;/code&gt; is autogenerated to &lt;code&gt;now()&lt;/code&gt; (set during table creation)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;user_id&lt;/code&gt; is set to the requesting user's ID&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since the &lt;code&gt;user_id&lt;/code&gt; is dependent on the particular request, it must be configured as a "Column preset". Set it to &lt;code&gt;X-Hasura-User-Id&lt;/code&gt; from the "session variable".&lt;/p&gt;

&lt;p&gt;When you use &lt;a href="https://www.clerk.dev/?utm_source=nacho&amp;amp;utm_medium=devto&amp;amp;utm_campaign=heroku_guide" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt;'s Hasura integration, &lt;code&gt;X-Hasura-User-ID&lt;/code&gt; is automatically set in the session variable that gets sent to Hasura. The code to retrieve the session variable and send it to Hasura is in &lt;code&gt;lib/apolloClient.js&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Select (Read)
&lt;/h3&gt;

&lt;p&gt;For &lt;strong&gt;Select&lt;/strong&gt; permissions, you want to configure Hasura so users can only read their own to-dos. You can verify this by "checking" if the to-do's &lt;code&gt;user_id&lt;/code&gt; is the same as the &lt;code&gt;X-Hasura-User-Id&lt;/code&gt; you receive from the session variable.&lt;/p&gt;

&lt;p&gt;If the user ID's match, you can grant read permissions to every column. The exact configuration required is 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%2Fijq5x6yowvywrk8mkr7a.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%2Fijq5x6yowvywrk8mkr7a.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Update
&lt;/h3&gt;

&lt;p&gt;For &lt;strong&gt;Update&lt;/strong&gt; permissions, you want to include the same "check" as &lt;strong&gt;Select&lt;/strong&gt;, to ensure that a user can only update their own to-dos.&lt;/p&gt;

&lt;p&gt;However, if the check is valid, you don't want the user to have permission to update every column. Instead, only grant permission to update the &lt;code&gt;completed&lt;/code&gt; column.&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%2Fcthce9d8lh4d45vw638o.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%2Fcthce9d8lh4d45vw638o.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Delete
&lt;/h3&gt;

&lt;p&gt;For &lt;strong&gt;Delete&lt;/strong&gt; permissions, you want to include the same "check" as &lt;strong&gt;Select&lt;/strong&gt;, to ensure that a user can only delete their own to-dos.&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%2F2woozr3taz2xv0qrvjl5.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%2F2woozr3taz2xv0qrvjl5.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's all of the permissions we need to set! Now, let's work on the frontend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect Hasura to the Frontend
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; and create an account on your app. Then, click &lt;strong&gt;"Start saving your todos"&lt;/strong&gt; and you will see this:&lt;/p&gt;

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

&lt;p&gt;These is sample data and is still static. In the next steps of the tutorial, we will connect this list to Hasura and your database, so users can create and manage their own to-dos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a to-do
&lt;/h3&gt;

&lt;p&gt;The first step is giving users the ability to create a to-do. We will do this from &lt;code&gt;components/AddTodo.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you look at the &lt;code&gt;onSubmit&lt;/code&gt; function, you will see that nothing will currently happen when the user clicks add. You must create a GraphQL "mutation" to update the database when add is clicked.&lt;/p&gt;

&lt;p&gt;Replace the top of your file (everything above the return statement) with this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useMutation&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;@apollo/client&lt;/span&gt;&lt;span class="dl"&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;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ADD_TODO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  mutation AddTodo($title: String!) {
    insert_todos_one(object: { title: $title }) {
      id
      title
    }
  }
`&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;AddTodo&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;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;addTodo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ADD_TODO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;onCompleted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTitle&lt;/span&gt;&lt;span class="p"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;addTodo&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This mutation accepts a title and passes it to the &lt;code&gt;insert_todos_one&lt;/code&gt; method that Hasura has created for us.&lt;/p&gt;

&lt;p&gt;Now, let's go back to our frontend and try adding a todo.&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%2F6s3oe2t4hg8pk2g5rne2.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%2F6s3oe2t4hg8pk2g5rne2.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll see notice that nothing happens on the frontend, and that's expected because we're still reading static to-dos. But, let's check the database to see if the mutation succeeded. Go back to the Hasura Cloud Console, copy and paste the following query and click the play button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GetTodos&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;todos&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;completed&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see your todo was created successfully:&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%2F081ojcd0u65z3kp3vqfb.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%2F081ojcd0u65z3kp3vqfb.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fetch to-dos
&lt;/h3&gt;

&lt;p&gt;Now, we will update the frontend to read the user's to-dos from Hasura. You can do this from &lt;code&gt;components/TodoList.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The file starts by showing static data. Update the component to instead run a GraphQL "query":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useQuery&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;@apollo/client&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;SingleTodo&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/SingleTodo&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GET_TODOS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  query GetTodos {
    todos(order_by: { created_at: desc }) {
      id
      title
      completed
    }
  }
`&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;TodoList&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;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GET_TODOS&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;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Loading...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="si"&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;error&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;/&amp;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;'overflow-hidden bg-white rounded-md shadow'&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;ul&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;'divide-y divide-gray-200'&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;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;todos&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;todo&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;SingleTodo&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;todo&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="na"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&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;ul&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;TodoList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we created a query that gets all to-dos (remember, the user can only see the ones attached to their own &lt;code&gt;user_id&lt;/code&gt;). We set the query to return &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;title&lt;/code&gt;, and &lt;code&gt;completed&lt;/code&gt;. We order the to-dos by &lt;code&gt;created_at&lt;/code&gt; descending, so the newest are first in the list.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useQuery&lt;/code&gt; returns an object so you can render different things depending on if the data is loading, if there's an error, or if the data has been retrieved.&lt;/p&gt;

&lt;p&gt;We've configured an early return while the data is loading or if there's an error, then render the list if that is available. After saving, you should see something like this:&lt;/p&gt;

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

&lt;p&gt;Let's try adding a new todo.&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%2Fu0mzmg5acldghptbbzmn.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%2Fu0mzmg5acldghptbbzmn.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should see that the form clears after clicking "Add", but the list below doesn't automatically update. However, if you manually refresh the page, you will see new to-do.&lt;/p&gt;

&lt;p&gt;That's not the best experience and we will fix this later by implementing a cache, so your can keep your database and your frontend in sync.&lt;/p&gt;

&lt;p&gt;Before that, let's implement toggle and delete mutations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Delete Todo
&lt;/h3&gt;

&lt;p&gt;Open &lt;code&gt;components/SingleTodo.js&lt;/code&gt;, which is the component the renders for each individual to-do.&lt;/p&gt;

&lt;p&gt;Update the code to add a delete mutation when the delete button is clicked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useMutation&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;@apollo/client&lt;/span&gt;&lt;span class="dl"&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;GET_TODOS&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;./TodoList&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DELETE_TODO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  mutation DeleteTodo($id: uuid!) {
    delete_todos_by_pk(id: $id) {
      id
      title
    }
  }
`&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;SingleTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;todo&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;deleteTodoMutation&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DELETE_TODO&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;deleteTodo&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="nf"&gt;deleteTodoMutation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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="c1"&gt;// rest of the code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, try deleting a todo. It works, but you get same experience as inserting. You need to refresh the page to see it.&lt;/p&gt;

&lt;p&gt;We will fix this shortly, but first let's add toggle functionality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Toggle Todo
&lt;/h3&gt;

&lt;p&gt;Still inside &lt;code&gt;components/SingleTodo.js&lt;/code&gt;, now you can add a new toggle mutation. Here is the updated component with both delete and toggle functionality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useMutation&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;@apollo/client&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;TrashIcon&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;@heroicons/react/solid&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;GET_TODOS&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;./TodoList&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;DELETE_TODO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  mutation DeleteTodo($id: uuid!) {
    delete_todos_by_pk(id: $id) {
      id
      title
    }
  }
`&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;TOGGLE_TODO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  mutation ToggleTodo($id: uuid!, $completed: Boolean!) {
    update_todos_by_pk(
      pk_columns: { id: $id }
      _set: { completed: $completed }
    ) {
      id
      completed
    }
  }
`&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;SingleTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;todo&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;deleteTodoMutation&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DELETE_TODO&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;toggleTodoMutation&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TOGGLE_TODO&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;deleteTodo&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="nf"&gt;deleteTodoMutation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toggleTodo&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="nf"&gt;toggleTodoMutation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&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;li&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;todo&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'flex justify-between 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;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;input&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'completed'&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'checkbox'&lt;/span&gt;
          &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggleTodo&lt;/span&gt;&lt;span class="si"&gt;}&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-4 h-4 mr-3 text-blue-600 border-gray-300 rounded focus:ring-blue-500'&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;label&lt;/span&gt;
          &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;line-through text-gray-400&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="si"&gt;}&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;todo&lt;/span&gt;&lt;span class="p"&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;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TrashIcon&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-5 h-5 text-gray-500 cursor-pointer'&lt;/span&gt;
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;deleteTodo&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;li&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;SingleTodo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, every CRUD operation works. But you need still need to refresh the page to see changes. Let's fix that.&lt;/p&gt;

&lt;p&gt;Notice we are importing &lt;code&gt;GET_TODOS&lt;/code&gt;, we'll need it for the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Apollo Cache
&lt;/h3&gt;

&lt;p&gt;The GraphQL library this tutorial uses, Apollo, implements a dynamic, local cache. Instead of reloading the full list of updates after each mutation, you can run the mutations against your local cache. Then, the to-do list on your frontend will automatically be updated.&lt;/p&gt;

&lt;p&gt;One great feature of this cache is called the &lt;code&gt;optimisticResponse&lt;/code&gt;. With this, you can assume that your GraphQL mutations will succeed and reflect the change in your frontend right away, instead of waiting for the success message from Hasura. The &lt;code&gt;optimisticResponse&lt;/code&gt; is preferred for your to-do app since you're not anticipating any errors, and it results in a faster-feeling user experience.&lt;/p&gt;

&lt;p&gt;To use the cache, you need to add the &lt;code&gt;cache&lt;/code&gt; and &lt;code&gt;optimisticResponse&lt;/code&gt; parameters to your mutation functions.&lt;/p&gt;

&lt;p&gt;In your &lt;code&gt;deleteTodo&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deleteTodo&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="nf"&gt;deleteTodoMutation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;optimisticResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readQuery&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="nx"&gt;GET_TODOS&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;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&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;id&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeQuery&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="nx"&gt;GET_TODOS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;todos&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your &lt;code&gt;toggleTodo&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toggleTodo&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="nf"&gt;toggleTodoMutation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;optimisticResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readQuery&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="nx"&gt;GET_TODOS&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;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todos&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;t&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;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;...&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&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;t&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeQuery&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="nx"&gt;GET_TODOS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;todos&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we must leverage the cache in &lt;code&gt;components/AddTodo.js&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;At the top of the file, add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GET_TODOS&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;./TodoList&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And update your &lt;code&gt;onSubmit&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;addTodo&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&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="na"&gt;update&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;existingTodos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readQuery&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="nx"&gt;GET_TODOS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeQuery&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="nx"&gt;GET_TODOS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insert_todos_one&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;existingTodos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todos&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;That's it! You now have a complete to-do list using &lt;a href="https://www.clerk.dev/?utm_source=nacho&amp;amp;utm_medium=devto&amp;amp;utm_campaign=heroku_guide" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt;, &lt;a href="https://cloud.hasura.io/" rel="noopener noreferrer"&gt;Hasura&lt;/a&gt;, and &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; - and you didn't write any backend code. It's powerful, easy to configure, and easy to scale.&lt;/p&gt;

&lt;p&gt;If you have enjoyed this tutorial or have questions or concerns, feel free to contact me at &lt;a href="https://twitter.com/nachoiacovino" rel="noopener noreferrer"&gt;@nachoiacovino&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>nextjs</category>
      <category>graphql</category>
      <category>postgres</category>
    </item>
  </channel>
</rss>
