Creating a SAAS Boilerplate

https://authjs.dev/reference/adapter/prisma

chmod -R 777 /Users/poojas/Downloads/my-saas-boilerplate-z

Main Setup

  1. npx create-next-app ./ --typescript --tailwind --eslint (Initialize project)
  2. npx shadcn-ui@latest init (Shadcn is a component library built on radix ui and tailwind css)
    1. npx shadcn-ui@latest add button
  3. Set up planetscale
  4. Prisma: npm install prisma
  5. npx prisma init --datasource-provider mysql
  6. paste database_URL in .env
  7. npm install @prisma/client

Installations

.env and other changes

Instructions

  1. tsrafce
  2. (typescript react arrow function export component)
<aside> 💡 Setup Database and Prisma </aside>
  1. In lib → db.ts
  2. Hot reloads → you create new prisma instance every time it reloads → wasteful of resources
  3. So we’re checking if there’s already a global cached prisma instance
import { PrismaClient } from "@prisma/client";
import "server-only";

declare global {
  // eslint-disable-next-line no-var, no-unused-vars
  var cachedPrisma: PrismaClient;
}

export let prisma: PrismaClient;
if (process.env.NODE_ENV === "production") {
  prisma = new PrismaClient();
} else {
  if (!**global.cachedPrisma**) {
    global.cachedPrisma = new PrismaClient();
  }
  prisma = global.cachedPrisma;
}
  1. create Account, Session and User models in schema.prisma (Copy from nextjs prisma adapter website)

    1. @@index is only for planetscale DB
    2. add under User: Credits → 10
    3. credits Int @default(10)
  2. npx prisma db push (sync up the entire mysql database with whatever configurations we write in schema.prisma)

<aside> 💡 Next Auth Setup </aside>
  1. In lib → create “auth*.ts”*

    1. next auth is gonna interact with out db through prisma
    2. so, we need the prisma adapter to do that
    3. npm install next-auth
    4. npm install @prisma/client @auth/prisma-adapter
  2. For session → we’re using jwt tokens

  3. callbacks → bunch of functions

    1. jwt function itself ({token}) → we’re gonna destructure the token from it

      1. find user with email = token.email
      2. if there is a user, set token.id and token.credits to id and credits in the db
      3. Return the token
    2. session

      1. Using the token returned, set

        session.user.id = token.id;
        session.user.name = token.name;
        session.user.email = token.email;
        session.user.image = token.picture;
        session.user.credits = token.credits;
        
      2. Return Session

      3. (Before that, set the types of them)

        declare module "next-auth" {
          interface Session extends DefaultSession {
            user: {
              id: string;
              credits: number;
            } & DefaultSession["user"];
          }
        }
        
      4. The token itself we must extend the types. So we tell it the interface of JWT

        declare module "next-auth/jwt" {
          interface JWT {
            id: string;
            credits: number;
          }
        }
        
    3. in .env → NEXTAUTH_SECRET

     ```
    
     adapter: PrismaAdapter(prisma), //Set prisma adapter
       providers: [
         GoogleProvider({
           clientId: process.env.GOOGLE_CLIENT_ID as string,
           clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
         }),
     ```
     
    

    2. Go to console.cloud.google.com 1. New project 2. Credentials→configure consent screen 1. user type: external (allow anyone to login) 2. Enter app name 3. add email under Developer contact information 4. leave scope empty 5. no test users 3. Create new credentials → oauth client ID 1. Authorized JavaScript origins: http://localhost:3001 2. Authorized redirect URIs: http://localhost:3001/api/auth/callback/google 3. Add to .env

     4. Create next auth endpoint in route.ts:
         1. create: **/app/api/auth/[...nextauth]/route.ts**
             
             ```
             import { authOptions } from "@/lib/auth";
             import NextAuth from "next-auth/next";
             
             const handler = NextAuth(authOptions);
             
             export { handler as GET, handler as POST };
             ```
             
     
    
<aside> 💡 Navbar </aside>
  1. in main layout.tsx
    1. cn : combines tailwind css classes , conditional styling
  2. Darkmode/ light mode: npm install next-themes
  3. npx shadcn-ui@latest add dropdown-menu

Auth screen:

npm install react-icons react-hot-toast react-hook-form axios

copy paste

api/sign-in folder

components/ auth-components folder

to use useSession()

add componets/ provider.tsx

wrap main layout.tsx within provider

npx shadcn-ui@latest add avatar

{session?.user ? (
               <UserAccountNav user={session.user} /> //user name, sign out and redirect
            ) : (
              <SignInButton /> // sign in and redirect
            )}

signOut({ callbackUrl: '/' })

Add images to next.config.js


Stripe

WEBHOOK WHILE DEPLOYMENT:

Back