The best way to learn a tool like React is to build something with it. Next.js is a powerful framework that helps you build for production. In this tutorial, we’ll learn how to build a clone of Twitter using Next.js and Prisma.
Our app will have the following features:
- authentication using NextAuth and Twitter OAuth
- an option to add a new tweet
- an option to view a list of tweets
- an option to view the profile of a user with only their tweets
The code for the app we’ll be building is available on GitHub. We’ll be using TypeScript to build our app.
Preliminaries
Next.js is one of the most popular React.js frameworks. It has a lot of features like server-side rendering, TypeScript support, image optimization, I18n support, file-system routing, and more.
Prisma is an ORM for Node.js and TypeScript. It also provides a lot of features like raw database access, seamless relation API, native database types, and so on.
Software required
We’ll need the following installed for the purposes of running our app:
These technologies will be used in the app:
- Next.js: for building our app
- Prisma: for fetching and saving data into the database
- Chakra UI: for adding styles to our app
- NextAuth: for handling authentication
- React Query: for fetching and updating data in our app
Creating a new Next.js App
Now, let’s get started! We’ll first create a new Next.js app by running the following command from our terminal:
yarn create next-app
We’ll need to enter the name of the app when the command prompts for it. We can name it anything we want. However, in this case, I’ll name it twitter-clone. We should be able to see a similar output on our terminal:
$ yarn create next-app
yarn create v1.22.5
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 🔨 Building fresh packages...
success Installed "[email protected]" with binaries:
- create-next-app
✔ What is your project named? twitter-clone
Creating a new Next.js app in /twitter-clone.
....
Initialized a git repository.
Success! Created twitter-clone at /twitter-clone
Inside that directory, you can run several commands:
yarn dev
Starts the development server.
yarn build
Builds the app for production.
yarn start
Runs the built app in production mode.
We suggest that you begin by typing:
cd twitter-clone
yarn dev
We can now go inside the twitter-clone directory and start our app by running the following command:
cd twitter-clone && yarn dev
Our Next.js app should be up and running on http://localhost:3000. We should be able to see the following screen:
Adding a Dockerized PostgreSQL Database
Next, let’s add a Dockerized PostgreSQL database so that we can save the users and tweets into it. We can create a new docker-compose.yml
file in the root of our app with the following content:
version: "3"
services:
db:
container_name: db
image: postgres:11.3-alpine
ports:
- "5432:5432"
volumes:
- db_data:/var/lib/postgresql/data
restart: unless-stopped
volumes:
db_data:
If Docker is running on our machine, we can execute the following command from the root of our app to start our PostgreSQL container:
docker-compose up
The above command will start the PostgreSQL container and it can be accessed on postgresql://postgres:@localhost:5432/postgres
. Note that you can also use a local installation of Postgres instead of a Dockerized one.
Adding Chakra UI
Chakra UI is a very simple React.js component library. It’s very popular and has the features like accessibility, support for both light and dark mode, and more. We’ll be using Chakra UI for styling our user interface. We can install that package by running the following command from the root of our app:
yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion
Let’s rename our _app.js
file to _app.tsx
inside the pages
directory and replace its content with the following:
// pages/_app.tsx
import { ChakraProvider } from "@chakra-ui/react";
import { AppProps } from "next/app";
import Head from "next/head";
import React from "react";
const App = ({ Component, pageProps }: AppProps) => {
return (
<>
<Head>
<link rel="shortcut icon" href="/images/favicon.ico" />
</Head>
<ChakraProvider>
<Component {...pageProps} />
</ChakraProvider>
</>
);
};
export default App;
Since we added a new TypeScript file, we’ll need to restart our Next.js server. Once we restart our server, we’ll get the following error:
$ yarn dev
yarn run v1.22.5
$ next dev
ready - started server on http://localhost:3000
It looks like you're trying to use TypeScript but do not have the required package(s) installed.
Please install typescript, @types/react, and @types/node by running:
yarn add --dev typescript @types/react @types/node
If you are not trying to use TypeScript, please remove the tsconfig.json file from your package root (and any TypeScript files in your pages directory).
This is because we added a new TypeScript file but didn’t add the necessary dependencies that are required to run them. We can fix that by installing the missing dependencies. From the root of our app, we can execute the following command to install the missing dependencies:
yarn add --dev typescript @types/react @types/node
Now, if we start our Next.js server, our app should compile:
$ yarn dev
yarn run v1.22.5
$ next dev
ready - started server on http://localhost:3000
We detected TypeScript in your project and created a tsconfig.json file for you.
event - compiled successfully
Adding NextAuth
NextAuth is an authentication library for Next.js. It’s simple and easy to understand, flexible and secure by default. To set up NextAuth in our app, we’ll need to install it by running the following command from the root of our app:
yarn add next-auth
Next, we’ll have to update our pages/_app.tsx
file with the following content:
// pages/_app.tsx
import { ChakraProvider } from "@chakra-ui/react";
import { Provider as NextAuthProvider } from "next-auth/client";
import { AppProps } from "next/app";
import Head from "next/head";
import React from "react";
const App = ({ Component, pageProps }: AppProps) => {
return (
<>
<Head>
<link rel="shortcut icon" href="/images/favicon.ico" />
</Head>
<NextAuthProvider session={pageProps.session}>
<ChakraProvider>
<Component {...pageProps} />
</ChakraProvider>
</NextAuthProvider>
</>
);
};
export default App;
Here, we’re wrapping our app with NextAuthProvider
. Next, we’ll have to create a new file named [...nextauth].ts
inside the pages/api/auth
directory with the following content:
// pages/api/auth/[...nextauth].ts
import { NextApiRequest, NextApiResponse } from "next";
import NextAuth from "next-auth";
import Providers from "next-auth/providers";
const options = {
providers: [
Providers.Twitter({
clientId: process.env.TWITTER_KEY,
clientSecret: process.env.TWITTER_SECRET,
}),
],
};
export default NextAuth(options);
The above file will be responsible for handling our authentication using Next.js API routes. Next, we’ll create a new filed named .env
in the root of our app to store all our environment variables with the following content:
DATABASE_URL="postgresql://postgres:@localhost:5432/postgres?synchronize=true"
NEXTAUTH_URL=http://localhost:3000
NEXT_PUBLIC_API_URL=http://localhost:3000
TWITTER_KEY=""
TWITTER_SECRET=""
The Twitter environment variables will be generated from the Twitter API. We’ll be doing that next. We can create a new Twitter app from the Twitter Developer dashboard.
-
Create a new Twitter app by entering its name and click on the Complete button.
-
Copy the API key, API secret key and Bearer token in the next screen.
-
Change the App permissions from Read Only to Read and Write in the next screen.
-
Click on the Edit button next to the Authentication settings to enable 3-legged OAuth.
-
Enable 3-legged OAuth and Request email address from users and add http://localhost:3000/api/auth/callback/twitter as a Callback URL.
-
The Website URL, Terms of service and Privacy policy files can be anything (such as https://yourwebsite.com
, https://yourwebsite.com/terms
and https://yourwebsite.com/privacy
respectively).
Our 3-legged OAuth should be enabled now.
Paste the value of the API key from Step 2 into the TWITTER_KEY environment variable and the value of API secret key into the TWITTER_SECRET environment variable.
Our .env
file should look like this now:
DATABASE_URL="postgresql://postgres:@localhost:5432/postgres"
NEXTAUTH_URL=http://localhost:3000
NEXT_PUBLIC_API_URL=http://localhost:3000
TWITTER_KEY="1234" // Replace this with your own API key
TWITTER_SECRET="secret" // Replaces this with your own API secret key
Now, if we restart our Next.js server and visit http://localhost:3000/api/auth/signin, we should be able to see the Sign in with Twitter button:
If we click on that button, we’ll be able to authorize our Twitter app but we won’t be able to log in to our app. Our terminal will show the following error:
[next-auth][warn][jwt_auto_generated_signing_key]
https://next-auth.js.org/warnings#jwt_auto_generated_signing_key
We’ll fix this issue next when we’ll be adding and configuring Prisma.
Continue reading
Build a Twitter Clone Using TypeScript, Prisma and Next.js
on SitePoint.