Skip to content

Instantly share code, notes, and snippets.

@adrianhajdin
Created May 5, 2023 13:13
Show Gist options
  • Save adrianhajdin/6df61c6cd5ed052dce814a765bff9032 to your computer and use it in GitHub Desktop.
Save adrianhajdin/6df61c6cd5ed052dce814a765bff9032 to your computer and use it in GitHub Desktop.
Next.js 13 Full Course 2023 | Build and Deploy a Full Stack App Using the Official React Framework
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap");
@tailwind base;
@tailwind components;
@tailwind utilities;
/*
Note: The styles for this gradient grid background is heavily inspired by the creator of this amazing site (https://dub.sh) – all credits go to them!
*/
.main {
width: 100vw;
min-height: 100vh;
position: fixed;
display: flex;
justify-content: center;
padding: 120px 24px 160px 24px;
pointer-events: none;
}
.main:before {
background: radial-gradient(circle, rgba(2, 0, 36, 0) 0, #fafafa 100%);
position: absolute;
content: "";
z-index: 2;
width: 100%;
height: 100%;
top: 0;
}
.main:after {
content: "";
background-image: url("/assets/images/grid.svg");
z-index: 1;
position: absolute;
width: 100%;
height: 100%;
top: 0;
opacity: 0.4;
filter: invert(1);
}
.gradient {
height: fit-content;
z-index: 3;
width: 100%;
max-width: 640px;
background-image: radial-gradient(
at 27% 37%,
hsla(215, 98%, 61%, 1) 0px,
transparent 0%
),
radial-gradient(at 97% 21%, hsla(125, 98%, 72%, 1) 0px, transparent 50%),
radial-gradient(at 52% 99%, hsla(354, 98%, 61%, 1) 0px, transparent 50%),
radial-gradient(at 10% 29%, hsla(256, 96%, 67%, 1) 0px, transparent 50%),
radial-gradient(at 97% 96%, hsla(38, 60%, 74%, 1) 0px, transparent 50%),
radial-gradient(at 33% 50%, hsla(222, 67%, 73%, 1) 0px, transparent 50%),
radial-gradient(at 79% 53%, hsla(343, 68%, 79%, 1) 0px, transparent 50%);
position: absolute;
content: "";
width: 100%;
height: 100%;
filter: blur(100px) saturate(150%);
top: 80px;
opacity: 0.15;
}
@media screen and (max-width: 640px) {
.main {
padding: 0;
}
}
/* Tailwind Styles */
.app {
@apply relative z-10 flex justify-center items-center flex-col max-w-7xl mx-auto sm:px-16 px-6;
}
.black_btn {
@apply rounded-full border border-black bg-black py-1.5 px-5 text-white transition-all hover:bg-white hover:text-black text-center text-sm font-inter flex items-center justify-center;
}
.outline_btn {
@apply rounded-full border border-black bg-transparent py-1.5 px-5 text-black transition-all hover:bg-black hover:text-white text-center text-sm font-inter flex items-center justify-center;
}
.head_text {
@apply mt-5 text-5xl font-extrabold leading-[1.15] text-black sm:text-6xl;
}
.orange_gradient {
@apply bg-gradient-to-r from-amber-500 via-orange-600 to-yellow-500 bg-clip-text text-transparent;
}
.green_gradient {
@apply bg-gradient-to-r from-green-400 to-green-500 bg-clip-text text-transparent;
}
.blue_gradient {
@apply bg-gradient-to-r from-blue-600 to-cyan-600 bg-clip-text text-transparent;
}
.desc {
@apply mt-5 text-lg text-gray-600 sm:text-xl max-w-2xl;
}
.search_input {
@apply block w-full rounded-md border border-gray-200 bg-white py-2.5 font-satoshi pl-5 pr-12 text-sm shadow-lg font-medium focus:border-black focus:outline-none focus:ring-0;
}
.copy_btn {
@apply w-7 h-7 rounded-full bg-white/10 shadow-[inset_10px_-50px_94px_0_rgb(199,199,199,0.2)] backdrop-blur flex justify-center items-center cursor-pointer;
}
.glassmorphism {
@apply rounded-xl border border-gray-200 bg-white/20 shadow-[inset_10px_-50px_94px_0_rgb(199,199,199,0.2)] backdrop-blur p-5;
}
.prompt_layout {
@apply space-y-6 py-8 sm:columns-2 sm:gap-6 xl:columns-3;
}
/* Feed Component */
.feed {
@apply mt-16 mx-auto w-full max-w-xl flex justify-center items-center flex-col gap-2;
}
/* Form Component */
.form_textarea {
@apply w-full flex rounded-lg h-[200px] mt-2 p-3 text-sm text-gray-500 outline-0;
}
.form_input {
@apply w-full flex rounded-lg mt-2 p-3 text-sm text-gray-500 outline-0;
}
/* Nav Component */
.logo_text {
@apply max-sm:hidden font-satoshi font-semibold text-lg text-black tracking-wide;
}
.dropdown {
@apply absolute right-0 top-full mt-3 w-full p-5 rounded-lg bg-white min-w-[210px] flex flex-col gap-2 justify-end items-end;
}
.dropdown_link {
@apply text-sm font-inter text-gray-700 hover:text-gray-500 font-medium;
}
/* PromptCard Component */
.prompt_card {
@apply flex-1 break-inside-avoid rounded-lg border border-gray-300 bg-white/20 bg-clip-padding p-6 pb-4 backdrop-blur-lg backdrop-filter md:w-[360px] w-full h-fit;
}
.flex-center {
@apply flex justify-center items-center;
}
.flex-start {
@apply flex justify-start items-start;
}
.flex-end {
@apply flex justify-end items-center;
}
.flex-between {
@apply flex justify-between items-center;
}
{
"compilerOptions": {
"paths": {
"@*": ["./*"]
}
}
}
import Prompt from "@models/prompt";
import { connectToDB } from "@utils/database";
export const GET = async (request, { params }) => {
try {
await connectToDB()
const prompt = await Prompt.findById(params.id).populate("creator")
if (!prompt) return new Response("Prompt Not Found", { status: 404 });
return new Response(JSON.stringify(prompt), { status: 200 })
} catch (error) {
return new Response("Internal Server Error", { status: 500 });
}
}
export const PATCH = async (request, { params }) => {
const { prompt, tag } = await request.json();
try {
await connectToDB();
// Find the existing prompt by ID
const existingPrompt = await Prompt.findById(params.id);
if (!existingPrompt) {
return new Response("Prompt not found", { status: 404 });
}
// Update the prompt with new data
existingPrompt.prompt = prompt;
existingPrompt.tag = tag;
await existingPrompt.save();
return new Response("Successfully updated the Prompts", { status: 200 });
} catch (error) {
return new Response("Error Updating Prompt", { status: 500 });
}
};
export const DELETE = async (request, { params }) => {
try {
await connectToDB();
// Find the prompt by ID and remove it
await Prompt.findByIdAndRemove(params.id);
return new Response("Prompt deleted successfully", { status: 200 });
} catch (error) {
return new Response("Error deleting prompt", { status: 500 });
}
};
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx,mdx}',
'./app/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {
fontFamily: {
satoshi: ['Satoshi', 'sans-serif'],
inter: ['Inter', 'sans-serif'],
},
colors: {
'primary-orange': '#FF5722',
}
},
},
plugins: [],
}
username: {
type: String,
required: [true, 'Username is required!'],
match: [/^(?=.{8,20}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+(?<![_.])$/, "Username invalid, it should contain 8-20 alphanumeric letters and be unique!"]
},
@Thai-Huynh0510
Copy link

@ethanmorton it works thanks. I tried to switch both of them in the local host didn't work, but it works when I deployed it

@Ephraim67
Copy link

Hello everyone, I have been having issues with the jsconfig.json file and global css
jsconfig.json
{
"compilerOptions": {
"paths": {
"@": ["./"]
}
}
}

global.css
jsconfig.json
{
"compilerOptions": {
"paths": {
"@": ["./"]
}
}
}

Is there anything I am doing wrongly?

@brotherSI
Copy link

Hey guys, Please Help!

I've been stuck with this error 3 days I don't know what to do I have been following the tutorial video however I am getting this error

error

@KyleCLim
Copy link

KyleCLim commented Jun 2, 2024

In cases that your username has more than one space character, you will get "Access Denied" error when you are trying to login. You can try editing the route.js in the signIn function. Use global replacement to hit all the space characters. Try this:
username: profile.name.replace(/ /g, "").toLowerCase()

@prajapatibhaskar
Copy link

prajapatibhaskar commented Jun 11, 2024

The database share_prompts is not getting created.
My URI and PASSWORD are also exactly correct.

database.js

let isConnected = false; // track connection status
const connectToDB = async () => {
    mongoose.set('strictQuery', true);

    if(isConnected) {
        console.log('MongoDB is already connected.');
        return;
    }
    try {
        await mongoose.connect(process.env.MONGODB_URI, {
            dbName: 'share_prompt',
            useNewUrlParser: true,
            useUnifiedTopology: true,
        })

        isConnected = true;
        console.log('MongoDB connected.');
    } catch (error) {
        console.log(error);
    }
}

export default connectToDB;

route.js:

import NextAuth from "next-auth/next";
import GoogleProvider from "next-auth/providers/google";

import connectToDB from "@utils/database";
import User from "@models/user";

console.log({
  clientId: process.env.GOOGLE_CLIENT_ID,
  clientSecret: process.env.GOOGLE_CLIENT_SECRET,
});

const handler = NextAuth({
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],

  callback: {
    async session({ session }) {
      const sessionUser = await User.findOne({
        email: session.user.email,
      });

      session.user.id = sessionUser._id.toString();

      return session;
    },

    async signIn({ profile }) {
      try {
        await connectToDB();

        // check if user already exists
        const userExists = await User.findOne({
          email: profile.email,
        });

        // if not, create a new user and save it to database
        if (!userExists) {
          await User.create({
            email: profile.email,
            username: profile.name.replace(" ", "").toLowerCase(),
            image: profile.picture,
          });
        }
        return true;

      } catch (err) {
        console.log(error);
        return false;
      }
    },
  },
});

export { handler as GET, handler as POST };

@prajapatibhaskar
Copy link

The database share_prompts is not getting created. My URI and PASSWORD are also exactly correct.

database.js

let isConnected = false; // track connection status
const connectToDB = async () => {
    mongoose.set('strictQuery', true);

    if(isConnected) {
        console.log('MongoDB is already connected.');
        return;
    }
    try {
        await mongoose.connect(process.env.MONGODB_URI, {
            dbName: 'share_prompt',
            useNewUrlParser: true,
            useUnifiedTopology: true,
        })

        isConnected = true;
        console.log('MongoDB connected.');
    } catch (error) {
        console.log(error);
    }
}

export default connectToDB;

route.js:

import NextAuth from "next-auth/next";
import GoogleProvider from "next-auth/providers/google";

import connectToDB from "@utils/database";
import User from "@models/user";

console.log({
  clientId: process.env.GOOGLE_CLIENT_ID,
  clientSecret: process.env.GOOGLE_CLIENT_SECRET,
});

const handler = NextAuth({
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],

  callback: {
    async session({ session }) {
      const sessionUser = await User.findOne({
        email: session.user.email,
      });

      session.user.id = sessionUser._id.toString();

      return session;
    },

    async signIn({ profile }) {
      try {
        await connectToDB();

        // check if user already exists
        const userExists = await User.findOne({
          email: profile.email,
        });

        // if not, create a new user and save it to database
        if (!userExists) {
          await User.create({
            email: profile.email,
            username: profile.name.replace(" ", "").toLowerCase(),
            image: profile.picture,
          });
        }
        return true;

      } catch (err) {
        console.log(error);
        return false;
      }
    },
  },
});

export { handler as GET, handler as POST };

OK, it seems that changing from callback to callbacks worked for me.
In the video he said callbacks, but sometime ago it was not working for me, then i changed to callback, then it worked but, was not able to create database in MongoDB.

@i-oo
Copy link

i-oo commented Jun 14, 2024

I followed the youTube video until the end of the 'Homepage' section. After signing in with google, I got the error below

image

The culprit was with 'next/image' and src={session?.user.image} in the tag.

To resolve this I created a new next.config.js with

/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: "lh3.googleusercontent.com",
},
],
},
};

module.exports = nextConfig;

ref: https://nextjs.org/docs/pages/api-reference/components/image#remotepatterns

Resolved issue

@AbhayWakle
Copy link

Screenshot 2024-06-21 130936

how to solve this error

@brotherSI
Copy link

Hi all,

I get the following error when I try to deploy on Vercel. I have wrapped the useSearchParams() function with suspense boundary but it hasn't worked. Please Help

useSearchParams() should be wrapped in a suspense boundary at page "/update-prompt". Read more: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout

@Abdul073
Copy link

Guys i'm stuck with this error.anybody have a solution to this ⨯ Error: [next-auth]: useSession must be wrapped in a at Nav (./components/Nav.jsx:19:90) session

So if you watch the video, you need to add the following code inside Provider.jsx file inside your component folder.

"use client";
import React from "react";
import { SessionProvider } from "next-auth/react";

const Provider = ({ children, session }) => {
  return <SessionProvider session={session}>{children}</SessionProvider>;
};

export default Provider;

and after that inside layout.jsx file inside your create-prompt folder you need to wrap everything inside the body tag with the Provider component as follows.

import React from "react";
import "@styles/globals.css";
import Nav from "@components/Nav";
import Provider from "@components/Provider";

export const metadata = {
  title: "Promptopia",
  description: "Discover & Share prompts",
};

const RootLayout = ({ children }) => {
  return (
    <html lang="en">
      <body>
        <Provider>
          <div className="main">
            <div className="gradient" />
          </div>
          <main className="app">
            <Nav />
            {children}
          </main>
        </Provider>
      </body>
    </html>
  );
};

export default RootLayout;

Hope this solves your issue.

i got some issues in page loading its 404 page not found can you solve this

@Sidharth1327
Copy link

✓ Starting...
✓ Ready in 3.1s
○ Compiling / ...
⨯ ./styles/globals.css
Syntax error: D:\Full STack Developer\full-stack-next-js-app\styles\globals.css The shadow-[inset_10px_-50px_94px_0_rgb(199, class does not exist. If shadow-[inset_10px_-50px_94px_0_rgb(199, is a custom class, make sure it is defined within a @layer directive. (111:3)

109 |
110 | .copy_btn {

111 | @apply w-7 h-7 rounded-full bg-white/10 shadow-[inset_10px_-50px_94px_0_rgb(199, 199, 199, 0.2)] backdrop-blur flex justify-center items-center cursor-pointer;
| ^
112 | }
113 |
-- inner error --
Syntax error: D:\Full STack Developer\full-stack-next-js-app\styles\globals.css The shadow-[inset_10px_-50px_94px_0_rgb(199, class does not exist. If shadow-[inset_10px_-50px_94px_0_rgb(199, is a custom class, make sure it is defined within a @layer directive. (111:3)

109 |
110 | .copy_btn {

111 | @apply w-7 h-7 rounded-full bg-white/10 shadow-[inset_10px_-50px_94px_0_rgb(199, 199, 199, 0.2)] backdrop-blur flex justify-center items-center cursor-pointer;
| ^
112 | }
113 |
Generated code for D:\Full STack Developer\full-stack-next-js-app\node_modules\next\dist\build\webpack\loaders\css-loader\src\index.js??ruleSet[1].rules[13].oneOf[12].use[2]!D:\Full STack Developer\full-stack-next-js-app\node_modules\next\dist\build\webpack\loaders\postcss-loader\src\index.js??ruleSet[1].rules[13].oneOf[12].use[3]!D:\Full STack Developer\full-stack-next-js-app\styles\globals.css

Import trace for requested module:
./styles/globals.css
GET / 500 in 1702ms
⨯ ./styles/globals.css
Syntax error: D:\Full STack Developer\full-stack-next-js-app\styles\globals.css The shadow-[inset_10px_-50px_94px_0_rgb(199, class does not exist. If shadow-[inset_10px_-50px_94px_0_rgb(199, is a custom class, make sure it is defined within a @layer directive. (111:3)

109 |
110 | .copy_btn {

111 | @apply w-7 h-7 rounded-full bg-white/10 shadow-[inset_10px_-50px_94px_0_rgb(199, 199, 199, 0.2)] backdrop-blur flex justify-center items-center cursor-pointer;
| ^
112 | }
113 |
-- inner error --
Syntax error: D:\Full STack Developer\full-stack-next-js-app\styles\globals.css The shadow-[inset_10px_-50px_94px_0_rgb(199, class does not exist. If shadow-[inset_10px_-50px_94px_0_rgb(199, is a custom class, make sure it is defined within a @layer directive. (111:3)

109 |
110 | .copy_btn {

111 | @apply w-7 h-7 rounded-full bg-white/10 shadow-[inset_10px_-50px_94px_0_rgb(199, 199, 199, 0.2)] backdrop-blur flex justify-center items-center cursor-pointer;
| ^
112 | }
113 |
Generated code for D:\Full STack Developer\full-stack-next-js-app\node_modules\next\dist\build\webpack\loaders\css-loader\src\index.js??ruleSet[1].rules[13].oneOf[12].use[2]!D:\Full STack Developer\full-stack-next-js-app\node_modules\next\dist\build\webpack\loaders\postcss-loader\src\index.js??ruleSet[1].rules[13].oneOf[12].use[3]!D:\Full STack Developer\full-stack-next-js-app\styles\globals.css

Import trace for requested module:
./styles/globals.css
GET /_next/static/webpack/2c117a266159ffbc.webpack.hot-update.json 500 in 2265ms
⚠ Fast Refresh had to perform a full reload due to a runtime error.
GET / 200 in 537ms
GET / 500 in 13ms

Guys, anybody have any idea , whats wrong ?? Please help me

@Sidharth1327
Copy link

✓ Starting... ✓ Ready in 3.1s ○ Compiling / ... ⨯ ./styles/globals.css Syntax error: D:\Full STack Developer\full-stack-next-js-app\styles\globals.css The shadow-[inset_10px_-50px_94px_0_rgb(199, class does not exist. If shadow-[inset_10px_-50px_94px_0_rgb(199, is a custom class, make sure it is defined within a @layer directive. (111:3)

109 | 110 | .copy_btn {

111 | @apply w-7 h-7 rounded-full bg-white/10 shadow-[inset_10px_-50px_94px_0_rgb(199, 199, 199, 0.2)] backdrop-blur flex justify-center items-center cursor-pointer;
| ^
112 | }
113 |
-- inner error --
Syntax error: D:\Full STack Developer\full-stack-next-js-app\styles\globals.css The shadow-[inset_10px_-50px_94px_0_rgb(199, class does not exist. If shadow-[inset_10px_-50px_94px_0_rgb(199, is a custom class, make sure it is defined within a @layer directive. (111:3)

109 | 110 | .copy_btn {

111 | @apply w-7 h-7 rounded-full bg-white/10 shadow-[inset_10px_-50px_94px_0_rgb(199, 199, 199, 0.2)] backdrop-blur flex justify-center items-center cursor-pointer;
| ^
112 | }
113 |
Generated code for D:\Full STack Developer\full-stack-next-js-app\node_modules\next\dist\build\webpack\loaders\css-loader\src\index.js??ruleSet[1].rules[13].oneOf[12].use[2]!D:\Full STack Developer\full-stack-next-js-app\node_modules\next\dist\build\webpack\loaders\postcss-loader\src\index.js??ruleSet[1].rules[13].oneOf[12].use[3]!D:\Full STack Developer\full-stack-next-js-app\styles\globals.css

Import trace for requested module: ./styles/globals.css GET / 500 in 1702ms ⨯ ./styles/globals.css Syntax error: D:\Full STack Developer\full-stack-next-js-app\styles\globals.css The shadow-[inset_10px_-50px_94px_0_rgb(199, class does not exist. If shadow-[inset_10px_-50px_94px_0_rgb(199, is a custom class, make sure it is defined within a @layer directive. (111:3)

109 | 110 | .copy_btn {

111 | @apply w-7 h-7 rounded-full bg-white/10 shadow-[inset_10px_-50px_94px_0_rgb(199, 199, 199, 0.2)] backdrop-blur flex justify-center items-center cursor-pointer;
| ^
112 | }
113 |
-- inner error --
Syntax error: D:\Full STack Developer\full-stack-next-js-app\styles\globals.css The shadow-[inset_10px_-50px_94px_0_rgb(199, class does not exist. If shadow-[inset_10px_-50px_94px_0_rgb(199, is a custom class, make sure it is defined within a @layer directive. (111:3)

109 | 110 | .copy_btn {

111 | @apply w-7 h-7 rounded-full bg-white/10 shadow-[inset_10px_-50px_94px_0_rgb(199, 199, 199, 0.2)] backdrop-blur flex justify-center items-center cursor-pointer;
| ^
112 | }
113 |
Generated code for D:\Full STack Developer\full-stack-next-js-app\node_modules\next\dist\build\webpack\loaders\css-loader\src\index.js??ruleSet[1].rules[13].oneOf[12].use[2]!D:\Full STack Developer\full-stack-next-js-app\node_modules\next\dist\build\webpack\loaders\postcss-loader\src\index.js??ruleSet[1].rules[13].oneOf[12].use[3]!D:\Full STack Developer\full-stack-next-js-app\styles\globals.css

Import trace for requested module: ./styles/globals.css GET /_next/static/webpack/2c117a266159ffbc.webpack.hot-update.json 500 in 2265ms ⚠ Fast Refresh had to perform a full reload due to a runtime error. GET / 200 in 537ms GET / 500 in 13ms

Guys, anybody have any idea , whats wrong ?? Please help me

I even tried to comment out this code and again executed npm run dev , still it shows the error

@cahyo988
Copy link

findByIdAndDelete
thank you its resolve my problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment