-
Install dependencies
yarn
-
Get Pusher credentials Please refer to the Pusher Setup section for more details.
-
Get Github OAuth credentials Please refer to the NextAuth Setup section for more details.
-
Create
.env.local
file in the project root and add the following content:PUSHER_ID= NEXT_PUBLIC_PUSHER_KEY= PUSHER_SECRET= NEXT_PUBLIC_PUSHER_CLUSTER= AUTH_SECRET=<this can be any random string> AUTH_GITHUB_ID= AUTH_GITHUB_SECRET=
-
Start the database
docker compose up -d
-
Run migrations
yarn migrate
-
Start the development server
yarn dev
-
Open http://localhost:3000 in your browser
-
Install prettier and prettier plugins
yarn add -D prettier prettier-plugin-tailwindcss @trivago/prettier-plugin-sort-imports
-
Install eslint and eslint plugins
yarn add -D eslint typescript @typescript-eslint/parser eslint-config-prettier @typescript-eslint/eslint-plugin
-
Copy and paste the
./prettierrc.cjs
and./eslintrc.json
from this repo to your project root. -
Add
format
script topackage.json
{ "scripts": { "format": "prettier --write ." } }
-
Check if the scripts work
yarn format yarn lint
-
Install drizzle
yarn add drizzle-orm pg yarn add -D drizzle-kit @types/pg
-
Copy the
docker-compose.yml
from this repo to your project root. -
Start the database
docker compose up -d
-
Add
POSTGRES_URL
to.env.local
:... POSTGRES_URL=postgres://postgres:postgres@localhost:5432/notion-clone
-
Create
db
foldercd ./src mkdir db
-
Create the
./src/db/index.ts
file:import { drizzle } from "drizzle-orm/node-postgres"; import { Client } from "pg"; import { privateEnv } from "@/lib/env/private"; const client = new Client({ connectionString: privateEnv.POSTGRES_URL, connectionTimeoutMillis: 5000, }); await client.connect(); export const db = drizzle(client);
Remember to setup the environment variables handlers in
src/lib/env/private.ts
:import { z } from "zod"; const privateEnvSchema = z.object({ POSTGRES_URL: z.string().url(), }); type PrivateEnv = z.infer<typeof privateEnvSchema>; export const privateEnv: PrivateEnv = { POSTGRES_URL: process.env.POSTGRES_URL!, }; privateEnvSchema.parse(privateEnv);
-
Create an empty
./src/db/schema.ts
file -
Copy the
./drizzle.config.ts
from this repo to your project root. Remember to installdotenv
:yarn add dotenv
-
Change the
target
option intsconfig.json
toes2017
:{ "compilerOptions": { "target": "es2017", ... } }
-
Add scripts Add the following scripts to the
./package.json
file:{ "scripts": { // This script will update the database schema "migrate": "drizzle-kit push:pg", // This script opens a GUI to manage the database "studio": "drizzle-kit studio" } }
Remember to run
yarn migrate
after you make changes to the database schema, namely the./src/db/schema.ts
file. -
Add
pg-data
to.gitignore
... pg-data/
-
Setup Shadcn UI
npx shadcn-ui@latest init
-
Answer the questions carefully since some of the default options are not compatible with our setup.
- Would you like to use TypeScript (recommended)?
yes
- Which style would you like to use? ›
New York
- I personally prefer New York style, but you can choose any style you like.
- Which color would you like to use as base color? ›
Slate
- You can choose any color you like.
- Where is your global CSS file? › ›
src/app/globals.css
- IMPORTANT: You must enter
src/app/globals.css
here. Otherwise, the setup will fail.
- IMPORTANT: You must enter
- Do you want to use CSS variables for colors? ›
yes
- Where is your tailwind.config.js located? ›
tailwind.config.ts
- IMPORTANT: We are using TypeScript, so you must enter
tailwind.config.ts
here.
- IMPORTANT: We are using TypeScript, so you must enter
- Configure the import alias for components: ›
@/components
- Configure the import alias for utils: ›
@/lib/utils/shadcn
- Are you using React Server Components? ›
yes
- Would you like to use TypeScript (recommended)?
-
Install pusher
yarn add pusher pusher-js
-
Create a pusher account at https://pusher.com/
-
Create a new app
- Click
Get Started
orManage/Create app
on theChannel
tab - Enter the app name
- Select a cluster. Pick the one closest to you, i.e.
ap3(Asia Pacific (Tokyo))
- Click
Create app
- Click
-
Go to
App Keys
tab, you will see the following keys:app_id
key
secret
cluster
-
Copy these keys to your
.env.local
file:PUSHER_ID=<app_id> NEXT_PUBLIC_PUSHER_KEY=<key> PUSHER_SECRET=<secret> NEXT_PUBLIC_PUSHER_CLUSTER=<cluster>
NEXT_PUBLIC
prefix is required for the client side to access the env variable.Also, please remember to add these keys to your environment variables handler in
src/lib/env/private.ts
andsrc/lib/env/public.ts
. You can view those two files for more details. -
Go to
App Settings
tab, scroll down toEnable authorized connections
and enable it. Note: If you enable theEnable client events
option, every connection will last only 30 seconds if not authorized. So if you just want to do some experiments, you might need to disable this option.
We use the latest version (v5) of NextAuth, which is still in beta. So there are some differences between the documentation and the actual code. You can find the detailed v5 migration guide here: https://authjs.dev/guides/upgrade-to-v5#authenticating-server-side
-
Install next-auth
yarn add next-auth@beta
-
Get Github OAuth credentials
-
Go to
Settings
tab of your Github account -
Click
Developer settings
on the left sidebar -
Click
OAuth Apps
on the left sidebar -
Click
New OAuth App
orRegistr a new application
-
Enter the following information:
Application name
:Notion Clone
(or any name you like)Homepage URL
:http://localhost:3000
Authorization callback URL
:http://localhost:3000/api/auth/callback/github
-
Click
Register application
-
Copy the
Client ID
andClient Secret
to your.env.local
file:AUTH_GITHUB_ID=<Client ID> AUTH_GITHUB_SECRET=<Client Secret>
Before copying the Clinet Secret, you may need to click on
Generate a new client secret
first.Note that in NextAuth v5, the prefix
AUTH_
is required for the env variables.Note that you do not have to add those keys to
src/lib/env/private.ts
since they are automatically handled by NextAuth.
-
-
Add
AUTH_SECRET
to.env.local
:AUTH_SECRET=any-random-string
This is used to encrypt the session token. You can use any random string here. Make sure to keep it secret and update it regularly.
Note that you do not have to add those keys to
src/lib/env/private.ts
since they are automatically handled by NextAuth. -
Create
./src/lib/auth.ts
import NextAuth from "next-auth"; import GitHub from "next-auth/providers/github"; export const { handlers: { GET, POST }, auth, } = NextAuth({ providers: [GitHub], });
-
Add
./src/app/api/auth/[...nextauth]/route.ts
export { GET, POST } from "@/lib/auth";
-
Add providers to
./src/app/layout.ts
import { SessionProvider } from "next-auth/react"; ... return ( <html lang="en"> <body className={inter.className}> <SessionProvider>{children}</SessionProvider> </body> </html> ); ...