<?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: hexrcs</title>
    <description>The latest articles on DEV Community by hexrcs (@hexrcs).</description>
    <link>https://dev.to/hexrcs</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%2F62575%2F564be6df-fa64-4066-ab96-1e2ba1374f29.png</url>
      <title>DEV Community: hexrcs</title>
      <link>https://dev.to/hexrcs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hexrcs"/>
    <language>en</language>
    <item>
      <title>🔑 Passwordless Authentication with Next.js, Prisma, and next-auth</title>
      <dc:creator>hexrcs</dc:creator>
      <pubDate>Sat, 26 Sep 2020 13:51:51 +0000</pubDate>
      <link>https://dev.to/prisma/passwordless-authentication-with-next-js-prisma-and-next-auth-5g8g</link>
      <guid>https://dev.to/prisma/passwordless-authentication-with-next-js-prisma-and-next-auth-5g8g</guid>
      <description>&lt;h1&gt;
  
  
  Passwordless Authentication with Next.js, Prisma, and next-auth
&lt;/h1&gt;

&lt;p&gt;In this post, you'll learn how to add passwordless authentication to your &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; app using &lt;a href="https://www.prisma.io/docs/getting-started/quickstart-typescript" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt; and &lt;a href="https://github.com/nextauthjs/next-auth" rel="noopener noreferrer"&gt;next-auth&lt;/a&gt;. By the end of this tutorial, your users will be able to log in to your app with either their GitHub account or a Slack-styled &lt;em&gt;magic link&lt;/em&gt; sent right to their Email inbox.&lt;/p&gt;

&lt;p&gt;If you want to follow along, clone &lt;a href="https://github.com/hexrcs/prisma-next-auth" rel="noopener noreferrer"&gt;this repo&lt;/a&gt; and switch to the &lt;a href="https://github.com/hexrcs/prisma-next-auth/tree/start-here" rel="noopener noreferrer"&gt;&lt;code&gt;start-here&lt;/code&gt;&lt;/a&gt; branch! 😃&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%2Fi.imgur.com%2FtVbypFW.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%2Fi.imgur.com%2FtVbypFW.gif" alt=" raw `next-auth` endraw  OAuth demo"&gt;&lt;/a&gt;Check out the slick auth flow!&lt;/p&gt;




&lt;p&gt;If you want to see the live coding version of this tutorial, &lt;a href="https://www.youtube.com/watch?v=GPBD3acOx_M" rel="noopener noreferrer"&gt;check out the recording&lt;/a&gt; below! 👇&lt;/p&gt;

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




&lt;h2&gt;
  
  
  Step 0: Dependencies and database setup
&lt;/h2&gt;

&lt;p&gt;Before we start, let's install Prisma and &lt;code&gt;next-auth&lt;/code&gt; into the Next.js project.&lt;/p&gt;

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

npm i next-auth

npm i -D @prisma/cli @types/next-auth


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

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;I'm using TypeScript in this tutorial, so I'll also install the type definitions for &lt;code&gt;next-auth&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You will also need a PostgreSQL database to store all the user data and active tokens.&lt;/p&gt;

&lt;p&gt;If you don't have access to a database yet, Heroku allows us to host PostgreSQL databases for free, super handy! You can check out &lt;a href="https://dev.to/prisma/how-to-setup-a-free-postgresql-database-on-heroku-1dc1"&gt;this post&lt;/a&gt; by &lt;a href="https://dev.to/nikolasburk"&gt;Nikolas Burk&lt;/a&gt; to see how to set it up.&lt;/p&gt;

&lt;p&gt;If you are a Docker fan and would rather keep everything during development local, you can also check out &lt;a href="https://egghead.io/lessons/postgresql-set-up-and-run-a-postgresql-instance-locally-with-docker-compose?pl=build-a-full-stack-app-with-prisma-2-7c81" rel="noopener noreferrer"&gt;this video&lt;/a&gt; I did on how to do this with Docker Compose.&lt;/p&gt;

&lt;p&gt;Before moving on to the next step, make sure you have a PostgreSQL URI in this format:&lt;/p&gt;

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

postgresql://&amp;lt;USER&amp;gt;:&amp;lt;PASSWORD&amp;gt;@&amp;lt;HOST_NAME&amp;gt;:&amp;lt;PORT&amp;gt;/&amp;lt;DB_NAME&amp;gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Step 1: Initialize Prisma
&lt;/h2&gt;

&lt;p&gt;Awesome! Let's generate a starter &lt;a href="https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-schema" rel="noopener noreferrer"&gt;Prisma schema&lt;/a&gt; and a &lt;code&gt;@prisma/client&lt;/code&gt; module into the project.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npx prisma init


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

&lt;/div&gt;

&lt;p&gt;Notice that a new directory &lt;code&gt;prisma&lt;/code&gt; is created under your project. This is where all the database magic happens. 🧙‍♂️&lt;/p&gt;

&lt;p&gt;Now, replace the dummy database URI in &lt;code&gt;/prisma/.env&lt;/code&gt; with your own.&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%2Fi.imgur.com%2Fs0VLzsg.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%2Fi.imgur.com%2Fs0VLzsg.png" alt="Project structure after running  raw `npx prisma init` endraw "&gt;&lt;/a&gt;Project structure after running &lt;code&gt;npx prisma init&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Define database schema for authentication
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;next-auth&lt;/code&gt; requires us to have &lt;a href="https://next-auth.js.org/schemas/models" rel="noopener noreferrer"&gt;specific tables in our database&lt;/a&gt; for it to work seamlessly. In our project, the schema file is located at &lt;code&gt;/prisma/schema.prisma&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's use the &lt;a href="https://next-auth.js.org/schemas/adapters#prisma-schema" rel="noopener noreferrer"&gt;&lt;em&gt;default schema&lt;/em&gt;&lt;/a&gt; for now, but know that you can always &lt;a href="https://next-auth.js.org/schemas/adapters#custom-models" rel="noopener noreferrer"&gt;extend or customize&lt;/a&gt; the data models yourself.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: If you have an existing database, after replacing the dummy database URI, you can run &lt;code&gt;npx prisma introspect&lt;/code&gt; to generate the &lt;code&gt;schema.prisma&lt;/code&gt; for your database and work from there. Then, you should add the following data models to the generated &lt;code&gt;schema.prisma&lt;/code&gt; file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;

&lt;span class="n"&gt;datasource&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"postgresql"&lt;/span&gt;
  &lt;span class="n"&gt;url&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"DATABASE_URL"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"prisma-client-js"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;                 &lt;span class="n"&gt;Int&lt;/span&gt;       &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;autoincrement&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="nd"&gt;@id&lt;/span&gt;
  &lt;span class="n"&gt;compoundId&lt;/span&gt;         &lt;span class="n"&gt;String&lt;/span&gt;    &lt;span class="nd"&gt;@unique&lt;/span&gt; &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"compound_id"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;userId&lt;/span&gt;             &lt;span class="n"&gt;Int&lt;/span&gt;       &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"user_id"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;providerType&lt;/span&gt;       &lt;span class="n"&gt;String&lt;/span&gt;    &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"provider_type"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;providerId&lt;/span&gt;         &lt;span class="n"&gt;String&lt;/span&gt;    &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"provider_id"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;providerAccountId&lt;/span&gt;  &lt;span class="n"&gt;String&lt;/span&gt;    &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"provider_account_id"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;refreshToken&lt;/span&gt;       &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;   &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"refresh_token"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;accessToken&lt;/span&gt;        &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;   &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"access_token"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;accessTokenExpires&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"access_token_expires"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;createdAt&lt;/span&gt;          &lt;span class="n"&gt;DateTime&lt;/span&gt;  &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;updatedAt&lt;/span&gt;          &lt;span class="n"&gt;DateTime&lt;/span&gt;  &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;@index&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="n"&gt;providerAccountId&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt; &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"providerAccountId"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;@index&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="n"&gt;providerId&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt; &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"providerId"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;@index&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt; &lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"userId"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"accounts"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;           &lt;span class="n"&gt;Int&lt;/span&gt;      &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;autoincrement&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="nd"&gt;@id&lt;/span&gt;
  &lt;span class="n"&gt;userId&lt;/span&gt;       &lt;span class="n"&gt;Int&lt;/span&gt;      &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"user_id"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;expires&lt;/span&gt;      &lt;span class="n"&gt;DateTime&lt;/span&gt;
  &lt;span class="n"&gt;sessionToken&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;   &lt;span class="nd"&gt;@unique&lt;/span&gt; &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"session_token"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;accessToken&lt;/span&gt;  &lt;span class="n"&gt;String&lt;/span&gt;   &lt;span class="nd"&gt;@unique&lt;/span&gt; &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"access_token"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;createdAt&lt;/span&gt;    &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;updatedAt&lt;/span&gt;    &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"sessions"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;            &lt;span class="n"&gt;Int&lt;/span&gt;       &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;autoincrement&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="nd"&gt;@id&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt;          &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
  &lt;span class="n"&gt;email&lt;/span&gt;         &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;   &lt;span class="nd"&gt;@unique&lt;/span&gt;
  &lt;span class="n"&gt;emailVerified&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"email_verified"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;image&lt;/span&gt;         &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
  &lt;span class="n"&gt;createdAt&lt;/span&gt;     &lt;span class="n"&gt;DateTime&lt;/span&gt;  &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;updatedAt&lt;/span&gt;     &lt;span class="n"&gt;DateTime&lt;/span&gt;  &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"users"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;VerificationRequest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;         &lt;span class="n"&gt;Int&lt;/span&gt;      &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;autoincrement&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="nd"&gt;@id&lt;/span&gt;
  &lt;span class="n"&gt;identifier&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;
  &lt;span class="n"&gt;token&lt;/span&gt;      &lt;span class="n"&gt;String&lt;/span&gt;   &lt;span class="nd"&gt;@unique&lt;/span&gt;
  &lt;span class="n"&gt;expires&lt;/span&gt;    &lt;span class="n"&gt;DateTime&lt;/span&gt;
  &lt;span class="n"&gt;createdAt&lt;/span&gt;  &lt;span class="n"&gt;DateTime&lt;/span&gt;  &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"created_at"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;updatedAt&lt;/span&gt;  &lt;span class="n"&gt;DateTime&lt;/span&gt;  &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;@map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"verification_requests"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Let's break it down a bit:&lt;/p&gt;

&lt;p&gt;In the schema file, we defined 4 data models - &lt;code&gt;Account&lt;/code&gt;, &lt;code&gt;Session&lt;/code&gt;, &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;VerificationRequest&lt;/code&gt;. The &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;Account&lt;/code&gt; models are for storing user information, the &lt;code&gt;Session&lt;/code&gt; model is for managing active sessions of the user, and &lt;code&gt;VerificationRequest&lt;/code&gt; is for storing valid tokens that are generated for magic link Email sign in.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;@map&lt;/code&gt; attribute is for mapping the Prisma field name to a database column name, such as &lt;code&gt;compoundId&lt;/code&gt; to &lt;code&gt;compound_id&lt;/code&gt;, which is what &lt;code&gt;next-auth&lt;/code&gt; needs to have it working.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Snake_case" rel="noopener noreferrer"&gt;&lt;em&gt;snake_case&lt;/em&gt;&lt;/a&gt; is often used as a naming convention in database environments, but &lt;a href="https://en.wikipedia.org/wiki/Camel_case" rel="noopener noreferrer"&gt;&lt;em&gt;camelCase&lt;/em&gt;&lt;/a&gt; is how we usually name things in JavaScript and TypeScript. It's perfectly fine to name Prisma fields in &lt;em&gt;snake_case&lt;/em&gt;, but it wouldn't look so nice. :)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next, let's run these commands to populate the database with the tables we need.&lt;/p&gt;

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

npx prisma migrate save --experimental
npx prisma migrate up --experimental


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

&lt;/div&gt;

&lt;p&gt;Then, run this command to generate a Prisma client tailored to the database schema.&lt;/p&gt;

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

npx prisma generate


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

&lt;/div&gt;

&lt;p&gt;Now, if you open up &lt;a href="https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-studio" rel="noopener noreferrer"&gt;Prisma Studio&lt;/a&gt; with the following command, you will be able to inspect all the tables that we just created in the database.&lt;/p&gt;

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

npx prisma studio


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

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FDmeUlem.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%2Fi.imgur.com%2FDmeUlem.png" alt="Prisma studio screenshot"&gt;&lt;/a&gt;Prisma Studio model selection&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Configure &lt;code&gt;next-auth&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Before we start configuring &lt;code&gt;next-auth&lt;/code&gt;, let's create another &lt;code&gt;.env&lt;/code&gt; file in the project root to store secrets that will be used by &lt;code&gt;next-auth&lt;/code&gt; (or rename the &lt;code&gt;.env.example&lt;/code&gt; file from the template, if you cloned the tutorial repo).&lt;/p&gt;

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

SECRET=RAMDOM_STRING
SMTP_HOST=YOUR_SMTP_HOST
SMTP_PORT=YOUR_SMTP_PORT
SMTP_USER=YOUR_SMTP_USERNAME
SMTP_PASSWORD=YOUR_SMTP_PASSWORD
SMTP_FROM=YOUR_REPLY_TO_EMAIL_ADDRESS
GITHUB_SECRET=YOUR_GITHUB_API_CLIENT_SECRET
GITHUB_ID=YOUR_GITHUB_API_CLIENT_ID
DATABASE_URL=postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public


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

&lt;/div&gt;

&lt;p&gt;Now, let's create a new file at &lt;code&gt;/pages/api/auth/[...nextauth].ts&lt;/code&gt; as a "catch-all" &lt;a href="https://nextjs.org/docs/api-routes/introduction" rel="noopener noreferrer"&gt;Next.js API route&lt;/a&gt; for all the requests sent to &lt;code&gt;your-app-url-root/api/auth&lt;/code&gt; (like &lt;code&gt;localhost:3000/api/auth&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Inside the file, first import the essential modules from &lt;code&gt;next-auth&lt;/code&gt;, and define an API handler which passes the request to the &lt;code&gt;NextAuth&lt;/code&gt; function, which sends back a response that can either be an entirely generated login form page or a callback redirect. To connect &lt;code&gt;next-auth&lt;/code&gt; to the database with Prisma, you will also need to import &lt;code&gt;PrismaClient&lt;/code&gt; and initialize a &lt;a href="https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client" rel="noopener noreferrer"&gt;Prisma Client&lt;/a&gt; instance.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextApiHandler&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next&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;NextAuth&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-auth&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;Providers&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-auth/providers&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;Adapters&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-auth/adapters&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PrismaClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// we will define `options` up next&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authHandler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextApiHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;NextAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;authHandler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now let's create the &lt;code&gt;options&lt;/code&gt; object. Here, you can choose from a &lt;a href="https://next-auth.js.org/configuration/providers#sign-in-with-oauth" rel="noopener noreferrer"&gt;wide variety of builtin authentication providers&lt;/a&gt;. In this tutorial, we will use GitHub OAuth and "magic links" Email to authenticate the visitors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3.1: Set up GitHub OAuth
&lt;/h3&gt;

&lt;p&gt;For the builtin OAuth providers like GitHub, you will need a &lt;code&gt;clientId&lt;/code&gt; and a &lt;code&gt;clientSecret&lt;/code&gt;, both of which can be obtained by registering a new OAuth app at Github.&lt;/p&gt;

&lt;p&gt;First, log into your GitHub account, go to &lt;a href="https://github.com/settings/profile" rel="noopener noreferrer"&gt;&lt;em&gt;Settings&lt;/em&gt;&lt;/a&gt;, then navigate to &lt;a href="https://github.com/settings/apps" rel="noopener noreferrer"&gt;&lt;em&gt;Developer Settings&lt;/em&gt;&lt;/a&gt;, then switch to &lt;a href="https://github.com/settings/developers" rel="noopener noreferrer"&gt;&lt;em&gt;OAuth Apps&lt;/em&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%2Fi.imgur.com%2F4eQrMAs.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%2Fi.imgur.com%2F4eQrMAs.png" alt="GitHub OAuth apps"&gt;&lt;/a&gt;GitHub OAuth apps&lt;/p&gt;

&lt;p&gt;Clicking on the &lt;em&gt;Register a new application&lt;/em&gt; button will redirect you to a registration form to fill out some information for your app. The &lt;em&gt;Authorization callback URL&lt;/em&gt; should be the Next.js &lt;code&gt;/api/auth&lt;/code&gt; route that we defined earlier (&lt;code&gt;http://localhost:3000/api/auth&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;An important thing to note here is that the &lt;em&gt;Authorization callback URL&lt;/em&gt; field only supports 1 URL, unlike Auth0, which allows you to add additional callback URLs separated with a comma. This means if you want to deploy your app later with a production URL, you will need to set up a new GitHub OAuth app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FtYtq5fd.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%2Fi.imgur.com%2FtYtq5fd.png" alt="Registering an OAuth app"&gt;&lt;/a&gt;Registering an OAuth app&lt;/p&gt;

&lt;p&gt;Click on the &lt;em&gt;Register Application&lt;/em&gt; button, and then you will be able to find your newly generated Client ID and Client Secret. Copy this info into your &lt;code&gt;.env&lt;/code&gt; file in the root directory.&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%2Fi.imgur.com%2FQwEjV9s.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%2Fi.imgur.com%2FQwEjV9s.png" alt="Obtaining OAuth Client ID and Client Secret"&gt;&lt;/a&gt;Obtaining OAuth Client ID and Client Secret&lt;/p&gt;

&lt;p&gt;Now, let's go back to &lt;code&gt;/api/auth/[...nextauth].ts&lt;/code&gt; and create a new object called &lt;code&gt;options&lt;/code&gt;, and source the GitHub OAuth credentials like below.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;Providers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GitHub&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GITHUB_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GITHUB_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;OAuth providers typically work the same way, so if your choice is &lt;a href="https://next-auth.js.org/configuration/providers#built-in-providers" rel="noopener noreferrer"&gt;supported by &lt;code&gt;next-auth&lt;/code&gt;&lt;/a&gt;, you can configure it the same way as we did with GitHub here. If there is no builtin support, you can still &lt;a href="https://next-auth.js.org/configuration/providers#using-a-custom-provider" rel="noopener noreferrer"&gt;define a custom provider&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3.2: Set up passwordless Email authentication
&lt;/h3&gt;

&lt;p&gt;To allow users to authenticate with magic link Emails, you will need to have access to an SMTP server. These kinds of Emails are considered transactional Emails. If you don't have your own SMTP server or your mail provider has strict restrictions regarding outgoing Emails, I would recommend using &lt;a href="https://sendgrid.com/" rel="noopener noreferrer"&gt;SendGrid&lt;/a&gt;, or alternatively &lt;a href="http://aws.amazon.com/ses/" rel="noopener noreferrer"&gt;Amazon SES&lt;/a&gt;, &lt;a href="http://mailgun.com/" rel="noopener noreferrer"&gt;Mailgun&lt;/a&gt; and &lt;a href="https://www.slant.co/options/465/alternatives/~sendgrid-alternatives" rel="noopener noreferrer"&gt;others&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When you have your SMTP credentials ready, you can put that information into the &lt;code&gt;.env&lt;/code&gt; file, add a &lt;code&gt;Providers.Email({})&lt;/code&gt; to the list of providers, and source the environment variables like below.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// Providers.GitHub ...&lt;/span&gt;
    &lt;span class="nx"&gt;Providers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SMTP_HOST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SMTP_PORT&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SMTP_USER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SMTP_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SMTP_FROM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// The "from" address that you want to use&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Step 3.3: Link up Prisma
&lt;/h3&gt;

&lt;p&gt;The final step for setting up &lt;code&gt;next-auth&lt;/code&gt; is to tell it to use Prisma to talk to the database. For this, we will use the Prisma adapter and add it to the &lt;code&gt;options&lt;/code&gt; object. We will also need a &lt;em&gt;secret&lt;/em&gt; key to sign and encrypt tokens and cookies for &lt;code&gt;next-auth&lt;/code&gt; to work securely - this &lt;em&gt;secret&lt;/em&gt; should also be sourced from environment variables.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Adapters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Adapter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;To summarize, your &lt;code&gt;pages/api/auth/[...nextauth].ts&lt;/code&gt; should look like the following:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextApiHandler&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next&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;NextAuth&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-auth&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;Providers&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-auth/providers&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;Adapters&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-auth/adapters&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PrismaClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authHandler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextApiHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;NextAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;authHandler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;Providers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GitHub&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GITHUB_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GITHUB_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nx"&gt;Providers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SMTP_HOST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SMTP_PORT&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SMTP_USER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SMTP_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SMTP_FROM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Adapters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Adapter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;

  &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Step 4: Implement authentication on the frontend
&lt;/h2&gt;

&lt;p&gt;In the application, you can use &lt;code&gt;next-auth&lt;/code&gt; to check if a visitor has cookies/tokens corresponding to a valid session. If no session can be found, then it means the user is not logged in.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;next-auth&lt;/code&gt;, you have 2 options for checking the sessions - it can be done inside a React component using the &lt;code&gt;useSession()&lt;/code&gt; hook, or on the backend (&lt;code&gt;getServerSideProps&lt;/code&gt; or in API routes) with the helper function &lt;code&gt;getSession()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's have a look at how it works.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 4.1: Checking user sessions with the &lt;code&gt;useSession()&lt;/code&gt; hook
&lt;/h3&gt;

&lt;p&gt;In order to use the hook, you'll need to wrap the component inside a &lt;code&gt;next-auth&lt;/code&gt; &lt;em&gt;provider&lt;/em&gt;. For the authentication flow to work anywhere in your entire Next.js app, create a &lt;a href="https://nextjs.org/docs/advanced-features/custom-app" rel="noopener noreferrer"&gt;new file called &lt;code&gt;/pages/_app.tsx&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next-auth/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppProps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageProps&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;AppProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;session&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now, you can go to &lt;code&gt;/pages/index.tsx&lt;/code&gt;, and import the &lt;code&gt;useSession&lt;/code&gt; hook from the &lt;code&gt;next-auth/client&lt;/code&gt; module. You will also need the &lt;code&gt;signIn&lt;/code&gt; and &lt;code&gt;signOut&lt;/code&gt;functions to implement the authentication interaction. The&lt;code&gt;signIn&lt;/code&gt; function will redirect users to a login form, which is automatically generated by &lt;code&gt;next-auth&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signIn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useSession&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next-auth/client&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;The &lt;code&gt;useSession()&lt;/code&gt; hook returns an array with the first element being the user session, and the second one a boolean indicating the loading status.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IndexPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSession&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;If the &lt;code&gt;session&lt;/code&gt; object is &lt;code&gt;null&lt;/code&gt;, it means the user is not logged in. Additionally, we can obtain the user information from &lt;code&gt;session.user&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Hello, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Sign out&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      You are not logged in! &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;signIn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Sign in&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The finished &lt;code&gt;/pages/index.tsx&lt;/code&gt; file should look like the following.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signIn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useSession&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next-auth/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IndexPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSession&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Hello, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Sign out&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        You are not logged in! &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;signIn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Sign in&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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


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

&lt;/div&gt;

&lt;p&gt;Now, you can spin up the Next.js dev server with &lt;code&gt;npm run dev&lt;/code&gt;, and play with the authentication flow!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4.2: Checking user sessions with &lt;code&gt;getSession()&lt;/code&gt; on the backend
&lt;/h3&gt;

&lt;p&gt;To get user sessions from the backend code, inside either &lt;code&gt;getServerSideProps()&lt;/code&gt; or an API request handler, you will need to use the &lt;code&gt;getSession()&lt;/code&gt; async function.&lt;/p&gt;

&lt;p&gt;Let's create a new &lt;code&gt;/pages/api/secret.ts&lt;/code&gt; file for now like below. The same principles from the frontend apply here - if the user doesn't have a valid session, then it means they are not logged in, in which case we will return a message with a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403" rel="noopener noreferrer"&gt;403 status code&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextApiHandler&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getSession&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next-auth/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secretHandler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextApiHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getSession&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`Welcome to the VIP club, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hold on, you're not allowed in here!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;secretHandler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Go visit &lt;code&gt;localhost:3000/api/secret&lt;/code&gt; without logging in, and you will see something like in the following image.&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%2Fi.imgur.com%2F74G5s1J.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%2Fi.imgur.com%2F74G5s1J.png" alt="403 error if the user is not logged in"&gt;&lt;/a&gt;403 error if the user is not logged in&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;And that's it, authentication is so much easier with &lt;code&gt;next-auth&lt;/code&gt;!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/Ll37bXYmQecEdBpmmM/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/Ll37bXYmQecEdBpmmM/giphy.gif" alt="High five gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope you have enjoyed this tutorial and have learned something useful! You can always find the starter code and the completed project in &lt;a href="https://github.com/hexrcs/prisma-next-auth" rel="noopener noreferrer"&gt;this GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, check out the &lt;a href="https://github.com/catalinmiron/awesome-prisma" rel="noopener noreferrer"&gt;Awesome Prisma list&lt;/a&gt; for more tutorials and starter projects in the Prisma ecosystem!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>authentication</category>
      <category>react</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Complete Introduction to Fullstack, Type-Safe GraphQL (feat. Next.js, Nexus, Prisma)</title>
      <dc:creator>hexrcs</dc:creator>
      <pubDate>Tue, 09 Jun 2020 12:51:14 +0000</pubDate>
      <link>https://dev.to/prisma/complete-introduction-to-fullstack-type-safe-graphql-feat-next-js-nexus-prisma-c5</link>
      <guid>https://dev.to/prisma/complete-introduction-to-fullstack-type-safe-graphql-feat-next-js-nexus-prisma-c5</guid>
      <description>&lt;h1&gt;
  
  
  Complete Introduction to Fullstack, Type-Safe GraphQL (feat. Next.js, Nexus, Prisma)
&lt;/h1&gt;

&lt;p&gt;In this post, you'll learn how to build––from scratch––an entirely type-safe, fullstack web app, using GraphQL with a database attached!&lt;/p&gt;

&lt;p&gt;To follow along with the source code, clone &lt;a href="https://github.com/hexrcs/fullstack-graphql-next-nexus-prisma" rel="noopener noreferrer"&gt;this repo&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🗓 Update 19/11/2020: &lt;em&gt;The tutorial has been updated to use Nexus Schema as the Nexus Framework has been &lt;a href="https://github.com/prisma-labs/graphql-framework-experiment" rel="noopener noreferrer"&gt;discontinued&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Our tech stack
&lt;/h2&gt;

&lt;p&gt;First, let's have a look at our tools of choice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html" rel="noopener noreferrer"&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;&lt;/a&gt; - the programming language for both backend and frontend&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;React&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;Next.js&lt;/strong&gt;&lt;/a&gt; - as the frontend framework and &lt;a href="https://medium.com/the-ideal-system/next-js-is-not-what-you-may-think-it-is-8423172e7401" rel="noopener noreferrer"&gt;&lt;em&gt;middle-end&lt;/em&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://formidable.com/open-source/urql/" rel="noopener noreferrer"&gt;&lt;strong&gt;Urql GraphQL client&lt;/strong&gt;&lt;/a&gt; - the GraphQL client on the frontend&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/a&gt; - the database for the app&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.apollographql.com/docs/apollo-server/" rel="noopener noreferrer"&gt;&lt;strong&gt;Apollo Server&lt;/strong&gt;&lt;/a&gt; - the server framework we'll use to serve the GraphQL API&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nexusjs.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;Nexus Schema&lt;/strong&gt;&lt;/a&gt; - a library for building &lt;em&gt;code-first&lt;/em&gt; GraphQL APIs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client" rel="noopener noreferrer"&gt;&lt;strong&gt;Prisma Client&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://www.prisma.io/docs/reference/api-reference/command-reference/#db-push" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;prisma db push&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; - a toolkit to change the database schema, access, and query the database &lt;em&gt;(Note: &lt;code&gt;prisma db push&lt;/code&gt; is still in a preview state at the moment)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get started! 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0: Install VS Code extensions
&lt;/h2&gt;

&lt;p&gt;Before we start, make sure that you have installed these VS Code extensions for syntax highlighting and auto-formatting - &lt;a href="https://marketplace.visualstudio.com/items?itemName=Prisma.prisma" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt; and &lt;a href="https://marketplace.visualstudio.com/items?itemName=Prisma.vscode-graphql" rel="noopener noreferrer"&gt;GraphQL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UfKxpm8y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/wlX71dw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UfKxpm8y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/wlX71dw.png" alt="Prisma Extension for VS Code" width="800" height="198"&gt;&lt;/a&gt;Prisma Extension for VS Code&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TE2GUIBq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/NlcGhhq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TE2GUIBq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/NlcGhhq.png" alt="GraphQL Extension for VS Code" width="800" height="212"&gt;&lt;/a&gt;GraphQL Extension for VS Code&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Spin up a PostgreSQL database
&lt;/h2&gt;

&lt;p&gt;The first thing you'll need is a PostgreSQL database instance to interact with during development.&lt;/p&gt;

&lt;p&gt;There are many options for this, but Heroku allows us to host PostgreSQL databases for free with minimal setup required. Check out &lt;a href="https://dev.to/prisma/how-to-setup-a-free-postgresql-database-on-heroku-1dc1"&gt;this post&lt;/a&gt; by &lt;a href="https://dev.to/nikolasburk"&gt;Nikolas Burk&lt;/a&gt; guiding you through the process!&lt;/p&gt;

&lt;p&gt;If you have Docker installed and would rather keep your development database local, you can also check out &lt;a href="https://egghead.io/lessons/postgresql-set-up-and-run-a-postgresql-instance-locally-with-docker-compose?pl=build-a-full-stack-app-with-prisma-2-7c81" rel="noopener noreferrer"&gt;this video&lt;/a&gt; I did on how to do this with Docker Compose.&lt;/p&gt;

&lt;p&gt;You will be able to get a PostgreSQL URI in this format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;postgresql://&amp;lt;USER&amp;gt;:&amp;lt;PASSWORD&amp;gt;@&amp;lt;HOST_NAME&amp;gt;:&amp;lt;PORT&amp;gt;/&amp;lt;DB_NAME&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: if you are using Heroku, you'll get a URI with &lt;code&gt;postgres&lt;/code&gt; instead of &lt;code&gt;postgresql&lt;/code&gt; as the protocol. Both formats should work but we'd prefer to use &lt;code&gt;postgresql&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When everything is set up properly, you're good to move on to the next step! 😃&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Create a Next.js project
&lt;/h2&gt;

&lt;p&gt;Now, create a Next.js project with &lt;code&gt;create-next-app&lt;/code&gt; and enter the directory:&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 my-awesome-app &lt;span class="nt"&gt;--use-npm&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; with-typescript
&lt;span class="nb"&gt;cd &lt;/span&gt;my-awesome-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git should be automatically initialized by &lt;code&gt;create-next-app&lt;/code&gt;, and your project structure should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lGAXmLsg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/kzVMkAY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lGAXmLsg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/kzVMkAY.png" alt="Project structure bootstrapped by  raw `create-next-app` endraw " width="800" height="478"&gt;&lt;/a&gt;Project structure bootstrapped by &lt;code&gt;create-next-app&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;create-next-app&lt;/code&gt; might not have the latest TypeScript package pre-installed. If you want to use the latest TypeScript features, run &lt;code&gt;npm install -D typescript@latest&lt;/code&gt; after the project is bootstrapped.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 3: Install Nexus with Prisma
&lt;/h2&gt;

&lt;p&gt;With the Next.js project ready, open a terminal window at the root of the application and install both Nexus Schema and Prisma.&lt;/p&gt;

&lt;p&gt;For Prisma, we need &lt;code&gt;@prisma/client&lt;/code&gt;, &lt;code&gt;@nexus/schema&lt;/code&gt; and &lt;code&gt;nexus-plugin-prisma&lt;/code&gt; as a regular dependencies and &lt;code&gt;@prisma/cli&lt;/code&gt; as a dev dependency.&lt;/p&gt;

&lt;p&gt;Regular dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @prisma/client @nexus/schema nexus-plugin-prisma
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dev dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @prisma/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the dependencies are installed, initialize Prisma in the project.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This command will create a &lt;code&gt;prisma&lt;/code&gt; directory. If you have a look inside, you'll see a &lt;code&gt;.env&lt;/code&gt; file and a &lt;code&gt;schema.prisma&lt;/code&gt; file. The &lt;code&gt;schema.prisma&lt;/code&gt; file will hold the database model and the &lt;code&gt;.env&lt;/code&gt; file will hold the database connection string.&lt;/p&gt;

&lt;p&gt;Because the database connection string contains sensitive information, it's a good practice to &lt;strong&gt;never&lt;/strong&gt; commit this &lt;code&gt;.env&lt;/code&gt; file with Git, so make sure it's also added to the &lt;code&gt;.gitignore&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Adjust the &lt;code&gt;schema.prisma&lt;/code&gt; file to include a &lt;code&gt;User&lt;/code&gt; model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model User {
  id   String @default(cuid()) @id
  name String
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The schema file tells Prisma to use PostgreSQL as the database type, and the database connection URL is defined as an environment variable. It also defines a simple &lt;code&gt;User&lt;/code&gt; data model with an &lt;code&gt;id&lt;/code&gt; and a &lt;code&gt;name&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;Your project should currently look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lJL5s1e2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/riZnypE.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lJL5s1e2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/riZnypE.png" alt="Project structure after creating the  raw `prisma` endraw  directory" width="800" height="478"&gt;&lt;/a&gt;Project structure after creating the &lt;code&gt;prisma&lt;/code&gt; directory&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Wire up Nexus Schema with Next.js
&lt;/h2&gt;

&lt;p&gt;Nexus Schema is a library that allows us to build code-first GraphQL APIs. It's our responsibility to bring along a server to serve that API. For our purposes, we'll use &lt;a href="https://www.apollographql.com/docs/apollo-server/" rel="noopener noreferrer"&gt;Apollo Server&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are several varieties of Apollo Server that are used for various purposes. For our project, we'll want &lt;code&gt;apollo-server-mirco&lt;/code&gt; as it's well-suited to serverless deployments.&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;apollo-server-micro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create a GraphQL endpoint, create a new file in your project at &lt;code&gt;/pages/api/graphql.ts&lt;/code&gt;. Thanks to the powerful &lt;a href="https://nextjs.org/docs/api-routes/introduction" rel="noopener noreferrer"&gt;API routes&lt;/a&gt; in Next.js, the GraphQL server will be accessible at &lt;a href="http://our-app/api/graphql" rel="noopener noreferrer"&gt;&lt;code&gt;http://our-app-domain/api/graphql&lt;/code&gt;&lt;/a&gt; when the Next.js server is started.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;/pages/api/graphql.ts&lt;/code&gt; file, write the following boilerplate code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApolloServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apollo-server-micro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// we'll create these in a second!&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../graphql/schema&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./../../graphql/context&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apolloServer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApolloServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tracing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;apolloServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHandler&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/graphql&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;Since everything inside the &lt;code&gt;/pages/api/&lt;/code&gt; directory is considered as an API route, it's a good idea to implement the actual schema and resolvers outside this directory.&lt;/p&gt;

&lt;p&gt;Now, create a new directory in the project root called &lt;code&gt;/graphql/&lt;/code&gt; and two files within: &lt;code&gt;/graphql/schema.ts&lt;/code&gt; and &lt;code&gt;/graphql/context.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;/graphql/schema.ts&lt;/code&gt;, start by using the &lt;code&gt;makeSchema&lt;/code&gt; function to construct a GraphQL schema with Nexus. We'll also want to use &lt;code&gt;nexus-plugin-prisma&lt;/code&gt; with the &lt;em&gt;CRUD&lt;/em&gt; feature enabled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// graphql/schema.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;objectType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;queryType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mutationType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;makeSchema&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nexus/schema&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;nexusPrisma&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nexus-plugin-prisma&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;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;queryType&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nf"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makeSchema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;nexusPrisma&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;experimentalCRUD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})],&lt;/span&gt;
  &lt;span class="na"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;typegen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;generated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nexus-typegen.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;generated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;schema.graphql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;typegenAutoConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;contextType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Context.Context&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prisma&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;graphql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;context.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Context&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The call to &lt;code&gt;makeSchema&lt;/code&gt; includes a property called &lt;code&gt;plugins&lt;/code&gt;. This is an array of any plugins we want to use with Nexus Schema and, in our case, we want to use &lt;code&gt;nexus-plugin-prisma&lt;/code&gt;. The configuration we have here tells the plugin to use the CRUD feature which is what allows us to have automatically-generated CRUD resolvers for our API. You can &lt;a href="https://nexusjs.org/docs/plugins/prisma/overview" rel="noopener noreferrer"&gt;read more&lt;/a&gt; on the CRUD feature provided by Nexus Schema.&lt;/p&gt;

&lt;p&gt;Next, initialize the &lt;code&gt;PrismaClient&lt;/code&gt; within &lt;code&gt;/graphql/context.ts&lt;/code&gt; and export a function to create the context in Apollo Server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// graphql/context.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PrismaClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The file structure should now look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;my-awesome-app/
├─ components/
├─ graphql/
│  ├─ context.ts
│  ├─ schema.ts
├─ interfaces/
├─ pages/
├─ prisma/
│  ├─ .env
│  ├─ schema.prisma
├─ utils/
├─ next-env.d.ts
├─ package-lock.json
├─ package.json
├─ tsconfig.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these files in place, run the application:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If you go to &lt;a href="http://localhost:3000/api/graphql" rel="noopener noreferrer"&gt;http://localhost:3000/api/graphql&lt;/a&gt;, you'll see the GraphQL Playground up and running (with our "hello world" schema)! 😃&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F76awdex9a446jcazwz25.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F76awdex9a446jcazwz25.png" alt="GraphQL Playground with a hello world schema" width="800" height="554"&gt;&lt;/a&gt;GraphQL Playground with a hello world schema&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Implement your first GraphQL API
&lt;/h2&gt;

&lt;p&gt;With the GraphQL server running in the background and the GraphQL Playground ready at &lt;a href="http://localhost:3000/api/graphql" rel="noopener noreferrer"&gt;http://localhost:3000/api/graphql&lt;/a&gt;, it's time to start implementing the API!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5.1: Define an Object type
&lt;/h3&gt;

&lt;p&gt;Start by defining a &lt;code&gt;User&lt;/code&gt; object type to reflect the database schema. Once defined, add it to the &lt;code&gt;types&lt;/code&gt; array in &lt;code&gt;makeSchema&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// graphql/schema.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;objectType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;queryType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;makeSchema&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nexus/schema&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;objectType&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makeSchema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are typing the code above instead of copy n' pasting, you will notice that VS Code will autocomplete the fields (&lt;code&gt;id&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;) that are available on the &lt;code&gt;User&lt;/code&gt; data model defined earlier in &lt;code&gt;/prisma/schema.prisma&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tip: You can also always invoke intellisense with CTRL + SPACE, in case it doesn't automatically show up sometimes, super helpful!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, go back to the GraphQL Playground and toggle the &lt;em&gt;Schema&lt;/em&gt; side panel - you will see a GraphQL object type &lt;code&gt;User&lt;/code&gt; is generated from the code you just wrote in the &lt;code&gt;/graphql/schema.ts&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5.2: Define the Query type
&lt;/h3&gt;

&lt;p&gt;For the root &lt;code&gt;Query&lt;/code&gt; type, Nexus provides a &lt;code&gt;queryType&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;To query a list of existing users in the database, you can write a resolver for &lt;code&gt;allUsers&lt;/code&gt; field as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;queryType&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nf"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;allUsers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_parent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can do whatever you want in the &lt;code&gt;resolve&lt;/code&gt; function. The Prisma client for your database can be directly accessed as the &lt;code&gt;db&lt;/code&gt; property on the &lt;code&gt;ctx&lt;/code&gt; object. You can read more about the API of Prisma Client in its &lt;a href="https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/crud" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tip: You can always use the intellisense feature in VS Code to explore the APIs of Nexus and Prisma Client!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In addition to manually writing resolvers, the Nexus-Prisma plugin conveniently exposes basic "read" operations on the database on &lt;code&gt;t.crud&lt;/code&gt;. The following code will let you find a &lt;code&gt;User&lt;/code&gt; (or a list of &lt;em&gt;&lt;code&gt;User&lt;/code&gt;s&lt;/em&gt;) from the database directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;queryType&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nf"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;allUsers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_parent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;users&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above will generate a GraphQL root &lt;code&gt;Query&lt;/code&gt; type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;allUsers&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="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UserWhereUniqueInput&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UserWhereUniqueInput&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;before&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UserWhereUniqueInput&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;User&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="k"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UserWhereUniqueInput&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that all the related &lt;code&gt;Input&lt;/code&gt; types are also generated for us for free! 💯&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--drm9f_cO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/EXsOy3B.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--drm9f_cO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/EXsOy3B.png" alt=" raw `Query` endraw  type is generated by Nexus" width="800" height="477"&gt;&lt;/a&gt;&lt;code&gt;Query&lt;/code&gt; type is generated by Nexus&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5.3: Define the Mutation type
&lt;/h3&gt;

&lt;p&gt;Similar to the &lt;code&gt;Query&lt;/code&gt; type, a &lt;code&gt;Mutation&lt;/code&gt; type can be defined with the &lt;code&gt;mutationType&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;😈 Let's have some fun and create a &lt;code&gt;bigRedButton&lt;/code&gt; mutation to destroy all user data in the database.&lt;/p&gt;

&lt;p&gt;We also have access to the &lt;code&gt;t.crud&lt;/code&gt; helper here, which exposes the basic "create", "update" and "delete" operations on the database. We then must add &lt;code&gt;Mutation&lt;/code&gt; to the &lt;code&gt;types&lt;/code&gt; array in &lt;code&gt;makeSchema&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;objectType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;queryType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mutationType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;makeSchema&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nexus/schema&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Mutation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mutationType&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nf"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bigRedButton&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;String&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_parent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteMany&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; user(s) destroyed. Thanos will be proud.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createOneUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteOneUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteManyUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateOneUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateManyUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makeSchema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will generate a GraphQL schema like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;bigRedButton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createOneUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UserCreateInput&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;deleteOneUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UserWhereUniqueInput&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;deleteManyUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UserWhereInput&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BatchPayload&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;updateOneUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UserUpdateInput&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UserWhereUniqueInput&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;updateManyUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UserUpdateManyMutationInput&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UserWhereInput&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BatchPayload&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aoRLBJst--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/7mfLl68.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aoRLBJst--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/7mfLl68.png" alt=" raw `Mutation` endraw  type is generated by Nexus" width="800" height="477"&gt;&lt;/a&gt;&lt;code&gt;Mutation&lt;/code&gt; type is generated by Nexus&lt;/p&gt;

&lt;p&gt;Now, our simple but fully-featured GraphQL API is ready! 🥳&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Initialize the database
&lt;/h2&gt;

&lt;p&gt;Before you can do anything with your GraphQL API, you'll need to create tables in the database corresponding to the Prisma schema file.&lt;/p&gt;

&lt;p&gt;This can be done by manually connecting to the database and running SQL commands, but I'll show you how to do it with the &lt;code&gt;prisma db push&lt;/code&gt; commnand - the database tool that's part of Prisma 2.&lt;/p&gt;

&lt;p&gt;First, save the initial changes of our &lt;code&gt;schema.prisma&lt;/code&gt; file with the command below. At the moment, the &lt;a href="https://www.prisma.io/docs/reference/api-reference/command-reference/#db-push" rel="noopener noreferrer"&gt;&lt;code&gt;prisma db push&lt;/code&gt; command&lt;/a&gt; is still in a preview state, so the extra flag &lt;code&gt;--preview-feature&lt;/code&gt; flag is needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx prisma db push &lt;span class="nt"&gt;--preview-feature&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Awesome! With the database prepared, it's time to go back to &lt;a href="http://localhost:3000/api/graphql" rel="noopener noreferrer"&gt;http://localhost:3000/api/graphql&lt;/a&gt;, and have some fun with the your first GraphQL API with Nexus. Let me give you an example to play with!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createOneUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--apStJija--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/160bZim.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--apStJija--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/160bZim.png" alt="Testing out user creation 😎" width="800" height="477"&gt;&lt;/a&gt;Testing out user creation 😎&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Set up Urql GraphQL client with Next.js
&lt;/h2&gt;

&lt;p&gt;We'll use &lt;em&gt;&lt;a href="https://formidable.com/open-source/urql/" rel="noopener noreferrer"&gt;Urql&lt;/a&gt;&lt;/em&gt; as the GraphQL client on the frontend, but you can use any library you like.&lt;/p&gt;

&lt;p&gt;First, install the dependencies:&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;graphql-tag next-urql react-is urql isomorphic-unfetch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, create a new file at &lt;code&gt;/pages/_app.tsx&lt;/code&gt;. This is a &lt;a href="https://nextjs.org/docs/advanced-features/custom-app" rel="noopener noreferrer"&gt;special Next.js component&lt;/a&gt; that will be used to initialize all pages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;withUrqlClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NextUrqlAppContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next-urql&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;NextApp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppProps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isomorphic-unfetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// the URL to /api/graphql&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GRAPHQL_ENDPOINT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`http://localhost:3000/api/graphql`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageProps&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;AppProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getInitialProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextUrqlAppContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;NextApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInitialProps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;appProps&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;withUrqlClient&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_ssrExchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_ctx&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="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GRAPHQL_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;fetch&lt;/span&gt;
&lt;span class="p"&gt;}))(&lt;/span&gt;
  &lt;span class="c1"&gt;// @ts-ignore&lt;/span&gt;
  &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! Now you can use the GraphQL client in any page in your Next.js app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Use the GraphQL client
&lt;/h2&gt;

&lt;p&gt;First, create a TSX file at &lt;code&gt;/components/AllUsers.tsx&lt;/code&gt;. This file will have a component that performs an &lt;code&gt;allUsers&lt;/code&gt; GraphQL query and renders the result as a list. This way, we can use the component to fetch all the user info from our PostgreSQL database.&lt;/p&gt;

&lt;p&gt;You can create the query first, for example, with the following code. By using &lt;code&gt;gql&lt;/code&gt;, the GraphQL VS Code extension will be able to identify the template string as a GraphQL query and apply nice syntax highlighting to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;graphql-tag&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;urql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AllUsersQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  query {
    allUsers {
      id
      name
    }
  }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since it's known that the data you are going to get is an array of &lt;code&gt;User&lt;/code&gt; objects (thank you, GraphQL schema!), you can also define a new type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AllUsersData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;allUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}[];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create the React component that will be using the query.&lt;/p&gt;

&lt;p&gt;The component encapsulates the following logic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the query is still in a &lt;em&gt;fetching&lt;/em&gt; state, the text "Loading..." will be returned&lt;/li&gt;
&lt;li&gt;If an error is occurred during the process, we will display the error&lt;/li&gt;
&lt;li&gt;If the query is no longer &lt;em&gt;fetching&lt;/em&gt; and there's no error, the data will be used to render a list of users
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AllUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AllUsersData&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AllUsersQuery&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetching&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetching&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Oh no... &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;There are &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;allUsers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; user(s) in the database:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;allUsers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now, save the TSX file, and mount it onto the home page &lt;code&gt;/pages/index.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/Layout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AllUsers&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/AllUsers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IndexPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Home | Next.js + TypeScript Example"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello Next.js 👋&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/about"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;About&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* === Tada! === */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AllUsers&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Time to spin up the Next.js dev server!&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Voilà! The user list is rendered! 🥳&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bCEPfv51--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/l3XM26c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bCEPfv51--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/l3XM26c.png" alt="User list is rendered on our home page" width="800" height="478"&gt;&lt;/a&gt;A user list is rendered on our home page&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 9: Auto-generate &lt;code&gt;useQuery&lt;/code&gt; hooks and types
&lt;/h2&gt;

&lt;p&gt;Instead of manually defining all the types we expect to receive via GraphQL, we can also use a very cool package &lt;em&gt;&lt;a href="https://graphql-code-generator.com/" rel="noopener noreferrer"&gt;GraphQL Code Generator&lt;/a&gt;&lt;/em&gt; to generate types directly from the Nexus GraphQL endpoint. This way, you essentially only have to define the types once in the &lt;code&gt;schema.prisma&lt;/code&gt; file as the single-source-of-truth, then all types you'll use in the application can be derived from that schema with little manual effort! 🎉&lt;/p&gt;

&lt;p&gt;First, copy and refactor the GraphQL queries from the TSX files into the &lt;code&gt;graphql&lt;/code&gt; directory. With the example from Step 8, create a new file at &lt;code&gt;/graphql/queries.graphql.ts&lt;/code&gt; and copy the query from &lt;code&gt;/components/AllUsers.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;graphql-tag&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AllUsersQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  query AllUsers {
    allUsers {
      id
      name
    }
  }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Separating GraphQL operations from components makes it easier to navigate the codebase.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next, install the packages needed by &lt;code&gt;graphql-code-generator&lt;/code&gt; as dev dependencies:&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; &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    @graphql-codegen/cli &lt;span class="se"&gt;\&lt;/span&gt;
    @graphql-codegen/typescript &lt;span class="se"&gt;\&lt;/span&gt;
    @graphql-codegen/typescript-operations &lt;span class="se"&gt;\&lt;/span&gt;
    @graphql-codegen/typescript-urql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, create a &lt;code&gt;codegen.yml&lt;/code&gt; file in the project root with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;overwrite&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://localhost:3000/api/graphql'&lt;/span&gt; &lt;span class="c1"&gt;# GraphQL endpoint via the nexus dev server&lt;/span&gt;
&lt;span class="na"&gt;documents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;graphql/**/*.graphql.ts'&lt;/span&gt; &lt;span class="c1"&gt;# parse graphql operations in matching files&lt;/span&gt;
&lt;span class="na"&gt;generates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;generated/graphql.tsx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# location for generated types, hooks and components&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;typescript'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;typescript-operations'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;typescript-urql'&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;withComponent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="c1"&gt;# we'll use Urql client with hooks instead&lt;/span&gt;
      &lt;span class="na"&gt;withHooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The configs above will tell &lt;code&gt;graphql-code-generator&lt;/code&gt; to pull the GraphQL schema from &lt;code&gt;http://localhost:3000/api/graphql&lt;/code&gt;, then generate types, Urql &lt;code&gt;useQuery&lt;/code&gt; hooks into a file located at &lt;code&gt;/generated/graphql.tsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Cool, let the code generation begin (in &lt;em&gt;watch&lt;/em&gt; mode)!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;npx graphql-codegen --watch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see some nice, written-by-a-robot code in &lt;code&gt;/generated/graphql.tsx&lt;/code&gt;. How neat!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b7WbqG7C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/d7PCb0a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b7WbqG7C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/d7PCb0a.png" alt="A  raw `useAllUsersQuery` endraw  hook and all the types are generated by GraphQL Code Generator" width="800" height="478"&gt;&lt;/a&gt;A &lt;code&gt;useAllUsersQuery&lt;/code&gt; hook and all the types are generated by GraphQL Code Generator&lt;/p&gt;

&lt;p&gt;Now, you can go back to &lt;code&gt;components/AllUsers.tsx&lt;/code&gt;, and replace the manually written &lt;code&gt;AllUsersData&lt;/code&gt; type, the GraphQL query, and the &lt;code&gt;useQuery&lt;/code&gt; hook, with what's in the &lt;code&gt;/generated/graphql.tsx&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAllUsersQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../generated/graphql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AllUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAllUsersQuery&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetching&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetching&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Oh no... &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;There are &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;allUsers&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; user(s) in the database:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;allUsers&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Revisit the index page of the app at &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;, everything works like a charm! 🙌&lt;/p&gt;

&lt;p&gt;To make the development experience even better, let's optimize the NPM scripts for the project.&lt;/p&gt;

&lt;p&gt;First, install the &lt;em&gt;&lt;a href="https://github.com/kimmobrunfeldt/concurrently" rel="noopener noreferrer"&gt;Concurrently&lt;/a&gt;&lt;/em&gt; NPM module, which is a great tool for running multiple CLI watchers at the same time:&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; &lt;span class="nt"&gt;-D&lt;/span&gt; concurrently
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, replace &lt;code&gt;dev&lt;/code&gt; script in the &lt;code&gt;package.json&lt;/code&gt; file with the following:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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;"concurrently -r &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;npx nexus dev&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;npx next&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;npx graphql-codegen --watch&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can use a single &lt;code&gt;npm run dev&lt;/code&gt; command to launch Nexus, Next.js, and GraphQL Code Generator, all at the same time!&lt;/p&gt;

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

&lt;p&gt;I hope you have enjoyed this tutorial and have learned something useful! You can find the source code in &lt;a href="https://github.com/hexrcs/fullstack-graphql-next-nexus-prisma" rel="noopener noreferrer"&gt;this GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, check out the &lt;a href="https://github.com/catalinmiron/awesome-prisma" rel="noopener noreferrer"&gt;Awesome Prisma list&lt;/a&gt; for more tutorials and starter projects in the Prisma ecosystem!&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>typescript</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>🔥 Debugging Frontend Apps inside VS Code!</title>
      <dc:creator>hexrcs</dc:creator>
      <pubDate>Wed, 22 Jan 2020 09:19:15 +0000</pubDate>
      <link>https://dev.to/methodcoder/debugging-frontend-app-inside-vs-code-4cg0</link>
      <guid>https://dev.to/methodcoder/debugging-frontend-app-inside-vs-code-4cg0</guid>
      <description>&lt;p&gt;Did you know that we can also debug client-side, frontend code right from VS Code, using its powerful built-in debugger? 🤯&lt;/p&gt;

&lt;p&gt;In this 94-second video, we'll use the Chrome debugger extension to debug an event handler in a React app.&lt;/p&gt;

&lt;p&gt;Although the demo is in React, the same knowledge applies to any frontend apps! 🥳&lt;/p&gt;




&lt;p&gt;This video is part of my new 6-minute crash course series on YouTube 👉 &lt;a href="https://www.youtube.com/playlist?list=PLyNmzPg2z6Og_dyyeVviQxefnG06rq_FK" rel="noopener noreferrer"&gt;&lt;strong&gt;Debugging in VS Code&lt;/strong&gt; 🔥&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Like this video?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I'm also on Twitter: &lt;a href="https://twitter.com/hexrcs" rel="noopener noreferrer"&gt;@hexrcs&lt;/a&gt;&lt;/em&gt;&lt;br&gt;&lt;em&gt;Check out my YouTube Channel: &lt;a href="http://methodcoder.com/" rel="noopener noreferrer"&gt;The Method Coder&lt;/a&gt;&lt;/em&gt;&lt;br&gt;&lt;em&gt;You can find me at my homepage as well: &lt;a href="https://www.xiaoru.li" rel="noopener noreferrer"&gt;xiaoru.li&lt;/a&gt;&lt;/em&gt;&lt;br&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>vscode</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>💪 React + MobX Crash Course (in 5 pics!)</title>
      <dc:creator>hexrcs</dc:creator>
      <pubDate>Tue, 03 Dec 2019 13:25:39 +0000</pubDate>
      <link>https://dev.to/methodcoder/react-mobx-crash-course-in-5-pics-2m3b</link>
      <guid>https://dev.to/methodcoder/react-mobx-crash-course-in-5-pics-2m3b</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on Twitter as a thread: &lt;a href="https://twitter.com/hexrcs/status/1201593792417144833" rel="noopener noreferrer"&gt;https://twitter.com/hexrcs/status/1201593792417144833&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;State management in React apps can be a hard thing to do.&lt;/p&gt;

&lt;p&gt;Are you having a hard time wrapping your head around React state management, and getting tired of writing boilerplate for Redux?&lt;/p&gt;

&lt;p&gt;Let's check out &lt;a href="https://github.com/mobxjs/mobx" rel="noopener noreferrer"&gt;MobX&lt;/a&gt; - everything becomes so simple and effortless 😃&lt;/p&gt;

&lt;p&gt;👇 Here's a 5-minute React + MobX crash course for you! 🥳&lt;/p&gt;

&lt;h2&gt;
  
  
  1 - MobX Concepts
&lt;/h2&gt;

&lt;p&gt;MobX is a "reactive" state management library.&lt;/p&gt;

&lt;p&gt;We directly mutate the state. Because we use MobX to observe and track mutations, the UI will be auto-updated, like cell updates in Excel. Network requests can also auto-send when conditions are met.&lt;/p&gt;

&lt;p&gt;Everything is automatic!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WBGaappo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/9zqUM2a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WBGaappo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/9zqUM2a.png" alt="MobX Concepts" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2 - Decorator and observable
&lt;/h2&gt;

&lt;p&gt;We normally use the decorator syntax to mark fields in a class "MobX observables" - easy to use or read. This way, normal JS stuff gets "enhanced" (eg. a JS number becomes an observable that can be tracked).&lt;/p&gt;

&lt;p&gt;Grouping state logic in a "store" also makes our code more modular.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qvZ-CzhE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/69Buoof.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qvZ-CzhE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/69Buoof.png" alt="Decorator and observable" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Action and Computed
&lt;/h2&gt;

&lt;p&gt;In addition to &lt;code&gt;@observable&lt;/code&gt;, we also have:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@computed&lt;/code&gt; - derived state from other observable/computed that can be used just like observables. Getter syntax is required. The derivation is automatic.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@action&lt;/code&gt; - batched state mutations. Reactions will only be triggered by the update when the action completes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N7iKiL82--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/WRTYfQi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N7iKiL82--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/WRTYfQi.png" alt="Action and Computed" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Reactions
&lt;/h2&gt;

&lt;p&gt;We can use &lt;code&gt;autorun()&lt;/code&gt; or &lt;code&gt;when()&lt;/code&gt; to watch observables and perform effects when there's update&lt;/p&gt;

&lt;p&gt;&lt;code&gt;autorun()&lt;/code&gt; takes a callback and runs it each time any observable used in it gets updated. (Remember to do the clean-up!)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;when()&lt;/code&gt; only runs the callback once, when a condition is met.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TBMUwMvB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/kGKGSjY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TBMUwMvB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/kGKGSjY.png" alt="Reactions" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Using MobX with React
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;mobx-react&lt;/code&gt; binding lets us use MobX with React without writing &lt;code&gt;autorun&lt;/code&gt; functions to rerender components.&lt;/p&gt;

&lt;p&gt;We use &lt;code&gt;@observer&lt;/code&gt; as a decorator to a class component, or HoC wrapping a function component. This creates an observer component that tracks observables needed during render, and auto rerenders whenever an update is observed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hsG4tNuY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/jTaDvPn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hsG4tNuY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/jTaDvPn.png" alt="Using MobX with React" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;And that's it, everything you need to start using MobX effectively. Pretty effortless, isn't it? 😃&lt;/p&gt;

&lt;p&gt;If you are curious how MobX works under the hood, check out this amazing talk "&lt;a href="https://www.youtube.com/watch?v=P_WqKZxpX8g" rel="noopener noreferrer"&gt;Reinventing MobX&lt;/a&gt;" by Max Gallo.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Credits
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Thank you so much &lt;a href="https://twitter.com/mweststrate" rel="noopener noreferrer"&gt;Michel Weststrate&lt;/a&gt; for creating this amazing library, and helping to review this crash course! 🙌&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Thread crash course format inspired by &lt;a href="https://twitter.com/chrisachard" rel="noopener noreferrer"&gt;Chris Achard&lt;/a&gt; 😁 Check out his excellent React/Redux, Git crash courses!)&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;While you are still here, if you've got 13 more minutes and are interested in learning the new hot framework Svelte, I've also got a crash course with companion videos here 👉 &lt;a href="https://dev.to/hexrcs/svelte-crash-course-with-pics-27cc"&gt;&lt;strong&gt;Svelte Crash Course&lt;/strong&gt; 🔥&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've also got another &lt;a href="https://dev.to/hexrcs/graphql-crash-course-in-10-pics-3b04"&gt;&lt;strong&gt;GraphQL Crash Course&lt;/strong&gt; 🔥&lt;/a&gt; 👈 Check it out!&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Like this post?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I'll be posting more on Twitter: &lt;a href="https://twitter.com/hexrcs" rel="noopener noreferrer"&gt;@hexrcs&lt;/a&gt;&lt;/em&gt;&lt;br&gt;&lt;em&gt;You can also find me at my homepage: &lt;a href="https://www.xiaoru.li" rel="noopener noreferrer"&gt;xiaoru.li&lt;/a&gt;&lt;/em&gt;&lt;br&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>🔥 GraphQL Crash Course (in 10 pics!)</title>
      <dc:creator>hexrcs</dc:creator>
      <pubDate>Sun, 03 Nov 2019 10:34:24 +0000</pubDate>
      <link>https://dev.to/methodcoder/graphql-crash-course-in-10-pics-3b04</link>
      <guid>https://dev.to/methodcoder/graphql-crash-course-in-10-pics-3b04</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on Twitter as a thread: &lt;a href="https://twitter.com/hexrcs/status/1190332090149150720" rel="noopener noreferrer"&gt;https://twitter.com/hexrcs/status/1190332090149150720&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Always wanted to use GraphQL for your new projects, but never got time to learn how it works? 😃&lt;/p&gt;

&lt;p&gt;Let's start the week with some new GraphQL knowledge in hand! 🙌&lt;/p&gt;

&lt;p&gt;👇 Here's a 10-minute GraphQL crash course for you! 🥳&lt;/p&gt;

&lt;h2&gt;
  
  
  1 - How GraphQL works
&lt;/h2&gt;

&lt;p&gt;GraphQL is a query language for making flexible API calls.&lt;/p&gt;

&lt;p&gt;We describe what we want in a single request with nested fields, then we will receive a data payload of the exact shape.&lt;/p&gt;

&lt;p&gt;No need to make many small requests to stitch data together or over-fetch unwanted parts!&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%2Fi.imgur.com%2FZalpOf7.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%2Fi.imgur.com%2FZalpOf7.png" alt="How GraphQL works"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2 - A GraphQL Query Exchange
&lt;/h2&gt;

&lt;p&gt;GraphQL is not a library, but a language spec.&lt;/p&gt;

&lt;p&gt;We send structured queries as POST or GET requests. The server checks if they're valid with a predefined schema, runs corresponding resolver functions to perform operations, then prepares the data to be returned to 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%2Fi.imgur.com%2FcIqFAw8.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%2Fi.imgur.com%2FcIqFAw8.png" alt="A GraphQL Query Exchange"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3 - The GraphQL Schema
&lt;/h2&gt;

&lt;p&gt;GraphQL schema defines the structure of valid queries and the return data types of them. It's the protocol the client &amp;amp; server use to communicate under.&lt;/p&gt;

&lt;p&gt;They're strongly typed, can be nested. In addition to the most common "object" types, the schema also supports unions, enums, interfaces, etc.&lt;/p&gt;

&lt;p&gt;There are 3 operation types in GraphQL - &lt;code&gt;query&lt;/code&gt;, &lt;code&gt;mutation&lt;/code&gt;, or &lt;code&gt;subscription&lt;/code&gt;. &lt;code&gt;query&lt;/code&gt; is the most commonly used operation.&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%2Fi.imgur.com%2FzyTgxJr.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%2Fi.imgur.com%2FzyTgxJr.png" alt="The GraphQL Schema"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4 - Argument
&lt;/h2&gt;

&lt;p&gt;Some queries allow us to pass in arguments in order to eg. filter results. The schema defines all valid arguments.&lt;/p&gt;

&lt;p&gt;On the backend, we need to have corresponding resolvers to fulfill those conditioned queries.&lt;/p&gt;

&lt;p&gt;NOTE: GraphQL has no builtin comparison operators or functions like &lt;code&gt;&amp;gt;&lt;/code&gt; or &lt;code&gt;TOP&lt;/code&gt;, &lt;code&gt;LIMIT&lt;/code&gt; in SQL! Those additional features &lt;strong&gt;must&lt;/strong&gt; be implemented in the resolvers. Most GraphQL frameworks however already ship with those utility resolvers.&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%2Fi.imgur.com%2FjldtXcJ.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%2Fi.imgur.com%2FjldtXcJ.png" alt="Arguments"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5 - Alias
&lt;/h2&gt;

&lt;p&gt;Sometimes in a query, we select the same field multiple times, but each time with a different argument (like in the pic). This will cause naming conflicts, so we need to assign aliases to the fields.&lt;/p&gt;

&lt;p&gt;Aliases can be added to any field.&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%2Fi.imgur.com%2FTEp0pnR.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%2Fi.imgur.com%2FTEp0pnR.png" alt="Alias"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6 - Fragment
&lt;/h2&gt;

&lt;p&gt;We can wrap "subfields" into a Fragment and reuse them with the spread operator in selections. Useful when we select the same fields over and over again. Think of it as a JS object for GraphQL field names that can be destructured!&lt;/p&gt;

&lt;p&gt;The Fragment is sent to the server alongside the main operation in the &lt;code&gt;query&lt;/code&gt; field of the HTTP request payload.&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%2Fi.imgur.com%2FVBCpQ0L.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%2Fi.imgur.com%2FVBCpQ0L.png" alt="Fragment"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7 - Variable
&lt;/h2&gt;

&lt;p&gt;Using GraphQL variables makes it easy to modularize and share/reuse our prewritten query code. We declare them at the beginning of a query, and are allowed to assign default values to them. The variables can be nested, just like a normal JSON object.&lt;/p&gt;

&lt;p&gt;Noticed the GraphQL request payload in the pic of section &lt;em&gt;2 - A GraphQL Query Exchange&lt;/em&gt;? This is what the "variables" field is for.&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%2Fi.imgur.com%2FCZ9IXJ1.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%2Fi.imgur.com%2FCZ9IXJ1.png" alt="Variable"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8 - Interface
&lt;/h2&gt;

&lt;p&gt;Interfaces in a GraphQL schema allow us to flexibly create and use complex data types in an OOP manner.&lt;/p&gt;

&lt;p&gt;Types can implement (multiple) interfaces.&lt;/p&gt;

&lt;p&gt;When the return type is an interface, we can use the &lt;code&gt;on&lt;/code&gt; keyword to conditionally access fields of a specific implementation.&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%2Fi.imgur.com%2FR2W9Kax.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%2Fi.imgur.com%2FR2W9Kax.png" alt="Interface"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  9 - Mutation Operation
&lt;/h2&gt;

&lt;p&gt;Contrary to queries, a Mutation operation is used to change the serverside data - eg. to create an account, generate auth token, or add data entries.&lt;/p&gt;

&lt;p&gt;Like queries, we can supply arguments to a mutation. The mutation also returns value, so don't forget to select the fields we need!&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%2Fi.imgur.com%2FguzWD0X.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%2Fi.imgur.com%2FguzWD0X.png" alt="Mutation Operation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  10 - Subscription Operation
&lt;/h2&gt;

&lt;p&gt;Instead of sending queries over HTTP back and forth, GraphQL also has a Subscription operation type for creating WebSocket connections, so the server can push continuous updates to the client.&lt;/p&gt;

&lt;p&gt;Particularly useful for real-time apps like 💹 stock market or 💬 messaging apps.&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%2Fi.imgur.com%2FXZ5jtC2.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%2Fi.imgur.com%2FXZ5jtC2.png" alt="Subscription Operation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  BONUS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Online Playgrounds
&lt;/h3&gt;

&lt;p&gt;Many GraphQL frameworks come with a web IDE with autocompletion support and interactive schema lookups like &lt;a href="https://github.com/graphql/graphiql" rel="noopener noreferrer"&gt;GraphiQL&lt;/a&gt; or &lt;a href="https://github.com/prisma-labs/graphql-playground" rel="noopener noreferrer"&gt;GraphQL Playground&lt;/a&gt;. Make use of them when debugging your queries! ✨ &lt;/p&gt;

&lt;p&gt;You can also create your own playground online with &lt;a href="https://codesandbox.io/" rel="noopener noreferrer"&gt;CodeSandbox&lt;/a&gt; by selecting the &lt;em&gt;Apollo GraphQL Server&lt;/em&gt; sandbox.&lt;/p&gt;

&lt;p&gt;However, if you are as lazy as me 🤪, there are also a few zero-config public GraphQL APIs to play with online 👉 &lt;a href="https://apis.guru/graphql-apis/" rel="noopener noreferrer"&gt;https://apis.guru/graphql-apis/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources
&lt;/h3&gt;

&lt;p&gt;There's a &lt;a href="https://ladybug.dev/episode/what-the-heck-is-graphql/" rel="noopener noreferrer"&gt;great episode&lt;/a&gt; on GraphQL from the &lt;a href="https://ladybug.dev" rel="noopener noreferrer"&gt;Ladybug Podcast&lt;/a&gt;, do check it out!&lt;/p&gt;

&lt;p&gt;I hope you have enjoyed this GraphQL crash course! 😁 Have a great and productive week ahead! 🙌&lt;/p&gt;

&lt;p&gt;(Thread crash course format inspired by &lt;a href="https://twitter.com/chrisachard" rel="noopener noreferrer"&gt;@chrisachard&lt;/a&gt; 😁 Check out his excellent React/Redux, Git crash courses!)&lt;/p&gt;




&lt;p&gt;While you are still here, if you've got 13 more minutes and are interested in learning the new hot framework Svelte, I've also got a crash course with companion videos here 👉 &lt;a href="https://dev.to/hexrcs/svelte-crash-course-with-pics-27cc"&gt;&lt;strong&gt;Svelte Crash Course&lt;/strong&gt; 🔥&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Like this post?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I'll be posting more on Twitter: &lt;a href="https://twitter.com/hexrcs" rel="noopener noreferrer"&gt;@hexrcs&lt;/a&gt;&lt;/em&gt;&lt;br&gt;&lt;em&gt;You can also find me at my homepage: &lt;a href="https://www.xiaoru.li" rel="noopener noreferrer"&gt;xiaoru.li&lt;/a&gt;&lt;/em&gt;&lt;br&gt;&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>javascript</category>
    </item>
    <item>
      <title>⏰ Svelte Crash Course (in 10 pics!)</title>
      <dc:creator>hexrcs</dc:creator>
      <pubDate>Sat, 19 Oct 2019 19:58:42 +0000</pubDate>
      <link>https://dev.to/methodcoder/svelte-crash-course-with-pics-27cc</link>
      <guid>https://dev.to/methodcoder/svelte-crash-course-with-pics-27cc</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on Twitter as a thread: &lt;a href="https://twitter.com/hexrcs/status/1185186492982943744" rel="noopener noreferrer"&gt;https://twitter.com/hexrcs/status/1185186492982943744&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Huge Update: Video Version Now Available!
&lt;/h3&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://www.youtube.com/playlist?list=PLyNmzPg2z6OiXylVCmsUOpaXdZm7lrzCt" rel="noopener noreferrer"&gt;YouTube Playlist&lt;/a&gt; - Only 13 minutes in total!&lt;/strong&gt; 🥳&lt;/p&gt;




&lt;p&gt;Always wanted to check out Svelte (aka. "the next big thing in web dev") but never got time for it? ⏰&lt;/p&gt;

&lt;p&gt;🔥 I've got a 10-minute crash course for you! 👇&lt;/p&gt;

&lt;p&gt;(Spoiler alert: Svelte is so intuitive and easy to use that you may feel like you already know it! 🥳)&lt;/p&gt;

&lt;h2&gt;
  
  
  1 - How Svelte works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Compiler: Doesn't ship a Svelte "library" to users, but build-time optimized plain JS&lt;/li&gt;
&lt;li&gt;Components: App is made up of composable UI elements&lt;/li&gt;
&lt;li&gt;Reactive: Event/User interaction triggers chain of state changes, auto-updating components throughout the entire app&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h2&gt;
  
  
  2 - UI Is a Component Tree
&lt;/h2&gt;

&lt;p&gt;A &lt;em&gt;component&lt;/em&gt; defines how your app should interpret some abstract "state" values, so that it can turn them into DOM elements in your browser, and ultimately pixels on your 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%2Fi.imgur.com%2FPVb4NIr.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%2Fi.imgur.com%2FPVb4NIr.png" alt="UI Is a Component Tree"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3 - The Anatomy of a Svelte Component
&lt;/h2&gt;

&lt;p&gt;Each &lt;code&gt;.svelte&lt;/code&gt; file contains a single component, consisting of 3 parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; is component logic in JS&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; is CSS styling, scoped and applied to only the current component&lt;/li&gt;
&lt;li&gt;Svelte template, based on HTML but can use custom components and inline logic (like JSX)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FZZvHUCb.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%2Fi.imgur.com%2FZZvHUCb.png" alt="The Anatomy of a Svelte Component"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4 - The Svelte Template
&lt;/h2&gt;

&lt;p&gt;The Svelte template allows us to use our own custom components in addition to HTML elements. The &lt;code&gt;.svelte&lt;/code&gt; file extension is optional if there's no ambiguity, but the first letter of a custom component MUST be in uppercase.&lt;/p&gt;

&lt;p&gt;We can use JS expressions inside curly braces &lt;code&gt;{ }&lt;/code&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%2Fi.imgur.com%2FrQUIWsK.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%2Fi.imgur.com%2FrQUIWsK.png" alt="The Svelte Template"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5 - Setting "Props"
&lt;/h2&gt;

&lt;p&gt;A common way to "control" how a child component behaves is to pass data into it as props (properties).&lt;/p&gt;

&lt;p&gt;To accept a prop, expose a variable with &lt;code&gt;export&lt;/code&gt;. It's important to use &lt;code&gt;let&lt;/code&gt; because &lt;code&gt;const&lt;/code&gt; is not reassignable.&lt;/p&gt;

&lt;p&gt;Setting a prop is just like doing regular HTML.&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%2Fi.imgur.com%2FJtHdsPk.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%2Fi.imgur.com%2FJtHdsPk.png" alt="Setting "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6 - Updating Component States
&lt;/h2&gt;

&lt;p&gt;User actions trigger events. &lt;code&gt;on:&lt;/code&gt; lets us listen to events and fire functions to update states. State changes will auto-update the UI.&lt;/p&gt;

&lt;p&gt;Data generally flows from a parent to a child, but we can use &lt;code&gt;bind:&lt;/code&gt; to simplify the state-update logic by allowing two-way data flow.&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%2Fi.imgur.com%2Fj3MARwh.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%2Fi.imgur.com%2Fj3MARwh.png" alt="Updating Component States"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7 - &lt;code&gt;$:&lt;/code&gt; Reactive Statements
&lt;/h2&gt;

&lt;p&gt;"Reactive statements" are those statements marked by &lt;code&gt;$:&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Svelte analyzes which variables they depend on. When any of those dependencies changes, the corresponding reactive statements will be rerun. Very useful for declaring derived states, or triggering "side effects".&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%2Fi.imgur.com%2FCUjXeFs.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%2Fi.imgur.com%2FCUjXeFs.png" alt="Reactive Statements"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8 - Reactive State "Store"
&lt;/h2&gt;

&lt;p&gt;A reactive "store" makes it easy to share states across many components. It can exist in a separate JS file. To create a store, just wrap &lt;code&gt;writable&lt;/code&gt; around a value.&lt;/p&gt;

&lt;p&gt;In a component, we prefix store names with a &lt;code&gt;$&lt;/code&gt; in order to directly use or update them. Compiler magic!&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%2Fi.imgur.com%2FkHV9MTq.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%2Fi.imgur.com%2FkHV9MTq.png" alt="Reactive State "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  9 - Conditional Rendering And Lists
&lt;/h2&gt;

&lt;p&gt;We can conditionally render elements with Svelte's template via &lt;code&gt;{#if}&lt;/code&gt; and optionally &lt;code&gt;{:else}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To render everything in a list, we have &lt;code&gt;{#each}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Remember to always close a block with &lt;code&gt;{/if}&lt;/code&gt; or &lt;code&gt;{/each}&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;(Should've used &lt;code&gt;&amp;lt;ol&amp;gt;&lt;/code&gt; in the example, but I wanted to show how index- access works.)&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%2Fi.imgur.com%2FlkdkmAR.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%2Fi.imgur.com%2FlkdkmAR.png" alt="Conditional Rendering And Lists"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  10 - Elegant Async/Await
&lt;/h2&gt;

&lt;p&gt;It's super easy to do asynchronous stuff like API requests with Svelte.&lt;/p&gt;

&lt;p&gt;We can simply &lt;code&gt;{#await}&lt;/code&gt; a Promise to resolve, displaying a &lt;em&gt;"loading"&lt;/em&gt; placeholder before the result is ready.&lt;/p&gt;

&lt;p&gt;Note that we await the Promise in the template section, so no &lt;code&gt;await&lt;/code&gt; keyword in &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&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%2Fi.imgur.com%2F6OPtzdV.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%2Fi.imgur.com%2F6OPtzdV.png" alt="Elegant Async/Await"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  BONUS - Animated Transitions
&lt;/h2&gt;

&lt;p&gt;Svelte comes with neat animated transitions built-in. Try giving your components a &lt;code&gt;transition:fly&lt;/code&gt; property! There're also other types like fade, slide, etc. You can also use &lt;code&gt;in:&lt;/code&gt; &lt;code&gt;out:&lt;/code&gt; to separately define intro/outros.&lt;/p&gt;

&lt;p&gt;Attached to the transition prop are the params.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  👆 That's All, Folks!
&lt;/h2&gt;

&lt;p&gt;That's it - everything you need to get started with Svelte! 😁&lt;/p&gt;

&lt;p&gt;We covered a lot in this crash course, from the most fundamental concepts to topics that might even be considered intermediate or advanced in other frameworks (eg. API requests and animated transitions).&lt;/p&gt;

&lt;p&gt;Now it's your turn to play with Svelte and build something cool. The &lt;a href="https://svelte.dev/repl" rel="noopener noreferrer"&gt;Svelte REPL&lt;/a&gt; is a great place to start!&lt;/p&gt;

&lt;p&gt;Have fun! 🥳&lt;/p&gt;

&lt;p&gt;(Thread crash course format inspired by &lt;a href="https://twitter.com/chrisachard" rel="noopener noreferrer"&gt;@chrisachard&lt;/a&gt; 😁 Check out his excellent React/Redux, Git crash courses!)&lt;/p&gt;

&lt;h2&gt;
  
  
  PS
&lt;/h2&gt;

&lt;p&gt;Because Svelte is so expressive, I &lt;a href="https://twitter.com/hexrcs/status/1180226461665566721" rel="noopener noreferrer"&gt;joked the other day&lt;/a&gt; that Svelte devs count "characters of code", instead of "lines of code"...&lt;/p&gt;

&lt;p&gt;True that! Here are a few tweet-sized Svelte applets Tomasz Łakomy (&lt;a href="https://twitter.com/tlakomy" rel="noopener noreferrer"&gt;@tlakomy&lt;/a&gt;) and I (&lt;a href="https://twitter.com/hexrcs" rel="noopener noreferrer"&gt;@hexrcs&lt;/a&gt;) have been playing with -&lt;/p&gt;

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

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



&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;p&gt;So, what's the most complex Svelte app that we can fit in a tweet? 😁&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Like this post?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I'll be posting more on Twitter: &lt;a href="https://twitter.com/hexrcs" rel="noopener noreferrer"&gt;@hexrcs&lt;/a&gt;&lt;/em&gt;&lt;br&gt;&lt;em&gt;You can also find me at my homepage: &lt;a href="https://www.xiaoru.li" rel="noopener noreferrer"&gt;xiaoru.li&lt;/a&gt;&lt;/em&gt;&lt;br&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>svelte</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>5 Visual Studio Code Tricks to Boost Your Productivity</title>
      <dc:creator>hexrcs</dc:creator>
      <pubDate>Thu, 08 Aug 2019 08:48:09 +0000</pubDate>
      <link>https://dev.to/hexrcs/5-visual-studio-code-tricks-to-boost-your-productivity-27a4</link>
      <guid>https://dev.to/hexrcs/5-visual-studio-code-tricks-to-boost-your-productivity-27a4</guid>
      <description>&lt;p&gt;VS Code is perhaps the most popular free and open-source code editor/lightweight IDE in the world right now. Here are 5 tricks guaranteed to boost your productivity!&lt;/p&gt;

&lt;h2&gt;
  
  
  #1 - Refactoring With "Rename Symbol"
&lt;/h2&gt;

&lt;p&gt;We don't always give variables, functions or attribute keys the right name they deserve when we first come up with them. Quite often, when we are doing refactoring, we need to rename some of those to better ones.&lt;/p&gt;

&lt;p&gt;Say we want to change a dictionary/object &lt;code&gt;foo&lt;/code&gt; to &lt;code&gt;counter&lt;/code&gt; in our code, but it has already been used numerous times throughout the entire project, across many different files. We also would like to change its attribute key &lt;code&gt;bar&lt;/code&gt; to &lt;code&gt;value&lt;/code&gt;, so that we have &lt;code&gt;counter.value&lt;/code&gt; instead of &lt;code&gt;foo.bar&lt;/code&gt;. How do we proceed?&lt;/p&gt;

&lt;p&gt;A naive way to do that is to simply to do a global search-and-replace via the search panel (&lt;code&gt;shift + cmd + F&lt;/code&gt; on macOS, or &lt;code&gt;shift + ctrl + F&lt;/code&gt; on Windows and Linux). That can be swift, but can also be unsafe - if we happen to have another variable called &lt;code&gt;food&lt;/code&gt;, then the simple replacement would take effect on this variable too. &lt;code&gt;counterd&lt;/code&gt;, oops!&lt;/p&gt;

&lt;p&gt;These named entities are called "symbols". And the most straightforward and "correct" way to do this is to use the "rename symbol" feature in VS Code. Place the cursor on the "symbols" that we want to rename, then hit &lt;code&gt;F2&lt;/code&gt; (also on macOS). We will be greeted with a text field next to the symbol we want to rename. This way, all references to this name throughout the entire project will be correctly renamed. If we use this on a React component, the JSX markup tag will be renamed too!&lt;/p&gt;

&lt;h2&gt;
  
  
  #2 - Shortcuts For Editing
&lt;/h2&gt;

&lt;p&gt;An editor is not only where we type things - but also where we move chunks of text around.&lt;/p&gt;

&lt;p&gt;Have you noticed that if you hit the standard copy/paste/cut shortcuts without selecting anything, VS Code will invoke that action on the whole line? This is great for editing entire lines of text.&lt;/p&gt;

&lt;p&gt;There are also other shortcuts dedicated to duplicating and moving lines around.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;alt + up&lt;/code&gt; or &lt;code&gt;alt + down&lt;/code&gt; will simply move the line your cursor is currently placed on up or down. &lt;code&gt;shift + alt + up&lt;/code&gt; or &lt;code&gt;shift + alt + down&lt;/code&gt; will duplicate the line and place it above or below the current line. These shortcuts also work when you have selected multiple lines. On some Linux distros though, these combinations might conflict with the default systemwide keymapping. In that case, you will have to reassign them in VS Code's settings. &lt;/p&gt;

&lt;p&gt;The best thing ever however, is &lt;code&gt;shift + ctrl + cmd + right/left&lt;/code&gt; for expanding or shrinking block selection. &lt;em&gt;Try it out in the middle of a nested code block and you will know what I mean!&lt;/em&gt; The Windows/Linux equivalent is &lt;code&gt;shift + alt + right/left&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  #3 - Multi Cursor Magic
&lt;/h2&gt;

&lt;p&gt;One of my favorite productivity trick in VS Code is its multi cursor support. If you have used &lt;a href="https://www.sublimetext.com/" rel="noopener noreferrer"&gt;Sublime&lt;/a&gt; before, you already know how dope this is!&lt;/p&gt;

&lt;p&gt;First of all, we can use &lt;code&gt;alt + mouse click&lt;/code&gt; to insert cursors. If you made a mistake somewhere, you can use &lt;code&gt;cmd + U&lt;/code&gt; or &lt;code&gt;ctrl + U&lt;/code&gt; to undo the cursor insertion. If the text blocks we want to multi-select are already neatly aligned vertically, we can just use &lt;code&gt;cmd + alt + up&lt;/code&gt; or &lt;code&gt;cmd + alt + down&lt;/code&gt; (replace &lt;code&gt;cmd&lt;/code&gt; with &lt;code&gt;ctrl&lt;/code&gt; on Windows or Linux) to insert cursors directly above or below the current position.&lt;/p&gt;

&lt;p&gt;If you want to select the next occurrence of the word (text separated by spaces or special characters) currently under cursor or text of the current selection, &lt;code&gt;cmd + D&lt;/code&gt; will do the job.&lt;/p&gt;

&lt;p&gt;Super neat for doing mass rename, delete or copy-paste, especially when working with markup languages!&lt;/p&gt;

&lt;h2&gt;
  
  
  #4 - Fast Keyboard Navigation
&lt;/h2&gt;

&lt;p&gt;Navigating with the keyboard is a breeze. You can use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ctrl + G&lt;/code&gt; (on macOS too) to &lt;em&gt;Go To Line...&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ctrl + P&lt;/code&gt; (replace &lt;code&gt;ctrl&lt;/code&gt; with &lt;code&gt;cmd&lt;/code&gt; on macOS this time!) to &lt;em&gt;Go To File...&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ctrl + shift + O&lt;/code&gt; (replace &lt;code&gt;ctrl&lt;/code&gt; with &lt;code&gt;cmd&lt;/code&gt; on macOS) to &lt;em&gt;Go To Symbol...&lt;/em&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Man, I love the third one! It will bring you right to where you declared that function or variable - the symbol. You can then take it from there. 😉&lt;/p&gt;

&lt;p&gt;Another nice shortcut is &lt;code&gt;ctrl + -&lt;/code&gt; or &lt;code&gt;shift + ctrl + -&lt;/code&gt; on Mac (&lt;code&gt;alt + left/right&lt;/code&gt; on Windows/Linux) to just jump back or forth to previous cursor locations, ideal if combined with those &lt;em&gt;Go To&lt;/em&gt; shortcuts!&lt;/p&gt;

&lt;h2&gt;
  
  
  #5 - DIY Code Snippets
&lt;/h2&gt;

&lt;p&gt;If you have been using VS Code for a while, you may have got some code snippet extensions already installed from the marketplace. Code snippets are shorthands that you can type to expand to entire pieces of code. They are also often smart enough to place your cursor right at the key positions where you can directly change the placeholder function name or similar things.&lt;/p&gt;

&lt;p&gt;But, the code snippets that suit you the best are always going to be handmade and homebrew. Making our own code snippets for VS Code is not that hard at all!&lt;/p&gt;

&lt;p&gt;Just go to the &lt;em&gt;Code &amp;gt; Preferences &amp;gt; User Snippets&lt;/em&gt; on a Mac or &lt;em&gt;File &amp;gt; Preferences &amp;gt; User Snippets&lt;/em&gt; on a Windows/Linux, and you can select a language (or global scope) you can write your own snippets!&lt;/p&gt;

&lt;p&gt;Snippets follow this format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Name of the snippet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prefix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;helo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// the shorthand to invoke the snippet&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;print('Hello, $1');&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Prints 'Hello, blahblahblah' to terminal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the &lt;code&gt;$1&lt;/code&gt;, &lt;code&gt;$2&lt;/code&gt; etc. simply means placeholder key positions which you can use &lt;code&gt;Tab&lt;/code&gt; key to jump to when the snippet is invoked. To move the cursor outside the snippet and make &lt;code&gt;Tab&lt;/code&gt; key go back to normal, just press &lt;code&gt;Esc&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus - Install The IntelliCode Extension
&lt;/h2&gt;

&lt;p&gt;Microsoft has recently launched a more advanced IntelliSense extension for VS Code, powered by machine learning. &lt;a href="https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.vscodeintellicode" rel="noopener noreferrer"&gt;Check it out from their extension marketplace!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The extension currently supports JavaScript, TypeScript, Python, and Java. Having coded with IntelliCode since its preview release, this little extension has been a huge time + frustration saver for me! :)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.xiaoru.li/post/vscode-tricks/" rel="noopener noreferrer"&gt;on my blog&lt;/a&gt;, where I publish random stuff on web dev, flutter and sometimes ML every two weeks or so.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can also find me on Twitter &lt;a href="https://twitter.com/hexrcs" rel="noopener noreferrer"&gt;@hexrcs&lt;/a&gt; :)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>vscode</category>
      <category>tutorial</category>
      <category>tools</category>
    </item>
    <item>
      <title>Become a Command-Line Ninja with These Shortcuts</title>
      <dc:creator>hexrcs</dc:creator>
      <pubDate>Tue, 18 Jun 2019 16:28:11 +0000</pubDate>
      <link>https://dev.to/hexrcs/become-a-terminal-ninja-with-these-shortcuts-48bp</link>
      <guid>https://dev.to/hexrcs/become-a-terminal-ninja-with-these-shortcuts-48bp</guid>
      <description>&lt;p&gt;I've often found myself in such a frustrating situation, where I have to replace &lt;em&gt;one&lt;/em&gt; keyword in the middle of a looong shell command that I just copied and pasted into the terminal (from StackOverflow or course 😅). Jumping over words with &lt;code&gt;Alt-Arrow&lt;/code&gt; doesn't work on all machines; how many left arrows and backspaces do I have to press, in order to replace that &lt;code&gt;path/to/file&lt;/code&gt; or &lt;code&gt;username&lt;/code&gt; in that genius command I stole from that SO answer??&lt;/p&gt;

&lt;p&gt;Finally, I sat myself down to do some research on how to properly practice Ninjutsu in the terminal. As it turns out, roaming inside that command-line environment is not that difficult at all!&lt;/p&gt;

&lt;p&gt;I'm primarily a &lt;a href="https://www.zsh.org" rel="noopener noreferrer"&gt;Z-Shell&lt;/a&gt; user, so this article will be more focused on ZSH. The shortcuts we are going to see here, however, should mostly work in BASH as well (sorry I don't use FISH or other shells ).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fun fact: shell key bindings actually defaults to "emacs mode"! You may have already discovered this if you are an emacs user. But for us mere mortals (or &lt;em&gt;VIM-mortals&lt;/em&gt;), let's carry on and learn something new!&lt;/p&gt;

&lt;p&gt;In fact, if you are more comfortable with VI/VIM, you can even switch to VI-bindings from the standard emacs one - use &lt;code&gt;set -o vi&lt;/code&gt; to test it out! (You might need a plugin or two to give you hints whether you are in &lt;em&gt;edit&lt;/em&gt; or &lt;em&gt;normal&lt;/em&gt; mode though. &lt;a href="https://ohmyz.sh/" rel="noopener noreferrer"&gt;Oh-My-Zsh&lt;/a&gt; has a &lt;a href="https://github.com/robbyrussell/oh-my-zsh/tree/master/plugins/vi-mode" rel="noopener noreferrer"&gt;plugin&lt;/a&gt; for this!)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Navigation
&lt;/h2&gt;

&lt;p&gt;Let's jump right in with the navigation shortcuts. Here's a little list of the useful ones:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Shortcut&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl-A&lt;/td&gt;
&lt;td&gt;Jump to the beginning of line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl-E&lt;/td&gt;
&lt;td&gt;Jump to end of line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl-B&lt;/td&gt;
&lt;td&gt;Move back by one character&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl-F&lt;/td&gt;
&lt;td&gt;Move forward by one character&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Meta-B&lt;/td&gt;
&lt;td&gt;Jump back by one word&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Meta-F&lt;/td&gt;
&lt;td&gt;Jump forward by one word&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note that what the Meta key actually is may vary on different setups (OS + terminal simulator). You might find &lt;code&gt;Alt&lt;/code&gt; working on your system as the Meta key, or the &lt;code&gt;Command&lt;/code&gt; key (if you are using iTerm on macOS, you can change Meta key binding in "Preferences"). However, if all fails, try pressing &lt;code&gt;ESC&lt;/code&gt; then release (not using it as a modifier), followed by the other key - this should work universally as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Editing
&lt;/h2&gt;

&lt;p&gt;Here's a little list of default key bindings for editing:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Shortcut&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl-U&lt;/td&gt;
&lt;td&gt;Cut current line*&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Meta-W&lt;/td&gt;
&lt;td&gt;Cut everything before the cursor (multi-line!)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl-K&lt;/td&gt;
&lt;td&gt;Cut everything after the cursor on current line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl-W&lt;/td&gt;
&lt;td&gt;Cut the previous word&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Meta-D&lt;/td&gt;
&lt;td&gt;Cut the next word&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl-Y&lt;/td&gt;
&lt;td&gt;Paste the stuff just cut (doesn't use OS clipboard)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ctrl-_&lt;/td&gt;
&lt;td&gt;Undo last change&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;* This shortcut cuts everything &lt;em&gt;before&lt;/em&gt; the cursor in BASH.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;I never knew that I can undo in the terminal!&lt;/em&gt;&lt;/strong&gt; How do you undo on Android BTW? 🤨&lt;/p&gt;

&lt;h2&gt;
  
  
  Searching and History
&lt;/h2&gt;

&lt;p&gt;Something you might not know is that shells &lt;em&gt;default to log&lt;/em&gt; every command that you've ever executed if you didn't opt-out. For ZSH, that logbook is kept under &lt;code&gt;~/.zsh_history&lt;/code&gt; (or &lt;code&gt;~/.bash_history&lt;/code&gt; for BASH). This is actually a pretty neat feature, allowing us to search from previous commands and reuse them anytime to save time. (If you are feeling like to go incognito, you may wanna set &lt;code&gt;HISTSIZE = 1&lt;/code&gt; in your &lt;code&gt;.zshrc&lt;/code&gt; to limit the history storing to only 1 record. &lt;code&gt;HISTSIZE = 0&lt;/code&gt; doesn't seem to work though.)&lt;/p&gt;

&lt;p&gt;To enter search mode, press &lt;code&gt;Ctrl-R&lt;/code&gt;. Now type the keyword that you are looking for. Press &lt;code&gt;Ctrl-R&lt;/code&gt; again to "find next".&lt;/p&gt;

&lt;p&gt;You can exit the search mode anytime by trying to edit the current displaying search result, directly with the shortcuts we've mentioned above. Of course, you can abort with &lt;code&gt;Ctrl-C&lt;/code&gt; as well!&lt;/p&gt;

&lt;p&gt;To iterate through the previous commands though, we don't need to enter search mode - just use &lt;code&gt;Ctrl-P&lt;/code&gt; to show the &lt;em&gt;p&lt;/em&gt;-revious, or &lt;code&gt;Ctrl-N&lt;/code&gt; to show the &lt;em&gt;n&lt;/em&gt;-ext line!&lt;/p&gt;

&lt;h2&gt;
  
  
  More Cool Stuff
&lt;/h2&gt;

&lt;p&gt;Instead of the &lt;code&gt;clear&lt;/code&gt; command, shortcut &lt;code&gt;Ctrl-L&lt;/code&gt; is another way to &lt;strong&gt;clear the screen&lt;/strong&gt;. It also leaves the line you are working on intact, so if you are in the middle of typing a long command but suddenly find the littered terminal screen is super distracting, you can hit &lt;code&gt;Ctrl-L&lt;/code&gt; to clean up, without having to retype the command.&lt;/p&gt;

&lt;p&gt;Ever wanted to &lt;strong&gt;type multiple lines&lt;/strong&gt; into ZSH then execute in one single setting, just like copy &amp;amp; pasting some multi-line shell snippets? &lt;code&gt;Ctrl-V Ctrl-J&lt;/code&gt; will do the trick! (&lt;code&gt;Ctrl-V&lt;/code&gt; is "quoted-insert", which &lt;em&gt;inserts&lt;/em&gt; instead of &lt;em&gt;interprets&lt;/em&gt; the next input; &lt;code&gt;Ctrl-J&lt;/code&gt; prints the ASCII symbol &lt;code&gt;LF&lt;/code&gt;, the Unix "next-line".)&lt;/p&gt;

&lt;h2&gt;
  
  
  Even Cooler - DIY! 😋
&lt;/h2&gt;

&lt;p&gt;In ZSH, you can always obtain a list of the current key bindings with a simple &lt;code&gt;bindkey&lt;/code&gt; command. A BASH equivalent would be &lt;code&gt;bind -P&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In addition to the ability of switching to VIM mode, if are using ZSH and would like to customize your key bindings, you can easily do so by declaring stuff like &lt;code&gt;bindkey "^[X" zle-command&lt;/code&gt; (zle, &lt;a href="http://zsh.sourceforge.net/Guide/zshguide04.html" rel="noopener noreferrer"&gt;&lt;em&gt;The Z-Shell Line Editor&lt;/em&gt;&lt;/a&gt; is the line editor behind our beloved ZSH). A list of &lt;code&gt;zle-command&lt;/code&gt;s can be obtained with &lt;code&gt;zle -al&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I hope you have enjoyed this post, and have learned something useful, my fellow ninja! 🥳 &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.xiaoru.li/post/shell-shortcuts/" rel="noopener noreferrer"&gt;on my blog&lt;/a&gt;, where I publish random stuff on web dev, flutter and sometimes ML every two weeks or so.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can also find me on Twitter &lt;a href="https://twitter.com/hexrcs" rel="noopener noreferrer"&gt;@hexrcs&lt;/a&gt; :)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>shell</category>
      <category>productivity</category>
      <category>zsh</category>
      <category>unix</category>
    </item>
    <item>
      <title>Fun with JavaScript Regex</title>
      <dc:creator>hexrcs</dc:creator>
      <pubDate>Fri, 24 May 2019 10:09:12 +0000</pubDate>
      <link>https://dev.to/hexrcs/fun-with-javascript-regex-101c</link>
      <guid>https://dev.to/hexrcs/fun-with-javascript-regex-101c</guid>
      <description>&lt;p&gt;Regex, or regular expression in its full name, can feel like some kind of scary dark witchcraft if you are not familiar with it. You know those magic spells are powerful for pattern matching and string parsing, but those weird-looking question marks, slashes, and asterisks are just plain gibberish to an untrained mind.&lt;/p&gt;

&lt;p&gt;Not all regex are equal. The regex we use in programming today comes in all kinds of syntax flavors. However, the most popular ones nowadays are mostly derivatives of &lt;a href="https://en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions" rel="noopener noreferrer"&gt;Perl's regex syntax&lt;/a&gt;. If you have mastered one regex dialect (like the Javascript one we are going to play with today, which is 99% identical to Dart's regex syntax), picking up other dialects like Python's or Java's would be trivial. So now, let's have some regex fun!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started!
&lt;/h2&gt;

&lt;p&gt;In Javascript, a "regex pattern" is a class of objects, which we can initialize either with the &lt;code&gt;new&lt;/code&gt; keyword or a simpler regex literal (note the lack of quotation marks).&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;regex0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// regex constructor&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;regex1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/,/&lt;/span&gt; &lt;span class="c1"&gt;// regex literal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two &lt;code&gt;RegExp&lt;/code&gt; objects above are equivalent - they both represent the "pattern" of a single comma.&lt;/p&gt;

&lt;p&gt;So now we've defined a pattern, how do we use it? If what concerns us is only whether a pattern exists in a string or not, we can simply run the &lt;code&gt;test&lt;/code&gt; method on a &lt;code&gt;RegExp&lt;/code&gt; object.&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;str0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`1,000,000,000 is like, tres comas.`&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want to find the location of the pattern's occurrence, we can run the &lt;code&gt;exec&lt;/code&gt; method, like, executing the regex on this string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; [ ',', index: 1, input: '1,000,000,000 is like, tres comas.' ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's some cool info, but it only returns the index of the first match. Hmm, maybe running &lt;code&gt;exec()&lt;/code&gt; multiple times will do the trick, like pulling out data from an iterator?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; [ ',', index: 1, input: '1,000,000,000 is like, tres comas.' ]&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; [ ',', index: 1, input: '1,000,000,000 is like, tres comas.' ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Oops, nope! Well, we are partially right though - the &lt;code&gt;exec()&lt;/code&gt; method &lt;em&gt;is&lt;/em&gt; indeed stateful, and this &lt;em&gt;is&lt;/em&gt; the correct way to iterate through matches. The problem actually lies within that regex pattern we defined.&lt;/p&gt;

&lt;h2&gt;
  
  
  Regex Flags
&lt;/h2&gt;

&lt;p&gt;Flags let us toggle options of how the searching or matching should be carried out, and are part of the regex pattern.&lt;/p&gt;

&lt;p&gt;What we need in the last example is a &lt;em&gt;global&lt;/em&gt; flag &lt;code&gt;g&lt;/code&gt;, which tells the regex engine to do a "global" search while not just stop at the first match (like the examples above). &lt;code&gt;regex2&lt;/code&gt; now will return null when the iteration is complete, then restart from index &lt;code&gt;0&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;regex2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/,/g&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; [ ',', index: 1, input: '1,000,000,000 is like, tres comas.' ]&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; [ ',', index: 5, input: '1,000,000,000 is like, tres comas.' ]&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; [ ',', index: 9, input: '1,000,000,000 is like, tres comas.' ]&lt;/span&gt;
&lt;span class="c1"&gt;// let's only run 3 times for now&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's an interesting thing to observe - each &lt;code&gt;RegExp&lt;/code&gt; object has an attribute called &lt;code&gt;lastIndex&lt;/code&gt;, making it stateful. However, the object itself doesn't remember which string is passed into the &lt;code&gt;exec&lt;/code&gt; method. Right now, our &lt;code&gt;regex2&lt;/code&gt; object has its &lt;code&gt;lastIndex&lt;/code&gt; set to &lt;code&gt;10&lt;/code&gt; - if we swap &lt;code&gt;str0&lt;/code&gt; with another one, the matching will start from index &lt;code&gt;10&lt;/code&gt; instead of &lt;code&gt;0&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; 10&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;str1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`This, is, cool.`&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; null, because the searching starts at index 10.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other useful flags are: &lt;code&gt;i&lt;/code&gt; which makes the search case-insensitive, &lt;code&gt;m&lt;/code&gt; which basically ignores newlines and does multi-line searches, and other less used ones. A new &lt;em&gt;dotAll&lt;/em&gt; &lt;code&gt;s&lt;/code&gt; flag has been added to the ECMAScript 2018 this year - this is a very helpful addition since the dot character (&lt;code&gt;.&lt;/code&gt;) now finally matches &lt;em&gt;all&lt;/em&gt; characters in the string, including the &lt;code&gt;\n&lt;/code&gt; newline characters and co. This new flag is supported by Chrome &lt;a href="https://www.chromestatus.com/feature/5644209772036096" rel="noopener noreferrer"&gt;since version 62&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now let's see what all those question marks, slashes and asterisks are actually about!&lt;/p&gt;

&lt;h2&gt;
  
  
  Dealing with Wildcards
&lt;/h2&gt;

&lt;p&gt;If you are familiar with terminal emulators in either UNIX- or Windows-style, you have probably dealt with Wildcards before. You know how to use &lt;code&gt;rm -f *.gif&lt;/code&gt; on Mac or Linux to delete all GIFs in the current directory with no questions asked, use &lt;code&gt;del *.gif /q&lt;/code&gt; on your Windows box to do the same. Well, it is important to know that wildcards in Perl-like regular expressions work in other ways.&lt;/p&gt;

&lt;p&gt;We have only one wildcard character in Regex - the period &lt;code&gt;.&lt;/code&gt; (aka the dot). This character pattern represents one single unknown character but doesn't match a newline character (&lt;code&gt;\n&lt;/code&gt;), so &lt;code&gt;/c.t/&lt;/code&gt; matches string &lt;code&gt;cat&lt;/code&gt; and doesn't match &lt;code&gt;c\nt&lt;/code&gt;. It basically works like the &lt;code&gt;?&lt;/code&gt; wildcard you are familiar with inside command lines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repetition Qualifiers (aka. Quantifiers)
&lt;/h2&gt;

&lt;p&gt;So how do want to match many unknown characters? This is where repetition qualifiers come in.&lt;/p&gt;

&lt;p&gt;Asterisk &lt;code&gt;*&lt;/code&gt; represents &lt;em&gt;0 or more&lt;/em&gt; characters, &lt;code&gt;?&lt;/code&gt; means &lt;em&gt;0 or 1&lt;/em&gt; characters, and &lt;code&gt;+&lt;/code&gt; means &lt;em&gt;1 or more&lt;/em&gt; characters. &lt;/p&gt;

&lt;p&gt;So for example, &lt;code&gt;essential&lt;/code&gt; can be matched with &lt;code&gt;/es.*sential/&lt;/code&gt; (&lt;em&gt;0&lt;/em&gt; extra characters in this case), &lt;code&gt;/es.+ential/&lt;/code&gt; (&lt;em&gt;1&lt;/em&gt; extra here), &lt;code&gt;/es.?ential/&lt;/code&gt; (&lt;em&gt;1&lt;/em&gt; extra character), or obviously &lt;code&gt;/.*/&lt;/code&gt;. Repetition qualifier works with specific characters too, which allows &lt;code&gt;/ess?enstial/&lt;/code&gt; to both match &lt;code&gt;essential&lt;/code&gt; and &lt;code&gt;esential&lt;/code&gt; but not any other strings.&lt;/p&gt;

&lt;p&gt;What's more, you can DIY the range of the repetition - at least &lt;em&gt;n&lt;/em&gt; to at most &lt;em&gt;m&lt;/em&gt; -  with &lt;code&gt;{n,m}&lt;/code&gt;, or specify the exact amount of occurrences with &lt;code&gt;{n}&lt;/code&gt;. We can also match &lt;em&gt;n&lt;/em&gt; to infinity (greater than or equal to &lt;em&gt;n&lt;/em&gt;) occurrences with &lt;code&gt;{n,}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;essential&lt;/code&gt; can be matched with &lt;code&gt;/es{2}ential/&lt;/code&gt;, &lt;code&gt;1000101&lt;/code&gt; and &lt;code&gt;1000000101&lt;/code&gt; can both be matched with &lt;code&gt;10{3,6}101&lt;/code&gt; but &lt;code&gt;10101&lt;/code&gt; can not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sometimes We Need to Escape
&lt;/h2&gt;

&lt;p&gt;Sometimes, we need to match characters like &lt;code&gt;{&lt;/code&gt; or &lt;code&gt;*&lt;/code&gt; in our strings too - we can use backslash &lt;code&gt;\&lt;/code&gt; to escape those characters. In JavaScript, the special characters to escape are &lt;code&gt;\ / [ { ( ? + * | . ^ $&lt;/code&gt;. Interestingly, &lt;code&gt;] } )&lt;/code&gt; are not special characters, but trying to escaping them is not harmful. You can also escape normal characters, but you have to be careful since, in regex, there are character classes (like &lt;code&gt;\d&lt;/code&gt; for all number characters) that are written like escapes but are not - you can match &lt;code&gt;/\o/&lt;/code&gt; with &lt;code&gt;/dog/&lt;/code&gt; but not &lt;code&gt;/\d/&lt;/code&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Sets and Classes
&lt;/h2&gt;

&lt;p&gt;Character class makes our life easier when we want to match characters from a specific set. For example, if we want to match numbers in an ID string, we could simply use &lt;code&gt;\d&lt;/code&gt; to represent that number - essentially like a dot wildcard but only for numbers.&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;regex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\d&lt;/span&gt;&lt;span class="sr"&gt;+/g&lt;/span&gt; &lt;span class="c1"&gt;// the string must contain numbers&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;str0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1234&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;str1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;D1234&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;str2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;D&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; true&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; true&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also use a more flexible set notation &lt;code&gt;[0-9]&lt;/code&gt; to replace &lt;code&gt;\d&lt;/code&gt; - range 0 to 9. Following this "range" logic, for basic Latin letters we can also do &lt;code&gt;[a-z]&lt;/code&gt; or &lt;code&gt;[A-Z]&lt;/code&gt;, or simply &lt;code&gt;[a-zA-Z]&lt;/code&gt;. These are actually just predefined shorthands to simplify &lt;code&gt;[0123456789]&lt;/code&gt; or &lt;code&gt;[abcdef...]&lt;/code&gt;. If you are matching something from the extended Latin alphabet, you'll need to add the extra letters in manually. For example, &lt;code&gt;[a-zA-ZüöäÜÖÄß]&lt;/code&gt; for German. You get the idea 😉.&lt;/p&gt;

&lt;p&gt;You can also use &lt;code&gt;^&lt;/code&gt; inside the brackets as a negation operator - it negates all the rules inside the brackets - &lt;code&gt;[^0-9]&lt;/code&gt; will match everything except numbers.&lt;/p&gt;

&lt;p&gt;It is important to notice that special characters like &lt;code&gt;$&lt;/code&gt; or &lt;code&gt;.&lt;/code&gt; don't mean anything extra here inside the brackets - the brackets strip away all their magic, and they are simply plain special characters that may appear in normal texts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Predefined Character Class Shorthands
&lt;/h2&gt;

&lt;p&gt;As we have seen above, Javascript regex (or any other regex languages) has some predefined shorthands for common situations. Let's have a look at the code snippet below.&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;regex1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;// matches "word" characters - equivalent to [a-zA-Z0-9_]&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;regex2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;// matches "space" characters, also tabs and various unicode control code and stuff&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nregex1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\W&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;// negated \w - matches everything other than "word" characters&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nregex2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\S&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;// negated \s - matches everything other than "space" characters&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  OR operator
&lt;/h2&gt;

&lt;p&gt;Like in normal programming languages, &lt;code&gt;|&lt;/code&gt; is the &lt;em&gt;OR&lt;/em&gt; operator. &lt;code&gt;[0123456789]&lt;/code&gt; can also be written like &lt;code&gt;[01234]|[56789]&lt;/code&gt; if you feel like experimenting!&lt;/p&gt;

&lt;h2&gt;
  
  
  Replace by groups
&lt;/h2&gt;

&lt;p&gt;Other than matching patterns, regex is also super useful for replacing characters in a match. We can use JavaScript string's &lt;code&gt;replace()&lt;/code&gt; method to do this.&lt;/p&gt;

&lt;p&gt;Let's first construct a phone number matcher.&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;str0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+49 123-123-1234&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// a phone number...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;regex0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;(\+\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)\s(\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;(\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;(\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt; &lt;span class="c1"&gt;// matches the number and put all the digits into 4 groups.&lt;/span&gt;
&lt;span class="nx"&gt;regex0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; true, of course!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if we use the &lt;code&gt;replace()&lt;/code&gt; method, we can use &lt;code&gt;$&lt;/code&gt; plus a number to represent the corresponding group that we have defined in the regex pattern inside the second (&lt;code&gt;replacer&lt;/code&gt;) parameter.&lt;/p&gt;

&lt;p&gt;For example, we would like to extract the country code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;str0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="c1"&gt;// replace the match (the whole string in this case) with the first matched group, which is  (\+\d+)&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; '+49'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or replace the last 4 numbers with &lt;em&gt;4321&lt;/em&gt;...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;str0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$1 $2-$3-4321&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; '+49 123-123-4321'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fun isn't it? 😉&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted &lt;a href="https://www.xiaoru.li/post/fun-with-javascript-regex/" rel="noopener noreferrer"&gt;on my blog&lt;/a&gt;, where I publish random stuff on web dev, flutter and sometimes ML every two weeks or so.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can also find me on Twitter &lt;a href="https://twitter.com/hexrcs" rel="noopener noreferrer"&gt;@hexrcs&lt;/a&gt; :)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>regex</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
