-
Run
npx create-next-app@latestWhat is your project named? next-match-app Would you like to use TypeScript? Yes Would you like to use ESLint? Yes Would you like to use Tailwind CSS? Yes Would you like your code inside a `src/` directory? Yes Would you like to use App Router? (recommended) Yes Would you like to use Turbopack for `next dev`? Yes Would you like to customize the import alias (`@/*` by default)? No
2. Install eslint-plugin-simple-import-sort
- Run
npm install --save-dev eslint-plugin-simple-import-sort - Update
eslint.config.mjsto the code here - Enable
eslintin IDE
3. Install HeroUI and React Icons
I used Manual Installation and Tailwind v4 Migration Guide because I didn't start the project with HeroUI and this project uses Tailwind 4.
-
Run
npm install @heroui/react@beta framer-motion react-icons -
Follow the Tailwind v4 Migration Guide to set up HeroUI
-
Create
src/components/Providers.tsxand use the following code:"use client"; import { HeroUIProvider } from "@heroui/react"; import { ReactNode } from "react"; const Providers = ({ children }: { children: ReactNode }) => { return <HeroUIProvider>{children}</HeroUIProvider>; }; export default Providers;
-
Update the
returnstatement insrc/app/layout.tsxas shown:<html lang="en"> <body> <Providers>{children}</Providers> </body> </html>
When using a component, remember to import from @heroui/<component-folder> instead of @heroui/react since NextJS is SSR.
For example:
import { Button } from "@heroui/button";
import { Avatar } from "@heroui/avatar";In the node_modules/@heroui/react, it has "use strict";, but node_modules/@heroui/<component-folder> has "use client"; "use strict";.
- Run
react-hook-form zod @hookform/resolvers
-
Follow Auth.js setup steps
-
Follow Edge compatibility guide (step 1 and 2)
-
Run
npx prisma initto initialize Prisma -
Update
src/auth.tsto:import { PrismaAdapter } from "@auth/prisma-adapter"; import NextAuth from "next-auth"; import authConfig from "@/auth.config"; import { prisma } from "@/lib/prisma"; export const { handlers: { GET, POST }, auth, signIn, signOut, } = NextAuth({ adapter: PrismaAdapter(prisma), session: { strategy: "jwt" }, ...authConfig, });
-
Update
src/app/api/auth/[...nextauth]/route.tsto:export { GET, POST } from "@/auth";
-
Create a Postgres database with NEON and update the
DATABASE_URLvalue in.env -
In
prisma/schema.prisma, updategeneratorto:generator client { provider = "prisma-client-js" } -
Update
prisma/schema.prisma(see here) -
Run
npx prisma generate -
Create
src/lib/prisma.tswith the following code:import { PrismaClient } from "@prisma/client"; const globalForPrisma = global as unknown as { prisma: PrismaClient }; export const prisma = globalForPrisma.prisma || new PrismaClient({ log: ["query"] }); if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
-
Run
npx prisma db push -
Run
npx prisma studioto see the tables -
Run
npm i bcryptjsandnpm i -D @types/bcryptjs
-
Every time you update the
schema.prisma, Run:npx prisma generate npx prisma db push npx prisma studio
-
See Prisma's Seeding documentation if want to seed data.
There are 2 ways to do.
npx prisma migrate reset --skip-seed
npx prisma db push
npx prisma db seed- Run
npx prisma migrate dev -n Initial --create-onlyInitialis the name of the migration which can be anything that you want- Use
--create-onlywhen needed
- Run
npx prisma reset - A
migrationsfolder will be created in the/prismafolder
- Follow Auth.js Session Management documentation (both Next.js server and client)
- Follow Next.js Middleware documentation
For storing image.
-
Create an account
-
Run
npm install cloudinary -
Follow Installing Next Cloudinary
-
Create a
src/lib/cloudinary.tswith:import cloudinary from "cloudinary"; cloudinary.v2.config({ cloud_name: process.env.NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME, api_key: process.env.NEXT_PUBLIC_CLOUDINARY_API_KEY, api_secret: process.env.CLOUDINARY_API_SECRET, }); export { cloudinary };
For real-time features.
- Run
npm i pusherfor server side - Run
npm i pusher-jsfor client side - Add the following to
.env:NEXT_PUBLIC_PUSHER_APP_KEY= PUSHER_APP_ID= PUSHER_SECRET= - Create
src/lib/pusher
9. Set up Zustand
For state management.
- Run
npm install zustand - Add all hooks to
Provider.tsx- They don't have to be in the
Providers.tsx, but they must be in a client component and import that component to the main layout
- They don't have to be in the
10. Set up Resend
For email verification after registeration
- Create an account at https://resend.com/
- Create an API key and save it in the
.envasRESEND_API_KEY - Run
npm i resend
The email might be in spam
-
Add the following to
auth.config.tsimport Github from "next-auth/providers/github"; providers: [ Github({ clientId: process.env.GITHUB_CLIENT_ID, clientSecret: process.env.GITHUB_CLIENT_SECRET, }), ... ]
-
Go to you Github account > Developer settings > OAuth Apps
-
Click
New OAuth Appand enter the following- Application name: your app's name
- Homepage URL:
http://localhost:3000 - Authorization callback URL: you can find this URL by going to
http://localhost:3000/api/auth/providersin your browser and look forcallbackUrlforgithub
-
Click
Register applicationand save Client ID and Client secret in the.envas:GITHUB_CLIENT_ID= GITHUB_CLIENT_SECRET= -
See
SocialLogin.tsxon how to use it
-
Add the following to
auth.config.tsimport Google from "next-auth/providers/google"; providers: [ Google({ clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, }), ... ]
-
Go to Google Developer Console (must have a google account)
-
Create a project
-
A toast will appear on the top right, click Select
-
Go to APIs & Services > OAuth consent screen > create one
- App Information: enter a name and an email
- Audience: select External
- Contact Information: enter an email
-
Click
Creat OAuth client- Application type: select Web application
- Name: enter a name
- Authorized JavaScript origins:
http://localhost:3000 - Authorized redirect URIs: you can find this URL by going to
http://localhost:3000/api/auth/providersin your browser and look forcallbackUrlforgoogle
-
Click
Creat, go to the created client, and save Client ID and Client secret in the.envas:GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET=