<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nirmalya Ghosh</title>
    <description>The latest articles on DEV Community by Nirmalya Ghosh (@ghoshnirmalya).</description>
    <link>https://dev.to/ghoshnirmalya</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%2F126553%2F643f502b-0da7-442d-bf92-f0dec5008afd.jpeg</url>
      <title>DEV Community: Nirmalya Ghosh</title>
      <link>https://dev.to/ghoshnirmalya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ghoshnirmalya"/>
    <language>en</language>
    <item>
      <title>How to integrate Next.js with Fauna using React Query</title>
      <dc:creator>Nirmalya Ghosh</dc:creator>
      <pubDate>Mon, 08 Feb 2021 03:37:29 +0000</pubDate>
      <link>https://dev.to/ghoshnirmalya/how-to-integrate-next-js-with-fauna-using-react-query-7o4</link>
      <guid>https://dev.to/ghoshnirmalya/how-to-integrate-next-js-with-fauna-using-react-query-7o4</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we'll learn about how we can integrate&lt;a href="http://nextjs.org/" rel="noopener noreferrer"&gt; Next.js&lt;/a&gt; with&lt;a href="https://fauna.com/" rel="noopener noreferrer"&gt; Fauna&lt;/a&gt;. We'll also learn about how we can fetch GraphQL data on the server using&lt;a href="https://react-query.tanstack.com/" rel="noopener noreferrer"&gt; React Query&lt;/a&gt;. We'll be building a server-side rendered application which will look similar to the following:&lt;/p&gt;

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

&lt;p&gt;In this application, we’ll be showing a list of customers, products and orders. The data for these will be fetched from Fauna and rendered on the server side. This application won’t make any client side requests to Fauna even during routing.&lt;/p&gt;

&lt;p&gt;An online demo of the application that we built is hosted on&lt;a href="https://nextjs-react-query-faunadb.vercel.app/" rel="noopener noreferrer"&gt; Vercel&lt;/a&gt; and the code is available on&lt;a href="https://github.com/ghoshnirmalya/nextjs-react-query-faunadb" rel="noopener noreferrer"&gt; GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Fauna is a flexible, developer-friendly, secure database which delivers a web-native API. It has a lot of&lt;a href="https://fauna.com/features" rel="noopener noreferrer"&gt; features&lt;/a&gt; and is very easy to get up and running.&lt;/p&gt;

&lt;p&gt;Next.js is one of the most popular&lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt; React&lt;/a&gt; frameworks which has a lot of features like&lt;a href="https://nextjs.org/docs/routing/introduction" rel="noopener noreferrer"&gt; file-system routing&lt;/a&gt;,&lt;a href="https://nextjs.org/docs/basic-features/built-in-css-support" rel="noopener noreferrer"&gt; built-in CSS support&lt;/a&gt;,&lt;a href="https://nextjs.org/docs/api-routes/introduction" rel="noopener noreferrer"&gt; API routes&lt;/a&gt;,&lt;a href="https://nextjs.org/docs/basic-features/fast-refresh" rel="noopener noreferrer"&gt; fast refresh&lt;/a&gt;, etc. I've been building applications using Next.js and it has a good developer experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Softwares required for running the application&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;git&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Technologies used in the application&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://fauna.com/" rel="noopener noreferrer"&gt;Fauna&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://chakra-ui.com/" rel="noopener noreferrer"&gt;Chakra UI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://react-query.tanstack.com/" rel="noopener noreferrer"&gt;React Query&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Creating a new Next.js application&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s start by creating a new Next.js application. We can create a new Next.js application by running the following command from our terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn create next-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll have to enter the name of our application when the command prompts for it. We can name it anything we want. However, in this case, we'll name it &lt;strong&gt;nextjs-faunadb&lt;/strong&gt;. The above command will create a new Next.js application for us with the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── README.md
├── package.json
├── pages
│   ├── _app.js
│   ├── api
│   └── index.js
├── public
│   ├── favicon.ico
│   └── vercel.svg
├── styles
│   ├── Home.module.css
│   └── globals.css
└── yarn.lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now go inside the &lt;strong&gt;nextjs-faunadb&lt;/strong&gt; directory and start our Next.js application’s development server using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd nextjs-faunadb &amp;amp;&amp;amp; yarn dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our Next.js application should be up and running on&lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt; http://localhost:3000&lt;/a&gt; where we should be able to see the following 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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpn4rxpggt53j4399dgmg.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%2Fi%2Fpn4rxpggt53j4399dgmg.png" alt="image20"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Adding Chakra UI&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://chakra-ui.com/" rel="noopener noreferrer"&gt;Chakra UI&lt;/a&gt; is a popular React component library. Personally, I like using it on most of my applications as it's very flexible and easy to understand.&lt;/p&gt;

&lt;p&gt;We'll be using Chakra UI for styling the user interface of our application. We can install that package by running the following command from the root of our application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll be using&lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt; TypeScript&lt;/a&gt; for our application as well. So, let's rename the &lt;strong&gt;_app.js&lt;/strong&gt; file inside the &lt;strong&gt;pages&lt;/strong&gt; directory to &lt;strong&gt;_app.tsx&lt;/strong&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// pages/_app.tsx

import {
  Box,
  ChakraProvider,
  Container,
  HStack,
  Link as ChakraLink,
} from "@chakra-ui/react";
import type { AppProps } from "next/app";
import Link from "next/link";
import React from "react";

const App = ({ Component, pageProps }: AppProps) =&amp;gt; {
  return (
    &amp;lt;ChakraProvider&amp;gt;
      &amp;lt;Box bg="gray.100" h="100vh" w="100vw"&amp;gt;
        &amp;lt;Box borderWidth={1} rounded="md" bg="white" p={6}&amp;gt;
          &amp;lt;Container maxW="4xl"&amp;gt;
            &amp;lt;HStack spacing={16}&amp;gt;
              &amp;lt;Link href="/"&amp;gt;
                &amp;lt;ChakraLink&amp;gt;Customers&amp;lt;/ChakraLink&amp;gt;
              &amp;lt;/Link&amp;gt;
              &amp;lt;Link href="/products"&amp;gt;
                &amp;lt;ChakraLink&amp;gt;Products&amp;lt;/ChakraLink&amp;gt;
              &amp;lt;/Link&amp;gt;
              &amp;lt;Link href="/orders"&amp;gt;
                &amp;lt;ChakraLink&amp;gt;Orders&amp;lt;/ChakraLink&amp;gt;
              &amp;lt;/Link&amp;gt;
            &amp;lt;/HStack&amp;gt;
          &amp;lt;/Container&amp;gt;
        &amp;lt;/Box&amp;gt;
        &amp;lt;Container maxW="4xl" centerContent&amp;gt;
          &amp;lt;Component {...pageProps} /&amp;gt;
        &amp;lt;/Container&amp;gt;
      &amp;lt;/Box&amp;gt;
    &amp;lt;/ChakraProvider&amp;gt;
  );
};

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

&lt;/div&gt;



&lt;p&gt;Since we're using TypeScript, we'll need to restart our Next.js server. Once we restart our server, we'll get the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ yarn dev

yarn run v1.22.5
$ next dev
ready - started server on &amp;lt;http://localhost:3000&amp;gt;
It looks like you're trying to use TypeScript but do not have the required package(s) installed.

Please install typescript, @types/react, and @types/node by running:

    yarn add --dev typescript @types/react @types/node

If you are not trying to use TypeScript, please remove the tsconfig.json file from your package root (and any TypeScript files in your pages directory).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is because we added TypeScript to our application but didn't add the necessary dependencies. We can fix that by installing the missing dependencies. From the root of our application, we can execute the following command to install the missing dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add --dev typescript @types/react @types/node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if we start our Next.js server, our application should compile fine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ yarn dev

yarn run v1.22.5
$ next dev
ready - started server on &amp;lt;http://localhost:3000&amp;gt;
We detected TypeScript in your project and created a tsconfig.json file for you.

event - compiled successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Adding React Query&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://react-query.tanstack.com/" rel="noopener noreferrer"&gt;React Query&lt;/a&gt; is a data-fetching library for React. It helps in fetching, caching, synchronizing and updating server state in React applications. We will use React Query to fetch data in our application. We can install it by running the following command from the root of our application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add react-query
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll need to modify our &lt;strong&gt;pages/_app.tsx&lt;/strong&gt; file with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// pages/_app.tsx

....

import { QueryClient, QueryClientProvider } from "react-query";
import { Hydrate } from "react-query/hydration";

const queryClient = new QueryClient();

const App = ({ Component, pageProps }: AppProps) =&amp;gt; {
  return (
    &amp;lt;ChakraProvider&amp;gt;
      &amp;lt;QueryClientProvider client={queryClient}&amp;gt;
        &amp;lt;Hydrate state={pageProps.dehydratedState}&amp;gt;
          &amp;lt;Box bg="gray.100" h="100vh" w="100vw"&amp;gt;

              ....

          &amp;lt;/Box&amp;gt;
        &amp;lt;/Hydrate&amp;gt;
      &amp;lt;/QueryClientProvider&amp;gt;
    &amp;lt;/ChakraProvider&amp;gt;
  );
};

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Fetching GraphQL data from Fauna using React Query on the server side&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this step, we'll connect our Next.js application with Fauna and fetch data using the&lt;a href="https://github.com/prisma-labs/graphql-request" rel="noopener noreferrer"&gt; graphql-request&lt;/a&gt; plugin. Let's start by adding the plugin to our application. We can do that by running the following command from the root of our application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add graphql-request graphql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's also create a new file &lt;strong&gt;graphql-client.ts&lt;/strong&gt; inside the &lt;strong&gt;lib&lt;/strong&gt; directory with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// lib/graphql-client.ts

import { GraphQLClient } from "graphql-request";

const endpoint = process.env.FAUNA_GRAPHQL_ENDPOINT;

const graphQLClient = new GraphQLClient(endpoint, {
  headers: {
    authorization: `Basic ${process.env.FAUNA_AUTH_HEADER}`,
  },
});

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

&lt;/div&gt;



&lt;p&gt;This file will be responsible for handling the&lt;a href="https://docs.fauna.com/fauna/current/api/graphql/endpoints#authentication" rel="noopener noreferrer"&gt; Fauna authentication&lt;/a&gt; using Basic token for our GraphQL client.&lt;/p&gt;

&lt;p&gt;Next, let's create a new Fauna database.&lt;/p&gt;

&lt;p&gt;You need to visit&lt;a href="http://fauna.com/" rel="noopener noreferrer"&gt; http://fauna.com&lt;/a&gt; and log into your account. If you don't have an account, you'll need to create a new account. Once you log into your account, you'll be redirected to the Fauna dashboard.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click on the New Database button from the Fauna dashboard.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Create a new database by entering the name of your database. Check the Pre-populate with demo data checkbox so that there is some dummy data in the database and click on the Save button.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;The database will be created and we should be able to see a similar 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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fq91lsznnzgqc45jjrg4w.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%2Fi%2Fq91lsznnzgqc45jjrg4w.png" alt="image21"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If we click on the &lt;strong&gt;customers&lt;/strong&gt; collection, we can see the pre-populated data. The pre-populated data will help us in getting started with Fauna very easily.&lt;/p&gt;

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

&lt;p&gt;Next, if we visit the GraphQL tab on the Fauna dashboard, we should be able to execute a GraphQL query or mutation.&lt;/p&gt;

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

&lt;p&gt;The HTTP headers will already be pre-populated in the GraphQL Playground:&lt;/p&gt;

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

&lt;p&gt;We can also check out the &lt;strong&gt;Schema&lt;/strong&gt; of our database:&lt;/p&gt;

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

&lt;p&gt;We can also checkout the &lt;strong&gt;Docs&lt;/strong&gt; tab to know about the available GraphQL queries and mutations:&lt;/p&gt;

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

&lt;p&gt;We can run a simple GraphQL query to check out the playground. Let's run the following GraphQL query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query {
  allCustomers {
    data {
      _id
      firstName
      lastName
      address {
        street
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we click on the &lt;strong&gt;Execute Query&lt;/strong&gt; button, we'll get the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "data": {
    "allCustomers": {
      "data": [
        {
          "_id": "287346643083198981",
          "firstName": "Auria",
          "lastName": "Osgardby",
          "address": {
            "street": "87856 Mendota Court"
          }
        },
        {
          "_id": "287346643084247557",
          "firstName": "Skipper",
          "lastName": "Scanes",
          "address": {
            "street": "72 Waxwing Terrace"
          }
        },
        {
          "_id": "287346643084248581",
          "firstName": "Ardith",
          "lastName": "Probert",
          "address": {
            "street": "5 Troy Trail"
          }
        }
      ]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's try to do a similar query from our Next.js application. To do that, we need to do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new file name &lt;strong&gt;.env.local&lt;/strong&gt; in the root of our application to store all our &lt;a href="https://medium.com/chingu/an-introduction-to-environment-variables-and-how-to-use-them-f602f66d15fa" rel="noopener noreferrer"&gt;environment variables&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Copy the value of the &lt;strong&gt;authorization&lt;/strong&gt; key in the HTTP header (without the &lt;strong&gt;Basic&lt;/strong&gt; text) from the GraphQL playground and past it inside the &lt;strong&gt;.env.local&lt;/strong&gt; file. It should look like the following:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// .env.local

FAUNA_AUTH_HEADER=Zm5BRF9OdnBFN0FDQUpxcXF2V3dkRFpQaGFjpxcXF2V3dkRFpQaRGVIbEpxcXF2V3dkRFpQasxa0Yjpu=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Copy the value of the Fauna GraphQL API's endpoint from the playground and paste it inside the &lt;strong&gt;.env.local&lt;/strong&gt; file as well. Our .env.local file should look like the following:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// .env.local
// `FAUNA_AUTH_HEADER` will be different in your case.

FAUNA_AUTH_HEADER=Zm5BRF9OdnBFN0FDQUpxcXF2V3dkRFpQaGFjpxcXF2V3dkRFpQaRGVIbEpxcXF2V3dkRFpQasxa0Yjpu=
FAUNA_GRAPHQL_ENDPOINT=https://graphql.fauna.com/graphql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create a new file named &lt;strong&gt;get-all-customers.ts&lt;/strong&gt; inside the &lt;strong&gt;lib&lt;/strong&gt; directory with the following content:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// lib/get-all-customers.ts

import { gql } from "graphql-request";
import graphQLClient from "./graphql-client";

const getAllCustomers = async () =&amp;gt; {
  const query = gql`
    {
      allCustomers {
        data {
          _id
          firstName
          lastName
        }
      }
    }
  `;

  const response = await graphQLClient.request(query);
  const data = JSON.parse(JSON.stringify(response));

  return data.allCustomers.data;
};

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

&lt;/div&gt;



&lt;p&gt;The above code will be responsible for fetching all the customer data from our Fauna database.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Rename our &lt;strong&gt;pages/index.js&lt;/strong&gt; file to &lt;strong&gt;index.tsx&lt;/strong&gt; and replace its content with the following:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// pages/index.tsx

import { Box, Grid, Text } from "@chakra-ui/react";
import getAllCustomers from "../lib/get-all-customers";
import { NextPage } from "next";
import React from "react";
import { QueryClient, useQuery } from "react-query";
import { dehydrate } from "react-query/hydration";

const CustomersPage: NextPage = () =&amp;gt; {
  const { data } = useQuery("allCustomers", getAllCustomers, {
    staleTime: Infinity,
  });

  return (
    &amp;lt;Grid gap={4} m={4} gridTemplateColumns="1fr" w="100%"&amp;gt;
      &amp;lt;Box borderWidth={1} rounded="md" bg="white"&amp;gt;
        &amp;lt;Box borderBottomWidth={1} px={8} py={6} bg="gray.200"&amp;gt;
          &amp;lt;Text fontWeight="bold" textTransform="uppercase"&amp;gt;
            Customers
          &amp;lt;/Text&amp;gt;
        &amp;lt;/Box&amp;gt;
        &amp;lt;Box&amp;gt;
          {data.map((user) =&amp;gt; {
            return (
              &amp;lt;Text key={user._id} p={8} color="gray.700" borderBottomWidth={1}&amp;gt;
                {user.firstName} {user.lastName}
              &amp;lt;/Text&amp;gt;
            );
          })}
        &amp;lt;/Box&amp;gt;
      &amp;lt;/Box&amp;gt;
    &amp;lt;/Grid&amp;gt;
  );
};

export const getServerSideProps = async () =&amp;gt; {
  const queryClient = new QueryClient();
  await queryClient.prefetchQuery("allCustomers", getAllCustomers, {
    staleTime: Infinity,
  });

  return {
    props: {
      dehydratedState: dehydrate(queryClient),
    },
  };
};

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Stop our Next.js server and reload our &lt;strong&gt;.env.local&lt;/strong&gt; file by running the following command from the root of our application:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source .env.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Start our Next.js server by running the following command from the root of our application:
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;/div&gt;



&lt;p&gt;Now, if we visit&lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt; http://localhost:3000&lt;/a&gt;, we should be able to view the following 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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2jowcs05rmn2p1s6kjjh.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%2Fi%2F2jowcs05rmn2p1s6kjjh.png" alt="image2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we inspect using our browser's dev-tools, we'll be able to see that the page is rendered on the server and no data-fetching happens on the client:&lt;/p&gt;

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

&lt;p&gt;Next, let's create a similar page for &lt;strong&gt;Products&lt;/strong&gt; so that we can demonstrate that the fetching of data while routing also happens on the server.&lt;/p&gt;

&lt;p&gt;First, we need to create a new file named &lt;strong&gt;get-all-products.ts&lt;/strong&gt; inside the &lt;strong&gt;lib&lt;/strong&gt; directory with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// lib/get-all-products.ts

import { gql } from "graphql-request";
import graphQLClient from "./graphql-client";

const getAllProducts = async () =&amp;gt; {
  const query = gql`
    {
      allProducts {
        data {
          _id
          name
          description
          price
        }
      }
    }
  `;

  const response = await graphQLClient.request(query);
  const data = JSON.parse(JSON.stringify(response));

  return data.allProducts.data;
};

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

&lt;/div&gt;



&lt;p&gt;Next, we'll need to create a new file named &lt;strong&gt;products.tsx&lt;/strong&gt; inside the &lt;strong&gt;pages&lt;/strong&gt; directory with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// pages/products.tsx

import { Badge, Box, Grid, HStack, Text } from "@chakra-ui/react";
import getAllProducts from "../lib/get-all-products";
import { NextPage } from "next";
import React from "react";
import { QueryClient, useQuery } from "react-query";
import { dehydrate } from "react-query/hydration";

const ProductsPage: NextPage = () =&amp;gt; {
  const { data } = useQuery("allProducts", getAllProducts, {
    staleTime: Infinity,
  });

  return (
    &amp;lt;Grid gap={4} m={4} gridTemplateColumns="1fr" w="100%"&amp;gt;
      &amp;lt;Box borderWidth={1} rounded="md" bg="white"&amp;gt;
        &amp;lt;Box borderBottomWidth={1} px={8} py={6} bg="gray.200"&amp;gt;
          &amp;lt;Text fontWeight="bold" textTransform="uppercase"&amp;gt;
            Products
          &amp;lt;/Text&amp;gt;
        &amp;lt;/Box&amp;gt;
        &amp;lt;Box&amp;gt;
          {data.map((product) =&amp;gt; {
            return (
              &amp;lt;Box
                key={product._id}
                p={8}
                color="gray.700"
                borderBottomWidth={1}
              &amp;gt;
                &amp;lt;HStack spacing={8} justifyContent="space-between"&amp;gt;
                  &amp;lt;Text&amp;gt;{product.name}&amp;lt;/Text&amp;gt;
                  &amp;lt;Badge colorScheme="green"&amp;gt;{product.description}&amp;lt;/Badge&amp;gt;
                &amp;lt;/HStack&amp;gt;
              &amp;lt;/Box&amp;gt;
            );
          })}
        &amp;lt;/Box&amp;gt;
      &amp;lt;/Box&amp;gt;
    &amp;lt;/Grid&amp;gt;
  );
};

export const getServerSideProps = async () =&amp;gt; {
  const queryClient = new QueryClient();
  await queryClient.prefetchQuery("allProducts", getAllProducts, {
    staleTime: Infinity,
  });

  return {
    props: {
      dehydratedState: dehydrate(queryClient),
    },
  };
};

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering" rel="noopener noreferrer"&gt;getServerSideProps&lt;/a&gt; is a function through which we can fetch data on the server in Next.js.&lt;/p&gt;

&lt;p&gt;Now, if we visit&lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt; http://localhost:3000&lt;/a&gt; and click on the &lt;strong&gt;Products&lt;/strong&gt; tab, we'll be able to view the products listing page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fawqb0payj8scgr5jkp6p.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fawqb0payj8scgr5jkp6p.gif" alt="image17"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we inspect the request, we can see that the fetching of data happens on the server. No external API request to the Fauna GraphQL servers happens on the client-side of the Next.js application:&lt;/p&gt;

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

&lt;p&gt;Next, we'll push our code to&lt;a href="https://github.com/" rel="noopener noreferrer"&gt; GitHub&lt;/a&gt; and deploy to&lt;a href="http://vercel.com/" rel="noopener noreferrer"&gt; Vercel&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Pushing our code to GitHub&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this section, we’ll commit our code and push it to &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. We'll need to do the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Log into your GitHub Account.** **You’ll need a &lt;a href="https://github.com/join" rel="noopener noreferrer"&gt;GitHub account&lt;/a&gt; to store our code. This is required because we want to deploy our application on Vercel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Commit our code using&lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt; Git&lt;/a&gt;. You’ll need to have Git installed on your computer for this step.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From the root of our application, we can run the following command to&lt;a href="https://git-scm.com/docs/git-add" rel="noopener noreferrer"&gt; stage&lt;/a&gt; all our files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add --all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we can&lt;a href="https://git-scm.com/docs/git-commit" rel="noopener noreferrer"&gt; commit&lt;/a&gt; all our files by running the following command from the root of our application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit -m "Adds all files"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create a new GitHub repository by visiting&lt;a href="https://github.com/new" rel="noopener noreferrer"&gt; https://github.com/new&lt;/a&gt;. We'll need to enter the name of our repository and click on the &lt;strong&gt;Create Repository&lt;/strong&gt; button.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Push our code to GitHub by running the following command from the root of our application.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git remote add origin &amp;lt;https://github.com/&amp;gt;&amp;lt;your-github-username&amp;gt;/&amp;lt;your-repository-name&amp;gt;b.git
git branch -M main
git push -u origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, our code should be available on GitHub.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  &lt;strong&gt;Deploying the application to Vercel&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this step, we'll deploy our code using&lt;a href="http://vercel.com/" rel="noopener noreferrer"&gt; Vercel&lt;/a&gt;. We'll need to do the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Log into your Vercel account&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We’ll need a Vercel account to deploy our code. You can create one if you don't already have one.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Importing our repository to Vercel&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We can import our repository to Vercel by visiting&lt;a href="https://vercel.com/new" rel="noopener noreferrer"&gt; https://vercel.com/new&lt;/a&gt; and searching for our GitHub repository.&lt;/p&gt;

&lt;p&gt;We might need to grant Vercel access to the Git repositories that we want to import.&lt;/p&gt;

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

&lt;p&gt;We can configure the GitHub app by clicking on the &lt;strong&gt;Configure GitHub App&lt;/strong&gt; button. Once we give the necessary access to Vercel, we should be able to view our repository and click on the &lt;strong&gt;Import&lt;/strong&gt; button next to it.&lt;/p&gt;

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

&lt;p&gt;In the next step, we can select the scope of Vercel. For this application, we'll select our &lt;strong&gt;personal account&lt;/strong&gt; by clicking on the &lt;strong&gt;Select&lt;/strong&gt; button next to it.&lt;/p&gt;

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

&lt;p&gt;In the next step, we'll be able to view the details of our project. We'll need to enter the environment variables from our &lt;strong&gt;.env.local&lt;/strong&gt; file and click on the &lt;strong&gt;Deploy&lt;/strong&gt; button to deploy our application.&lt;/p&gt;

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

&lt;p&gt;Once the application is deployed, we should be able to view the following 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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgtzrepmgb9gz31qotsk6.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%2Fi%2Fgtzrepmgb9gz31qotsk6.png" alt="image14"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we click on the &lt;strong&gt;Visit&lt;/strong&gt; button, we should be able to view our application deployed on Vercel.&lt;/p&gt;

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

&lt;p&gt;In this tutorial, we learned about how we can integrate Next.js with Fauna, as well as how we can fetch GraphQL data on the server using React Query.&lt;/p&gt;

&lt;p&gt;An online demo of the application that we built is hosted on&lt;a href="https://nextjs-react-query-faunadb.vercel.app/" rel="noopener noreferrer"&gt; Vercel&lt;/a&gt; and the code is available on&lt;a href="https://github.com/ghoshnirmalya/nextjs-react-query-faunadb" rel="noopener noreferrer"&gt; GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>fauna</category>
      <category>nextjs</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>Integrating TailwindCSS with Next.js</title>
      <dc:creator>Nirmalya Ghosh</dc:creator>
      <pubDate>Sat, 02 Jan 2021 06:02:16 +0000</pubDate>
      <link>https://dev.to/ghoshnirmalya/integrating-tailwindcss-with-next-js-2kl3</link>
      <guid>https://dev.to/ghoshnirmalya/integrating-tailwindcss-with-next-js-2kl3</guid>
      <description>&lt;p&gt;In this tutorial, we'll learn the simplest way to integrate &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;TailwindCSS&lt;/a&gt; with &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Next.js?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; is a React framework which provides Server-Side Rendering out of box. It's a very popular Node.js framework with &lt;a href="https://github.com/zeit/next.js" rel="noopener noreferrer"&gt;over 59k stars on Github&lt;/a&gt;. It provides a &lt;a href="https://nextjs.org/#features" rel="noopener noreferrer"&gt;several features&lt;/a&gt; like &lt;a href="https://nextjs.org/features/server-side-rendering" rel="noopener noreferrer"&gt;Server-Side rendering&lt;/a&gt;, &lt;a href="https://nextjs.org/features/static-exporting" rel="noopener noreferrer"&gt;Static Exporting&lt;/a&gt;, &lt;a href="https://nextjs.org/features/css-in-js" rel="noopener noreferrer"&gt;CSS-in-JS&lt;/a&gt;, etc.&lt;/p&gt;

&lt;p&gt;I've worked with Next.js for more than a year and I liked the overall Developer Experience. It's pretty easy to create new pages, add new plugin, routing, etc. On top of all these, they've a lot of &lt;a href="https://github.com/zeit/next.js/tree/canary/examples/" rel="noopener noreferrer"&gt;starter templates (or examples)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Deploying Next.js applications to production using &lt;a href="https://zeit.co/" rel="noopener noreferrer"&gt;Zeit&lt;/a&gt; is also &lt;a href="https://zeit.co/solutions/nextjs" rel="noopener noreferrer"&gt;pretty simple&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is TailwindCSS?
&lt;/h2&gt;

&lt;p&gt;I've already covered about &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;TailwindCSS&lt;/a&gt; in one of my &lt;a href="https://www.nirmalyaghosh.com/what-is-tailwind-css" rel="noopener noreferrer"&gt;previous posts&lt;/a&gt;. In short, TailwindCSS is a utility-first CSS framework which aims to provide us with a set of utlity classes (like flex, block, inline-block, etc.). In addition to that, it also provides us utility classes to create CSS grids, responsive designs as well as style hover, focus and active pseudo-classes.&lt;/p&gt;

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

&lt;p&gt;Let's start by &lt;a href="https://github.com/zeit/next.js#setup" rel="noopener noreferrer"&gt;bootstrapping a Next.js application&lt;/a&gt;. To do so, we need to run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-next-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything works fine, you should get an output like the following:&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%2Fv1609515190200%2FoWr8MNE6B.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%2Fv1609515190200%2FoWr8MNE6B.png" alt="Bootstrapping a Next.js application"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the installation is complete, we'll get a new &lt;code&gt;frontend&lt;/code&gt; directory as that's the name we gave while creating the application. Let's go inside the &lt;code&gt;frontend&lt;/code&gt; and start the server:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now,if we visit &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;, we'll see the following page:&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%2Fv1609515213690%2F8om4UYBJ8.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%2Fv1609515213690%2F8om4UYBJ8.png" alt="Sample Next.js application"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing TailwindCSS
&lt;/h2&gt;

&lt;p&gt;I've written about how to integrate TailwindCSS with React in one of my &lt;a href="https://www.nirmalyaghosh.com/what-is-tailwind-css" rel="noopener noreferrer"&gt;previous posts&lt;/a&gt;. The process of integrating TailwindCSS with Next.js will be a similar one.&lt;/p&gt;

&lt;p&gt;First, we need to install TailwindCSS:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If you prefer npm, you can run the following command instead of the above one:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Next, we need to use the &lt;a class="mentioned-user" href="https://dev.to/tailwind"&gt;@tailwind&lt;/a&gt; directive to inject Tailwind's base, components, and utilities styles into our CSS. To do that we need to create a new file at &lt;code&gt;public/assets/styles/vendors.css&lt;/code&gt; add the following code to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="nt"&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="nt"&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="nt"&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;Next, we need to add the &lt;code&gt;build:style&lt;/code&gt; script to our &lt;code&gt;package.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next start"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"build:style"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tailwind build public/assets/styles/vendors.css -o public/assets/styles/tailwind.css"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the &lt;code&gt;build:style&lt;/code&gt; command will generate a new &lt;code&gt;public/assets/styles/tailwind.css&lt;/code&gt; file whenever we run it:&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%2Fv1609515235446%2FSxqLXjJzn.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%2Fv1609515235446%2FSxqLXjJzn.png" alt="Generating new tailwind.css file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we need to add the generated file to our &lt;code&gt;pages/index.js&lt;/code&gt; file:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Head&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;next/head&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;Nav&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/nav&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../public/assets/styles/tailwind.css&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;That's all we need to do to make TailwindCSS work with Next.js. To verify whether TailwindCSS is working or not, we can add a TailwindCSS class. We can add the &lt;code&gt;bg-blue-900 py-8&lt;/code&gt; class to our &lt;code&gt;pages/index.js&lt;/code&gt; file:&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;Home&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Home&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/title&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt; &lt;span class="nx"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;icon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/favicon.ico&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Head&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Nav&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hero bg-blue-100 py-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Welcome&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&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="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;To&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;started&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;edit&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/code&amp;gt; and save to reload&lt;/span&gt;&lt;span class="err"&gt;.
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if we restart our server and visit &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;, we'll see that TailwindCSS is working as expected:&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%2Fv1609515275782%2F5Pgxer9DH.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%2Fv1609515275782%2F5Pgxer9DH.png" alt="Integrating TailwindCSS with Next.js"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to know more about configuring Tailwind, you can read it &lt;a href="https://www.nirmalyaghosh.com/what-is-tailwind-css" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;In this tutorial, we've learnt how to use TailwindCSS with a Next.js application. In the future, we'll build a &lt;a href="https://www.producthunt.com/" rel="noopener noreferrer"&gt;ProductHunt&lt;/a&gt; clone using &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt; and &lt;a href="https://graphql.org/" rel="noopener noreferrer"&gt;GraphQL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope that this tutorial helps you in your future projects.&lt;/p&gt;

</description>
      <category>react</category>
      <category>nextjs</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Getting started with Next.js and GraphCMS</title>
      <dc:creator>Nirmalya Ghosh</dc:creator>
      <pubDate>Sun, 12 Jul 2020 05:50:11 +0000</pubDate>
      <link>https://dev.to/ghoshnirmalya/getting-started-with-next-js-and-graphcms-1mka</link>
      <guid>https://dev.to/ghoshnirmalya/getting-started-with-next-js-and-graphcms-1mka</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In this tutorial, we'll learn how we can create a Next.js project and integrate it with &lt;a href="https://graphcms.com/"&gt;GraphCMS&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://graphcms.com/"&gt;GraphCMS's&lt;/a&gt; mission is to remove traditional content management pain points by using the power of GraphQL, and take the idea of a Headless CMS to the next level.&lt;/p&gt;

&lt;p&gt;GraphCMS provides a lot of &lt;a href="https://graphcms.com/features"&gt;features&lt;/a&gt; out of the box. Some of them are as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;GraphQL API&lt;/li&gt;
&lt;li&gt;Content Localization&lt;/li&gt;
&lt;li&gt;Webhooks&lt;/li&gt;
&lt;li&gt;Versioning&lt;/li&gt;
&lt;li&gt;Content API&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It also provides a lot of Editorial and Operational features. Some of them are as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Rich Content Editing&lt;/li&gt;
&lt;li&gt;Global Marketing Campaigns&lt;/li&gt;
&lt;li&gt;SEO Friendly&lt;/li&gt;
&lt;li&gt;WYSIWYG&lt;/li&gt;
&lt;li&gt;Built in Localization&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A demo of the application that we will be building is available &lt;a href="https://nextjs-graphcms.vercel.app/"&gt;here&lt;/a&gt; which is hosted on &lt;a href="https://vercel.com/"&gt;Vercel&lt;/a&gt; and the source code is available on &lt;a href="https://github.com/ghoshnirmalya/nextjs-graphcms"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with Next.js
&lt;/h2&gt;

&lt;p&gt;Let's &lt;a href="https://nextjs.org/docs/getting-started#setup"&gt;setup&lt;/a&gt; a new Next.js project. To do so, we will have using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-next-app
&lt;span class="c"&gt;# or&lt;/span&gt;
yarn create next-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yyfJeXtp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yyfJeXtp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/1.png" alt="Bootstrapping a Next.js project" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above command will generate the following files for us:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t5In0YdK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t5In0YdK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/2.png" alt="Directory structure for Next.js project" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, we can go inside the directory Next.js created for us and start the development server using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;nextjs-graphcms &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; yarn dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will spin up a development server on &lt;a href="http://localhost:3000/"&gt;http://localhost:3000/&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IxTSLniX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IxTSLniX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/3.png" alt="Development server for Next.js on http://localhost:3000/" width="800" height="869"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;First, we need to create an account on &lt;a href="https://app.graphcms.com/signup"&gt;GraphCMS&lt;/a&gt; for free. If you already have an account, you can just sign in.&lt;/p&gt;

&lt;p&gt;Next, after signing in, we can select from one of the available Project Templates. We will start with the Blog Starter template.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kd_Qis2t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kd_Qis2t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/4.png" alt="GraphCMS templates" width="800" height="852"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we need to add a name to our Project and click on the "Create Project" button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pbx16Smg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pbx16Smg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/5.png" alt="Adding name to our GraphCMS templates" width="800" height="864"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we can select the "Personal" plan and click on the "Continue" button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rqXdCVPg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rqXdCVPg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/6.png" alt="Selecting our GraphCMS project plan" width="800" height="811"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can find out the URL endpoint of our project from our project settings:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5MBXB7iQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5MBXB7iQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/7.png" alt="GraphCMS project settings" width="800" height="811"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, if we visit the URL endpoint and start querying data using GraphQL, we won't get any data:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S-2xmnlj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S-2xmnlj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/8.png" alt="Fetching data from GraphCMS" width="800" height="811"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is because we haven't updated the API permissions to fetch both &lt;strong&gt;Draft&lt;/strong&gt; and &lt;strong&gt;Published&lt;/strong&gt; data from GraphCMS:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AsEyfOQY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AsEyfOQY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/9.png" alt="Updating project permissions on GraphCMS" width="800" height="875"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, if we fetching GraphQL from our URL endpoint, we will get proper data:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sGqoML_6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sGqoML_6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/10.png" alt="Fetching both draft and published data from GraphCMS" width="800" height="811"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's save the URL endpoint in a &lt;strong&gt;.env&lt;/strong&gt; file in our application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GRAPHQL_URL_ENDPOINT=https://api-eu-central-1.graphcms.com/v2/something/master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installing GraphQL client
&lt;/h2&gt;

&lt;p&gt;We will be using &lt;a href="https://github.com/prisma-labs/graphql-request"&gt;graphql-request&lt;/a&gt; which is a minimal GraphQL client supporting Node and browsers for scripts or simple apps.&lt;/p&gt;

&lt;p&gt;We can install that package using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm add graphql-request
&lt;span class="c"&gt;# or&lt;/span&gt;
yarn add graphql-request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's restart our Next.js server using &lt;code&gt;yarn dev&lt;/code&gt;. We can use &lt;strong&gt;graphq-request&lt;/strong&gt; to fetch data from our URL endpoint. To do so, we need to modify our &lt;code&gt;pages/index.js&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 { GraphQLClient } from "graphql-request";

const graphcms = new GraphQLClient(process.env.GRAPHQL_URL_ENDPOINT);

export async function getStaticProps() {
  const { posts } = await graphcms.request(
    `
    query Posts() {
      posts {
        id
        title
        excerpt
        slug
        coverImage {
          id
          url
        }
        author {
          id
          name
        }
        date
      }
    }
  `
  );

  return {
    props: {
      posts,
    },
  };
}

export default ({ posts }) =&amp;gt; {
  return (
    &amp;lt;&amp;gt;
      {posts.map((post) =&amp;gt; {
        return (
          &amp;lt;div key={post.id}&amp;gt;
            &amp;lt;img src={post.coverImage.url} alt={post.title} /&amp;gt;
            &amp;lt;h2&amp;gt;{post.title}&amp;lt;/h2&amp;gt;
            &amp;lt;p&amp;gt;{post.date}&amp;lt;/p&amp;gt;
            &amp;lt;p&amp;gt;{post.author.name}&amp;lt;/p&amp;gt;
            &amp;lt;p&amp;gt;{post.excerpt}&amp;lt;/p&amp;gt;
          &amp;lt;/div&amp;gt;
        );
      })}
    &amp;lt;/&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if we visit &lt;a href="http://localhost:3000/"&gt;http://localhost:3000/&lt;/a&gt;, we should be able to see the following screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Jsu7fl7Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jsu7fl7Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/11.png" alt="Showing data from GraphCMS" width="800" height="2113"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding styles using TailwindCSS
&lt;/h2&gt;

&lt;p&gt;We will be adding &lt;a href="https://tailwindcss.com/"&gt;TailwindCSS&lt;/a&gt; using &lt;a href="https://tailwindcss.com/docs/installation/#using-tailwind-via-cdn"&gt;CDN&lt;/a&gt;. However, that is not the recommended way of installing TailwindCSS. We are using that just for the sake of decreasing the size of this tutorial. More information regarding how to install TailwindCSS can be found &lt;a href="https://tailwindcss.com/docs/installation/"&gt;in their official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We need to create a new file &lt;code&gt;_app.js&lt;/code&gt; inside our &lt;strong&gt;pages&lt;/strong&gt; directory and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Head from "next/head";

const App = ({ Component, pageProps }) =&amp;gt; {
  return (
    &amp;lt;&amp;gt;
      &amp;lt;Head&amp;gt;
        &amp;lt;link
          href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css"
          rel="stylesheet"
        /&amp;gt;
      &amp;lt;/Head&amp;gt;
      &amp;lt;Component {...pageProps} /&amp;gt;
    &amp;lt;/&amp;gt;
  );
};

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

&lt;/div&gt;



&lt;p&gt;Now, if we restart our server, we should be able to see that TailwindCSS is getting downloaded.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--97k2xfBS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--97k2xfBS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/12.png" alt="Integrating TailwindCSS with out project" width="800" height="874"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we need to modify our &lt;code&gt;pages/index.js&lt;/code&gt; file with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default ({ posts }) =&amp;gt; {
  return (
    &amp;lt;div className="py-16 bg-gray-100"&amp;gt;
      {posts.map((post) =&amp;gt; {
        return (
          &amp;lt;div
            key={post.id}
            className="max-w-lg shadow-lg mb-16 rounded-lg mx-auto flex"
          &amp;gt;
            &amp;lt;div
              className="h-48 lg:h-auto lg:w-48 flex-none bg-cover rounded-t lg:rounded-t-none lg:rounded-l text-center overflow-hidden"
              style={{ backgroundImage: `url(${post.coverImage.url})` }}
              title={post.title}
            &amp;gt;&amp;lt;/div&amp;gt;
            &amp;lt;div className="bg-white rounded-b lg:rounded-b-none lg:rounded-r p-4 flex flex-col justify-between leading-normal"&amp;gt;
              &amp;lt;div className="mb-8"&amp;gt;
                &amp;lt;div className="text-gray-900 font-bold text-xl mb-2"&amp;gt;
                  {post.title}
                &amp;lt;/div&amp;gt;
                &amp;lt;p className="text-gray-700 text-base"&amp;gt;{post.excerpt}&amp;lt;/p&amp;gt;
              &amp;lt;/div&amp;gt;
              &amp;lt;div className="flex items-center"&amp;gt;
                &amp;lt;div className="text-sm"&amp;gt;
                  &amp;lt;p className="text-gray-900 leading-none"&amp;gt;
                    {post.author.name}
                  &amp;lt;/p&amp;gt;
                  &amp;lt;p className="text-gray-600"&amp;gt;{post.date}&amp;lt;/p&amp;gt;
                &amp;lt;/div&amp;gt;
              &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
        );
      })}
    &amp;lt;/div&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if we visit &lt;a href="http://localhost:3000/"&gt;http://localhost:3000/&lt;/a&gt;, we should be able to see the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VYutxN6O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VYutxN6O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/13.png" alt="Cards design using TailwindCSS for our Next.js project" width="800" height="1654"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We've successfully fetched data from GraphCMS and rendered them on the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating separate pages for each blog post
&lt;/h2&gt;

&lt;p&gt;We can also show blogs in separate routes. To do that, we will need to modify our &lt;code&gt;pages/index.js&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 { GraphQLClient } from "graphql-request";
import Link from "next/link";

const graphcms = new GraphQLClient(process.env.GRAPHQL_URL_ENDPOINT);

export async function getStaticProps() {
  const { posts } = await graphcms.request(
    `
    query Posts() {
      posts {
        id
        title
        excerpt
        slug
        coverImage {
          id
          url
        }
        author {
          id
          name
        }
        date
      }
    }
  `
  );

  return {
    props: {
      posts,
    },
  };
}

export default ({ posts }) =&amp;gt; {
  return (
    &amp;lt;div className="py-16 bg-gray-100"&amp;gt;
      {posts.map((post) =&amp;gt; {
        return (
          &amp;lt;Link key={post.id} as={`/post/${post.slug}`} href="/post/[slug]"&amp;gt;
            &amp;lt;a className="max-w-lg shadow-lg mb-16 rounded-lg mx-auto flex"&amp;gt;
              &amp;lt;div
                className="h-48 lg:h-auto lg:w-48 flex-none bg-cover rounded-t lg:rounded-t-none lg:rounded-l text-center overflow-hidden"
                style={{ backgroundImage: `url(${post.coverImage.url})` }}
                title={post.title}
              /&amp;gt;
              &amp;lt;div className="bg-white rounded-b lg:rounded-b-none lg:rounded-r p-4 flex flex-col justify-between leading-normal"&amp;gt;
                &amp;lt;div className="mb-8"&amp;gt;
                  &amp;lt;div className="text-gray-900 font-bold text-xl mb-2"&amp;gt;
                    {post.title}
                  &amp;lt;/div&amp;gt;
                  &amp;lt;p className="text-gray-700 text-base"&amp;gt;{post.excerpt}&amp;lt;/p&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div className="flex items-center"&amp;gt;
                  &amp;lt;div className="text-sm"&amp;gt;
                    &amp;lt;p className="text-gray-900 leading-none"&amp;gt;
                      {post.author.name}
                    &amp;lt;/p&amp;gt;
                    &amp;lt;p className="text-gray-600"&amp;gt;{post.date}&amp;lt;/p&amp;gt;
                  &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
              &amp;lt;/div&amp;gt;
            &amp;lt;/a&amp;gt;
          &amp;lt;/Link&amp;gt;
        );
      })}
    &amp;lt;/div&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will also need to create a new file &lt;code&gt;pages/post/[slug].js&lt;/code&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { GraphQLClient } from "graphql-request";
import Link from "next/link";

const graphcms = new GraphQLClient(process.env.GRAPHQL_URL_ENDPOINT);

export async function getStaticProps({ params }) {
  const { post } = await graphcms.request(
    `
    query Post($slug: String!) {
      post(where: { slug: $slug }) {
        id
        title
        content{
          text
        }
        slug
        coverImage {
          id
          url
        }
        author {
          id
          name
        }
        date
      }
    }
  `,
    {
      slug: params.slug,
    }
  );

  return {
    props: {
      post,
    },
  };
}

export async function getStaticPaths() {
  const { posts } = await graphcms.request(`
    {
      posts {
        id
        title
        content{
          text
        }
        slug
        coverImage {
          id
          url
        }
        author {
          id
          name
        }
        date
      }
    }
  `);

  return {
    paths: posts.map(({ slug }) =&amp;gt; ({
      params: { slug },
    })),
    fallback: false,
  };
}

export default ({ post }) =&amp;gt; {
  return (
    &amp;lt;div className="py-16 bg-gray-100 min-h-screen"&amp;gt;
      &amp;lt;div className="max-w-lg shadow-lg rounded-lg mx-auto mb-16"&amp;gt;
        &amp;lt;div
          className="h-48 rounded-t flex-none bg-cover text-center overflow-hidden"
          style={{ backgroundImage: `url(${post.coverImage.url})` }}
          title={post.title}
        /&amp;gt;
        &amp;lt;div className="bg-white rounded-b lg:rounded-b-none lg:rounded-r p-4 flex flex-col justify-between leading-normal"&amp;gt;
          &amp;lt;div className="mb-8"&amp;gt;
            &amp;lt;div className="text-gray-900 font-bold text-xl mb-2"&amp;gt;
              {post.title}
            &amp;lt;/div&amp;gt;
            &amp;lt;p className="text-gray-700 text-base"&amp;gt;{post.content.text}&amp;lt;/p&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div className="flex items-center"&amp;gt;
            &amp;lt;div className="text-sm"&amp;gt;
              &amp;lt;p className="text-gray-900 leading-none"&amp;gt;{post.author.name}&amp;lt;/p&amp;gt;
              &amp;lt;p className="text-gray-600"&amp;gt;{post.date}&amp;lt;/p&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div className="max-w-lg mx-auto"&amp;gt;
        &amp;lt;Link href="/"&amp;gt;
          &amp;lt;a&amp;gt;Back to all posts&amp;lt;/a&amp;gt;
        &amp;lt;/Link&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more information regarding how the &lt;strong&gt;Link&lt;/strong&gt; component works can be found in the official &lt;a href="https://nextjs.org/docs/api-reference/next/link"&gt;Next.js documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;More information regarding how to add pages in Next.js can be found in the official &lt;a href="https://nextjs.org/docs/basic-features/pages"&gt;Next.js documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k5ppPv-1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/14.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k5ppPv-1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://nirmalyaghosh.com/images/content/getting-started-with-nextjs-and-graphcms/14.gif" alt="Separate pages for blogs using the Link component" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;In this tutorial, we learnt how we can integrate GraphCMS with Next.js and create a blogging site. The demo of the application that we built as a part of this tutorial is available &lt;a href="https://nextjs-graphcms.vercel.app/"&gt;here&lt;/a&gt; which is hosted on &lt;a href="https://vercel.com/"&gt;Vercel&lt;/a&gt; and the source code is available on &lt;a href="https://github.com/ghoshnirmalya/nextjs-graphcms"&gt;Github&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>How to Automate the Backend stuffs with Open Source Headless CMS Strapi and Docker</title>
      <dc:creator>Nirmalya Ghosh</dc:creator>
      <pubDate>Mon, 06 Jul 2020 03:47:36 +0000</pubDate>
      <link>https://dev.to/ghoshnirmalya/how-to-automate-the-backend-stuffs-with-open-source-headless-cms-strapi-and-docker-377f</link>
      <guid>https://dev.to/ghoshnirmalya/how-to-automate-the-backend-stuffs-with-open-source-headless-cms-strapi-and-docker-377f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In this tutorial, we'll learn about the problems (related to saving our data) that we face while developing front-end applications. We'll explore an open source headless CMS, &lt;a href="https://strapi.io/"&gt;Strapi&lt;/a&gt;. We'll also learn about how to install and get started with Strapi using &lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of the aspects that always tend to be a blocker to me while developing front-end applications is the need for a ways to save the data from the front-end. In the past, I've use &lt;a href="https://firebase.google.com/"&gt;Firebase&lt;/a&gt; for saving my data to the database. However, it becomes difficult to manage this as Firebase has strict &lt;a href="https://firebase.google.com/docs/firestore/manage-data/data-types"&gt;data types&lt;/a&gt; as well as issues with &lt;a href="https://itnext.io/lessons-from-a-long-week-with-firebase-b433ce8ee49e"&gt;scaling&lt;/a&gt;, &lt;a href="https://crisp.chat/blog/why-you-should-never-use-firebase-realtime-database/"&gt;pricing&lt;/a&gt;, etc. For small apps and projects, Firebase works perfectly fine. However, for bigger apps, it presents its own set of problems. For those who don't know, Firebase is Google's mobile platform that helps you quickly develop high-quality apps and grow your business.&lt;/p&gt;

&lt;p&gt;As a result, I was trying to find an alternate tool which would take care of the back-end. Recently, I came across &lt;a href="https://strapi.io/"&gt;Strapi&lt;/a&gt; which is an open source Headless CMS. It's very easy to &lt;a href="https://strapi.io/documentation/3.0.0-beta.x/getting-started/quick-start.html"&gt;get started with Strapi&lt;/a&gt;. Also, it has a nice set of plugins in their &lt;a href="https://strapi.io/marketplace"&gt;marketplace&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'll also write about &lt;a href="https://hasura.io/"&gt;Hasura&lt;/a&gt; which connects to our databases &amp;amp; microservices and instantly gives us a production-ready GraphQL API. It's another tool that I found which takes care of the back-end.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;We'll be using the &lt;a href="https://github.com/strapi/strapi-docker"&gt;Docker version of Strapi&lt;/a&gt;. This will help us manage the database inside a containerized environment. In case our database gets corrupted, we can remove the container and re-build it again. There are many other advantages of using Docker. Instructions for installing Docker can be obtained from the &lt;a href="https://docs.docker.com/v17.09/engine/installation/"&gt;Docker documentation&lt;/a&gt;. Once the Docker installation is complete, we can proceed towards installing Strapi. We'll be using Postgres as our database. But, we can also use &lt;a href="https://strapi.io/documentation/3.0.0-beta.x/guides/databases.html#sqlite-installation"&gt;SQLite&lt;/a&gt;, &lt;a href="https://strapi.io/documentation/3.0.0-beta.x/guides/databases.html#mongodb-installation"&gt;MongoDB&lt;/a&gt;, MySQL and MariaDB. Example applications using these databases are present in the &lt;a href="https://github.com/strapi/strapi-docker/tree/master/examples"&gt;Strapi Docker repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Strapi
&lt;/h2&gt;

&lt;p&gt;First, we need to create a directory named &lt;code&gt;backend&lt;/code&gt; and then download the &lt;a href="https://github.com/strapi/strapi-docker/blob/master/examples/postgresql/docker-compose.yml"&gt;docker-compose.yml&lt;/a&gt; file from the &lt;a href="https://github.com/strapi/strapi-docker"&gt;strapi-docker repository&lt;/a&gt;. Now, we need to start Docker. Once Docker is up and running, we can go inside the &lt;code&gt;backend&lt;/code&gt; directory and run our Strapi container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;backend &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will pull &lt;strong&gt;postgres&lt;/strong&gt; and &lt;strong&gt;strapi/strapi&lt;/strong&gt; images from &lt;a href="https://hub.docker.com/"&gt;Docker Hub&lt;/a&gt;. So, it might take some time for this operation to complete. Once, everything is done, we'll get the following output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B5U0rn1B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B5U0rn1B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/1.png" alt="Message shown on completing Strapi installation" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating our first administrator profile
&lt;/h2&gt;

&lt;p&gt;We can now visit &lt;a href="http://localhost:1337/admin"&gt;http://localhost:1337/admin&lt;/a&gt; to create our first administrator. On visiting that url, we'll get the following form:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z720ImYk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z720ImYk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/2.png" alt="Form for creating an administrator" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we fill up the form with the required details, we'll be inside the admin panel of Strapi:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_gPr8_M3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_gPr8_M3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/3.png" alt="Strapi admin panel" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we're here, it means that our Strapi installation went perfectly fine and everytime Strapi asks us for login credentials, we can login to the admin panel using the credentials we provided while creating the administrator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding a new content-type
&lt;/h2&gt;

&lt;p&gt;By default, we should have three content-types: &lt;strong&gt;Permission&lt;/strong&gt;, &lt;strong&gt;Role&lt;/strong&gt; and &lt;strong&gt;User&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ztnTqkKR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ztnTqkKR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/4.png" alt="Default content-types" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, we want to add a &lt;strong&gt;Product&lt;/strong&gt; content-type. To do so, we need to click on the&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create new content-type&lt;/strong&gt; link. In the &lt;strong&gt;Display Name&lt;/strong&gt; field, we can type &lt;strong&gt;Product&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jlLtujY8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jlLtujY8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/5.png" alt="Adding a new content-type" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, we can click on &lt;strong&gt;Continue&lt;/strong&gt; to add fields for that content-type:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yENe0ivK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yENe0ivK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/6.png" alt="Adding fields for a new content-type" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll add a new &lt;strong&gt;Text&lt;/strong&gt; field and call it &lt;strong&gt;name&lt;/strong&gt; and select &lt;strong&gt;Short text&lt;/strong&gt; as its &lt;strong&gt;type&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UtBMPc7S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UtBMPc7S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/7.png" alt="Adding Name text field for Product content-type" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll add another &lt;strong&gt;Text&lt;/strong&gt; field and call it &lt;strong&gt;url&lt;/strong&gt; and select &lt;strong&gt;Short text&lt;/strong&gt; as its &lt;strong&gt;type&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G4_n5LWc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G4_n5LWc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/8.png" alt="Adding URL text field for Product content-type" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll add another &lt;strong&gt;Text&lt;/strong&gt; field and call it &lt;strong&gt;description&lt;/strong&gt; and select &lt;strong&gt;Long text&lt;/strong&gt; as its &lt;strong&gt;type&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NWf-B6m9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NWf-B6m9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/9.png" alt="Adding Description text field for Product content-type" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll add a &lt;strong&gt;Media&lt;/strong&gt; field and call it &lt;strong&gt;image&lt;/strong&gt; and select &lt;strong&gt;Single media&lt;/strong&gt; as its &lt;strong&gt;type&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mTUN24TO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mTUN24TO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/10.png" alt="Adding Image media field for Product content-type" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can now click on the &lt;strong&gt;Finish&lt;/strong&gt; button and then, we need to click on the &lt;strong&gt;Save&lt;/strong&gt; button to save our new content-type.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tiRlUGIB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tiRlUGIB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/11.png" alt="Saving our Product content-type" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we click on the &lt;strong&gt;Save&lt;/strong&gt; button, the Strapi server will automatically restart:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3GB-2iJr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3GB-2iJr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/12.png" alt="Restarting the Strapi server" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the server restarts completely, we can see our new Product content-type on the sidebar:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_bcJZx3n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_bcJZx3n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/13.png" alt="Viewing the entries for Product content-type" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Product content-type won't have any entries at the moment as we haven't added any entry yet! We can click on &lt;strong&gt;Add New Product&lt;/strong&gt; button to add a new entry to the Product content-type:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m5BKmq8A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/14.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m5BKmq8A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/14.png" alt="Adding a new entry for Product content-type" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can add the details of our product and then click on the &lt;strong&gt;Save&lt;/strong&gt; button to save the entry:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x-uHIvPb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/15.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x-uHIvPb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/15.png" alt="All entries for Product content-type" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Viewing entries of a content-type
&lt;/h2&gt;

&lt;p&gt;Strapi generates &lt;a href="https://strapi.io/documentation/3.0.0-beta.x/concepts/routing.html#concept"&gt;routes&lt;/a&gt; for our content-types automatically. But, if we visit &lt;a href="http://localhost:1337/products"&gt;http://localhost:1337/products&lt;/a&gt;, we'd get a &lt;strong&gt;403&lt;/strong&gt; response. This happens as our permission isn't set up for that content-type. To resolve this issue, we need to visit &lt;strong&gt;Roles &amp;amp; Permissions&lt;/strong&gt; tab and click on the &lt;strong&gt;Public&lt;/strong&gt; role:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ieN-OuG_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/16.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ieN-OuG_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/16.png" alt="Add Public role for Product content-type" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Public role tab, we need to find &lt;strong&gt;Product&lt;/strong&gt; inside the &lt;strong&gt;Permissions&lt;/strong&gt; tab. We need to allow all operations on the Product content-type. We can do so by selecting all the operations (count, create, delete, find, findone and update) or by clicking on &lt;strong&gt;Select All&lt;/strong&gt; checkbox.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---rkALH69--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---rkALH69--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/17.png" alt="Update permissions for Product content-type" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we need to click on the &lt;strong&gt;Save&lt;/strong&gt; button on the top right. Now, if we visit &lt;a href="http://localhost:1337/products"&gt;http://localhost:1337/products&lt;/a&gt;, we'd get a proper response:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--54AWP0Qs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--54AWP0Qs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/18.png" alt="Entries for Product content-type" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a new entry for a content-type
&lt;/h2&gt;

&lt;p&gt;Based on the permission we've set for the Product content-type, We can also create new entries using the API. We'll be using the &lt;a href="https://www.getpostman.com/"&gt;Postman&lt;/a&gt; tool to create a new Product entry.&lt;/p&gt;

&lt;p&gt;We just need to do a &lt;strong&gt;POST&lt;/strong&gt; request to &lt;a href="http://localhost:1337/products"&gt;http://localhost:1337/products&lt;/a&gt; endpoint with the following request body:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Dy8Uy9J0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/19.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Dy8Uy9J0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/19.png" alt="Creating a new entry for Product content-type" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We would get the following response once the entry is created:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LSqims9C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/20.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LSqims9C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://nirmalyaghosh.com/images/content/automate-backend-stuffs-with-strapi-and-docker/20.png" alt="Response for creating an entry for Product content-type" width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;We've leveraged Strapi, a Headless CMS to design the APIs for our back-end application. In the subsequest tutorials, we'd utlize these APIs to build front-end applications.&lt;/p&gt;

&lt;p&gt;I hope that this tutorial helps you in your future projects.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>opensource</category>
      <category>strapi</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
