NextJS Web Development for Beginners: Build & Launch a Subscription-Based SaaS Step by Step 2025 | Czero | Skillshare
Search

Playback Speed


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

NextJS Web Development for Beginners: Build & Launch a Subscription-Based SaaS Step by Step 2025

teacher avatar Czero, Backend Developer

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Intro

      3:56

    • 2.

      Setup

      4:56

    • 3.

      Navbar and Theme Settings

      9:11

    • 4.

      User Interface

      10:40

    • 5.

      Clerk Setup

      6:21

    • 6.

      Prisma Setup

      2:32

    • 7.

      Supabase Setup

      9:40

    • 8.

      Clerk Webhook

      12:09

    • 9.

      Stripe Webhook

      50:24

    • 10.

      Payment Pages

      5:35

    • 11.

      Sign In, Sign Up

      11:01

    • 12.

      Subscription Check

      5:57

    • 13.

      Product

      37:22

    • 14.

      Landing Page - Animation Container

      14:24

    • 15.

      Landing Page - Steps Component

      12:34

    • 16.

      Landing Page - Demo Component

      7:18

    • 17.

      Landing Page - FAQ Component

      12:52

    • 18.

      Landing Page - Pricing Component

      12:11

    • 19.

      Landing Page - Call to Action, Footer, Updates

      16:26

    • 20.

      Landing Page - New Navbar, Updates

      18:10

    • 21.

      Profile Page

      11:43

    • 22.

      Displaying Channel Name on Dashboard

      3:38

    • 23.

      Deployment

      7:56

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

35

Students

--

Project

About This Class

Live: https://saas-tutorial-v2-three.vercel.app/

Theme Settings: https://github.com/czerocourses/theme-for-saas

This course is designed for developers who want to build a fully functional SaaS website from scratch. You'll gain hands-on experience with Prisma, Clerk, Supabase, NextJS, learning how to integrate these technologies to create a modern and dynamic user experience.Throughout the course, you'll explore key concepts such as database management, server-side logic, front-end development, and API integration. By the end of the course, you'll have a solid understanding of how full stack website built with NextJs works, and the skills to develop your own fullstack applications with NextJs.

Meet Your Teacher

Teacher Profile Image

Czero

Backend Developer

Teacher
Level: Beginner

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Intro: Class is for everyone who wants to learn about creating a full SAC application. In this case, MicroSAS with Next JS. You learn how to work with the router, make calls to database, and set up and implement third party services like clerk for user management, stripe for payments or Super Base as a database provider. Don't forget to check out the class project and challenge yourself by creating your own MicroSAS after taking this class. We will create a library website featuring SAS or more specifically MicroSASPduct from scratch. We will start by preparing the UI, then move on to adding functionalities needed for Live SAS product. This includes setting up authentication using clerk, establishing a database connection using Prisma ORM, and storing data in suba baase, which I will be using in this tutorial. But don't worry. You don't have to use SupAbase. Since we are setting up connections with BismoRM, it's incredibly easy to sweep out SupABse for any other database of your choice. We will also integrate Stripe to set up a subscription model so users can access the product after subscribing. The goal of this tutorial is to help you gain hands on experience, building a SAS product and have one in your hand that you can just modify, customize, adapt, and use. And in the end, we will deploy our application to HID live where I will show you step by step how to make everything work together. Without further ado, let me walk you through the demo and then we will finally start building. We will start on page as a new user and we are starting there with Nov bar where we have a pricing, the team setting, and a possible sign in. Then on the page, we can see that we have some sale for the starting price of our product, name of the product. We have there get started, and then the three easy steps, how to use our product. If you will continue down the page, we will see there a demo of our product on this animated picture that is changing the rotation and opacity as we are scrolling. Then we have frequently asked questions section where we will click on the question and the answer will be displayed. Below is a pricing section, and there you can buy the yearly plan or monthly depends how you set it. And below is this animated section with some already done thumbnails being rotated there in a circle. And now let's continue to product itself. We will try to sign up. Then I will continue with Google. After we sign in, we can see that we are not subscribed yet, but also new items in our Navbar. These are for the product itself, pricing and also profile where we will set the channel name that we will use in the product. Let's click Subscribe. There we will fill in the data. And we will get onto payment successful page, and there we have our product because now we are subscribed to the application. There you can see we can set the title for the video card, then the tab itself, and the channel name. For the channel name, we will actually go to profile and as we will now be using this, we will set there our channel, something like this. I will submit it. Now I will go back to product, and there you can see I have it prefilled, and every time I will look into the application, I will have it there. Now that's the previewer itself. I will put there thumbnail for the title. I will also put there something, and then I can see the video card with the thumbnail. Now I can randomize the order, and also I can change it to Tablet View or mobile view. And if we would like to manage the subscription, we have that button that will redirect us to Stripe where we can just simply manage it. And that will be it, simple functionality for MicrosAS with one feature to test out the product. And of course, if it's successful, there can be more and more features addied. That will be it for the demo, and without further ado, let's finally dive into the code and bring this project to life. 2. Setup: Our folder, we will start with opening a terminal and pasting the command for creating next application. There as we are already in the folder, we can do there just the dot, head enter, and it will install the necessary things. We will proceed with Y. There we will do yes to tailwind, no to source, yes to a router, no to As. Now we will just wait a bit and we can continue with setting the theme for our application. I prepare the team for our application, and you will find it on this Gita link that will be in the description, and there we will start with taking Globus CSS and tailwind config. If you don't want to go to any link, I will show you the code and you can rewrite it, but it will be a bit tricky. Let's start with taking this tailwind config dot Ts, copy paste. Go to tell and config dot Ts you have there in your app and just paste there the wall code. Now I will go over the wall code in case you for some reason, don't want to copy paste it and just want to take it. Now we will go back to the page. We will go into Globals dot CSS, and we will put it into our app, globals dot CSS. What we past it there as a light team and a dark team, and then one more thing. On Git up, you will now take layout one dot Tsix. Now in layout Tsix there, you will paste there the wall layoutTSix from Layout one you took from the Git. And why do we have the layout two? On layout two are some things that are not yet implemented. So we will take Layout two in a few, I think, in around 10 minutes. I think we can now do NPM run depth and start developing the navigation bar, which will be the first component we will do. Now we can see first error on our page. We are missing some library. We will just open another terminal and we will do NPM. And this tailwind CSS animate, we will hit Enter. I will install the library. Now our page will work. You can see our page is currently having the next J template. We will change this really soon. Now we will start with the navigation bar. Let's go to our app folder, and inside this app folder we can create components folder. Or what we can just do is that we can start loading some components. The command for adding these components is real easy. You just need to do NPx, shed CN, at latest, at, and now you will just type the components. What we will use is a button. There we can do, New York neutral CSS variables for teaming. Yes, now it will be created. Then also, we will be using card. Then we will be using input. Then we will be using label. We will be using scroll area. And we will be also using text area. Now, as we have it, it created component folders for us and also it created a lip folder for us with this utils dot Ts. Lip folder, this is like a toolbox that holds the important tools and helpers for the wall project. And in talking about utils dot Ts, this is therefore combining CSS class names for styling. Into this lip folder, we will also add later helpers for database, for example, seeing these components and UI folder, we have the het CN components. If we will click on the components itself though, and there, click on a new file, we can create there, Navbar TSX, and we will have the separated UI for the ChetsN components and just the components folder for our Navbar, but everything is wrapped in this components folder. 3. Navbar and Theme Settings: Inside our navigation bar, we'll start with us client to define that this is a client component and we will import link from library that is called nextink. We'll start with doing the export constant Navbar. And we will be returning navigation. And for this navigation, we will start with background to background, which is the background that we defined in our team and border bottom. Then inside, we will do div and in this dip, we will set some maximum weight. I will do seven Excel. I will center this and background green 200, so we can see where it actually is on our page. Of course, we need to add to the layout. Now we have their Navbar. We can copy it. Now let's go into the root layout, which is this one. And there we can start typing Navbar, hit Enter, and it will get imported. Now we will save it on our page, we'll be able to see it really soon. I will just put there something and you can see on the top there the green background, which is our navigation bar. Let's fix this. Now we will continue. We will set there flexbox layout, justify between. That means we will have even spacing between our elements and height to 16. Inside this div, we will create the link, and this link will be containing our logo. We will put there just SAS now, and there in the link, the HRF will be to lending page. For our case, there is no route to this. It's just slash that will get us there to root page, and there we will put some bedding text three Excel and font Bum. Then below, you'll do a conditional rendering, and we will ask I signed. And in case, yes, it will render something there. And in case, now, it will render other thing that will be on the false position. Now to mock this because we currently didn't yet implemented the ALF, I will put the const is signed, and currently, I will just hardcode the true value. But later this will depend on other factors. Currently, it will always rear the true, but we can also change it to false, and for testing purpose, we will do it now before we implement the actual authentication. In case this is true, it will render the link to our actual application. We can just take this link. We can call this product. There it will get user to dashboard page and right below, he will be able to go to profile, which will be under dashboard Profile. Now in case he is not signed in, nothing will be rendered. That means we will put there false value, you can see the items will disappear. Now let's take this link, put it below this conditional rendering, and this will be linked to pricing, and the pricing won't be below dashboard. It will be accessible even from non authenticated users. So it will be just slash pricing. Then what I will do is that I will put this wall conditional rendering even with the pricing into one div because I would like this to be in the middle, how this will look like, is that as we are using justify between, we will first have the logo of our SAS, then we will have this div where will be pricing. Or if user will be signed, there will be product profile and pricing. And below, we will have a div and in this div, there will be setting of the Tuggle that we currently don't have, but we will edit later. For now, we can just put a placeholder Team tagle but it's really for us. This will be deleted a bit later. And now we will again do the conditional rendering. We will use this as signed constant we have there. And in case he is signed in there will be the sign out button. And in case he is not signed in, there will be the sign in button. This will be changed for the actual buttons that we will get from the library of our of provider. Now for the styling of our navigation bar, I will just put the background grade to 400 for a while, because we currently still don't have the team there for this div. I will put space x22. Then for the text, we know that text large will be enough for us. Let's just delete text sizing from everywhere there, and we will put it into the wrapping div. Let's go there to this div and put the text large. And also next to justify between, we can just add items center, save it, and it will be nicely centered like this. For the navigation bar, I think that's fine. And what we will do is that after we will do the tagle, we will put it there instead of displayholder, and after we will implement the O, we will put it there instead of the Sigou and sign in. Currently, I will also delete this background. Now to add the team, we will execute steps we can find on stsn.com. You can find it there in search documentation, dark mode, there you will select Next Js and we will just execute these steps. First, we will install the next teams. Let's open the terminal. Do NPMI. Next Teams, I did it twice because I copied it, but it shouldn't matter. There, you can see that we need to create Team provider TSX. Let's copy this code. There, let's go to Explorer and components. Let's create a new file. Team provider dot TSX, paste the code there, save it. Now on the page, let's continue. This is what I talked about. We will use the Team provider wrapper, and they will go to the Git upp. There you will go to Layout two. You will take this code and you will put it into the layout the TAix in app folder. And now we ddt their Team provider, so it looks like this. Also we edit font heading and font body for our font. There we are setting it in a class name and body. There we are using the team provider and we are wrapping the Navbar with children. And what we will do next is that we will go back to Chet CN. Now we can check this step and we can continue to add the mode Toggle. There we will use this one, and in a code, I will click on copy, and we'll be creating a toggle component. There in our ID, I will go to components. I will create a new file, and I will put the Team toggle, Tsix. And inside, I will paste the code. We are missing drop down menu. How we will fix it is that we will do NPX ShetCN at latest at dropdown menu, and it will install this component from the het CN library to our UI folder there. Now let's click again there, weigh the bit, save it, and that's it. And finally, what we can do is that we can use mode Tuggle in our Navbar because we have the export there. Let's go to our navigation bar there to placeholder, where is the team tagle we will do mode Tuggle. It's not named Team tagle because the export is just named mode Tuggle. And there, we will now go to our page, you can see we have it next to the sin in button and change to light, it will be using light mode. To dark, it will be using the dark mode, and to system, it will be using the system mode set. Now let's go back to Navbar, and for this DIF that is holding these sin Sinnot buttons and mode tagle we will add also space x to four. And also flexbox layout and items to center. That's it for the navbar, and we will come back to it after we will do the Of provider. 4. User Interface: You can start working on our lending page. First thing, what we will do is that we will delete this next GS template and we will start with DIV. In this div, we will use BG background and also text for ground. Inside this div, we will create a main tech and inside this main tech, we will put the classes of container, AMS auto, bedding x two, four, bedding from top to 12, and also text to center. There in the main, we will do heading one. We can put there for now some placeholder like micro SAS, tutorial, and we will add some styling to it that will be text for Excel. On medium screen, we will increase it to text six, Excel. We will do the font bolt and margin bottom to four. Also below, I would add paragraph tag, and there will be the description of our micro sas. For now, I will ada just this text. And for the styling, I will ada text Excel on medium text to Excel, margin to bottom eight, maximum width of three Excel, and a mix Auto. Next thing, what we will add is a div. In this div, we will have two buttons. The button will be the one we imported from Chet CN. I will import it like this. And inside will be view pricing. Then below, we will have this button again, and there we get started. Actually, let me maybe change it to get started and view pricing like this. Styling for these buttons will be flex, justify center and space X for because these buttons will be next to each other and below this dip, we will have an image. And in this image, we will have the closing tag there, and it will have some source and d and also some class name. For the class name, it will be width to full, height to auto, and margin from top eight. Why I'm using this image and not image from next image, I can actually delete the input from there is that because I will be using their source from URL. For now, we will leave this empty because we will style it later after we will have our product and we will put the picture of our product demo to this landing page. Currently, we will leave the landing page like this and we will finalize the styling later even with the image. Before we move on, last thing, what we will do there is just variant and there we will do outline. Now if we will save it, you can see how it will look on our page. And now we can move on with creation of UI of our Micross application. Let's continue by creating Dashboard folder. We will click there on app, there on a folder, and name it Dashboard. Inside Dashboard folder, we will create page dots six. But also, we will create there another folder, and that will be called Profile. Inside this profile folder, we will create another page dot Tsix. We will create also pricing folder. That won't be in Dashboard though, that will be in app. There in app, we will create new folder pricing. And in this folder, we will create page dots six. How this will work is that when we want to go to Dashboard, our URL will need to look like dashboard. For profile, it will be slash dashboard slash profile, and for pricing, it will be just slash pricing. In our dashboard page, we'll define the main dashboard component as async function, export default, async function dashboard. And there for now, we will just do a return. And in this return, we will create a paragraph tag with are Not subscribed. And below, we will do a link. And to this link, we will add subscribe. Then we will do HRF to pricing. Then we can make this one liner and we will wrap this into button that we imported from Chet CN. Now let's put it there, save it and it will be on our dashboard page. By the way, let's do this also on the landing page where I forgot to do it. There we will just make a link with HRF. Dashboard inside, I will put this get started. I also need to import it on the next line, we will make it as pricing with HRF to pricing. I will go to our page and we will click on Get Started, we will get to Dashboard. There we will click on Subscribe and we will get to pricing that is not yet defined. Let's stay on the dashboard, and there we will now make the styling for this. You are not subscribed. Text, I will add the Flexbox layout with flex direction Colum items to center. Justify center, bedding to eight, round it, large and shadow medium. Now I will save it for the paragraph tech. I will add text large, margin bottom to four. Maybe I will do text Excel, actually, and margin bottom I will do 26, and that will be as just some initial text for the dashboard when user will be not subscribed. But of course, there will be a lot of back end to this. What we are missing is a profile page and pricing page UI. Let's do the pricing page now. We will again export default acing function called pricing. Inside, we will do a return, and in this return, we will create a div and in this div will be first heading one, subscription plan. Below this heading one will be a div. And in this div will be heading two. You can just do full access. And below, we will continue with paragraph tech access to all features. Then with another one that this will cost $10 per month. Then there will be some conditional rendering. We can actually g this also is subscribed. There will be some form in case he is subscribed to manage the stripe portal, and in case he is not subscribed, there will be some form for the creation of the subscription. Currently, this is subscribed, will be always true or false. And after we will do the stripe integration, this will depend on the status of the subscription in case it will be active, this will be true value, in case not. This will be false value. Inside this form, we will put a button And this button will be managed subscription because when a user will be subscribed, there's no reason for him to subscribe again. He will be just redirected to a stripe portal where he can cancel his subscription. Type of this button will be submit, then we can copy this and put it there into our form below, and this won't be managed subscription, but it will be subscribe. Let's take a look on our pricing page. We have it there. Now let's add some styling. Let's start from the top with maximum weight to Excel, and mix Oto, BY eight, and Bx four. Then we will continue for heading one with text for Excel, for extra bolt tracking tight, and on large, we will increase this on text five Excel and march into bottom six. Now for this dif, we will do rounded large. We will set border and also background card. Then text card, foreground. Some shadow for the light mode, some bedding, and some bottom margin. Then for the full access, we will add a border to bottom, then bedding to bottom two, text three Excel, font semi bolt, also tracking tight, and margin bottom four. For access to all features, we will add leading seven for the price. We will add text to Excel and font bolt. And for the heading, actually, we will delete this margin to bottom, and there we will do space Y four. That means also we can delete margin to bottom there. Now let's save it, check our page. And on the pricing, we can also add which features will user get after he subscribes. Currently, he is not subscribed. We can also set data subscribe to falls. But as I thought, this will be changed with the packend we will code a bit later. Currently, this will be for the subscription plan, and we can continue and start with the integration of some third parties we are using and start coding the packend for our application. 5. Clerk Setup: We will integrate user management with Clark and you will sign in, then go to this dashboard. There in our applications, we will click on Create application. For application name, I will select SAS Tutorial, and next to email, I will have also login with Google. I will click on Create application and now I have there a guide how to do this with nextJS. First, we need to install it. Let's open a terminal, past the command there and hit enter that will install the library. Then we have their environment variables. Let's click on Copy. And in our folder, we will create a new file in the root folder, and that will be called dot NF. Also, we will go to Git Ignore, and there below f the local, we will add dot NF itself. And now we will paste it there. Next thing, what we need to do is to set this middleware Ts. Let's copy the code and middleware file also needs to be created in this root folder. There I will create a new file called middleware dot Ts, and I will paste there the code. Then we can also see the example of the implementation for this sign in sign out, but we will from this take only the clerk provider and put it into our root layout. And these buttons, we will put the navigation bar. Also, then it's just about NPM run D, which is something we are already doing. Now let's take this clerk provider Let's go there. There we will go to App layout. There we will wrap this HTML into Clark provider. You should do it like this and also import it. And now we can move to Navbar, and there we will use the sign in and sign Out. If you want to continue with a guide, you will click there and continue to Next Jazz guide, and there is a documentation of the things we will do now. First of them is to create these folders for signup and sign in. Let's go to our IDE, and there we will go into the app. And the app we will create a new folder that will be called sign in. There we will create another folder, which will be three dots, sign in with square brackets. And inside this one will be page dot TSX. Then again, click on a folder and do the same thing, but for sign up, then again, sign up with two and page dot TSX. Inside these two pages, we will put this code for sign up. And then the second one for the sign in. And I was referring to these two code snippets. Then if we will scroll down, we will take this. We will put it into our environment variables. Then we will go to sign in and sign up. And there after sign in, we will set attribute with force redirect URL, and that will be to dashboard. Now we will copy this and we will go to sign up and we will put it also there. This means that after user signs in or signs up, he will be redirected to his dashboard. And in the environment variables, we are setting that when clerk will be calling to sign in or sign up, he will be redirected to these folders we created there and it will handle it automatically. Now, before we try it, we need to put it into our Navbar. Let's go to components Navbar, and there we will use it instead of these sign Out and sign in place folders. I will put the sign out button. Let's go to the documentation. There we will take this. We will go back to our ID, and we will put it there. And with Clark, we don't need this conditional rendering because it has this text for this signed in and signed out. We just need to import this. Also signed in and sign in button. And I won't be using user button. I will be using just sign out button. I will make sure the imports are correct and it looks like the DS. And I think now we can go to our page and we can test this. We are on our page. We are not signed in. Let's click on it. We have their clerk. I will click on continue with Google. We are logged in, and now if you click on sign out, we will be signed out. We can again sign in with another user, and now we can go to clerk and there we can check our users. There in overview, you can see total users and resend signups or sign ins. I use these two accounts. I signed up and sign in. You will have all your users there. 6. Prisma Setup: Now let's set up the database and we will start with Prisma ORM, and then we will store the data in a super base which uses Post grass SQL. If you go into Prisma IO, there you can click on Get Started and you will get to this documentation. You can click there start on scratch in case you want to do this on your own. There, what we will do is that we will use the first command in terminal. Let's open a new one and put their NPM install Prisma with safe Dev. You are curious about more commands, you can do NPXPrismA. And that can give you some help. And now we will do NPXPrisma in it, and that will initialize Prisma in our repo. There we have it. And in this file, we will be adding models for our objects. In the documentation of Prisma, will click on Connect to your database, there we have also documentation about how to connect this, and there we will also install Prisma client. Let's take this NPM install Prisma client and also we will put it into our terminal. What this does is that this adds some special tool called Prisma client to our project, and this will basically help us to talk to our database more easily. Whenever we will make some changes like adding new fields or tables, and we will run the command and Px Prisma generate, it will update the Prisma client folder with new code, and it will match it to our database. In our case, it will be super baase. This way, our application can use the latest database changes. Prisma is really easy to set up. This is it. And if we want to just use Prisma and not use SupAbse and keep the database locally, we could just change this to file dot n for the source there and we can start writing our models for the objects. But we would like to keep our database on a server we will be deploying this project in the end and it will be accessible online. That means now we will go and set up Supase and then we will connect it to PRISMA 7. Supabase Setup: We will go to SupABse and there we will sign up or login if you already have an account or also you can basically use Continue with Git up. There you will click on create a new project. We will choose Organization. There we will select project name. There we will generate a password, and we will click on Copy. Save this password somewhere. We will use it in a while, select region, and then we will click on Create New Project. Now in Super Base in project settings, and there in database, we can get this connection string. We will click on copy, and we will go to our environment variables and we will paste it there. Now there into your password, you will paste your password that you got from Superbase that will look like this, but of course, this is your password. Then take this wall string and put it into this database URL. Now we will go on documentation called Super Base with Prisma, and there we can also see some next steps we need to do to connect this with Prisma. There you will find these two strings. The first one will be for the database URL. Basically, it's the same we have. The only thing edited there is after database name is this question mark with PG bouncer. Let's take it and paste it there. For the database URL, then your string will look like before, but with edit question mark and PG bouncer, we can delete this, and there we will create a new environment variable that will be called direct URL. And that will get the second string. If you will check it, it's the same string uler Superbse. It has a different port. It's using 5432 and the database name. That means we can go back to our environment variables. Take this string. Put it there. Now we will delete this up to this database name, which is Post Cress, and we will change this port to 5432. Now we will save it and now we will go to schema dot Prisma. And there, we will add below this URL for database URL, direct URL, and we will set the environment variable, direct URL. Now we will save it. And now we can start writing the models for our objects. We will start with model user for user, we will define ID that will be of type string. Then we will define and it will be ID, tech and unique. Then we will define email that will be also of type string. It will be also unique. Then we will define stripe customer ID for later implementation of stripe. This will be string with question mark that will mark this as optional field, and we will take it also as unique because we will have only one kind of this ID. We will continue with name that will be also string with question mark, and that also means it's optional and it can be now and that will go even for subscription. Now, what I did there is that I said this as an optional relation to a subscription model. Below, we will create a new model and that will be called subscription. We need this because we need to track if the user is subscribed or not subscribed to our application. There we will need stripe subscription ID that will be string ID, and unique. And we will use it as unique identifier for the subscription. Below, we will need to add more fields that will be status that we will use for the subscription status. It will be a string, then it will be current period start, which will be date time, then current period and it will be again datetime then created a that will be datetime and the default value will be now. This will put for our subscription, the datetime of now, which sounds obvious, but it's just that straightforward. Then updated it. We will use this whenever subscription will get updated. Then the interval, then the interval if the subscription is yearly or monthly, plan ID. If you have stripe plan, then we will save it into this field and user ID or the user that will have the subscription. Now, this will be string and this will be also string and this will be also unique. Then we will create a relation there to the user model that will be done like user user and relation with fields, User ID. References ID. Now in this terminal, we can do NPxPrisMa format. And if you will be adding something, you can just do arrow up, Henter and do it again. And if you want to clear your terminal, just write CLS. We can save it. And with this, we have the schema Prisma done. We will now hit NPXPrisma studio, and it will open UI for us where we will see this table. Let's now open N terminal and do NPxPrisma DB push. You see it failed for me and it's because I used the wrong password there because I was showing you with this example password, and now I will just put there the real password from the superbase. If you forgot it, I will show you how you can get it. There in database, you will click on Reset database password, generate password, reset it before, just copy it if you want a new one, and then you will put it there onto display. Now what we will do is that we will put there in the terminal NPXPrisma Migrate Dev. We will enter there we will put some name for the migration and wait for a bit. We can also do this with NPxPrisma DB push. NPXPrisma DB push is when you want to quickly push some changes to your database, it doesn't crack them, and NPXPrisma migrate Def will track the changes. When we will add some fields or some model, we will have it cracked down. You can also see there in Prisma migrations. There it is. I think as now we did it, we can go to Superbse and there in table Editor, you can now see subscription user, and you can see there all the fields. Now it's time to load the user into our database. How we will achieve this. We need to use Clark webhook for this because when user will again, then the clerk webhook will help us save the user into our database. Currently, where user web clerk logs in, is just saved into clerk. Let's now code the part where we will fetch this. 8. Clerk Webhook: Open documentation of clerk and we will go there to synchronize Clerk data to your application with webhooks. First step is to set up Engroc. This will help us expose our local server to the Internet. What we need to do is just download Ngrog and after you download it, you will open the engrogtExA file, which will open a terminal for you. And before downloading it, you need to login on this ungrog.com, create an account there, and then you will download it and open the engrog dot Xfile which looks like this. There on the page, we will go to endpoint. We click on Sarto tunnel. There we will copy this, and now we will go there into our terminal. In this terminal, we will paste this, but it won't be 80, it will be 3,000 as this is our local host. Now we can see it's forwarding it like this. If we will go into our rock and hit the tunnels, we can see it displayed there. Next thing we need to do is to create API web hooks. We will go into our IDE there in app. We will create a new folder called API. In this folder, we will create a next folder called webhooks. In this we won't create Route through Ts. But first, we'll create the clerk folder, and inside this one, we will create Route Ts. We can also create another folder in Webooks. It will be called Stripe. And in Stripe we can also create Route DS, and this is something we will set up later. For now, let's go with the clerk for the next step, we already have these environment variables. Only thing we will take is this Webhook secret. Let's copy it and put it into our N file. There in environment variables, I will put it like this and save it. For the next step where the middleware is being set, something we already did, we have it there. If we will continue, now we need to install SWIx. Let's copy it, go into our IDE, and then terminal, paste this and hit Install. Now, if you start moving to the next step, you can see that we are getting the route for our webhook. We will click on a copy there and we will paste it into our route. Let's go there into the clerk, route DS based the code there. And there in step seven, we can see that if condition, where if the Evans type is user created, something happens. We would like to use this because for this, when the user will be created, we would like to call the database section for creating the user in our database. Let's go back to step two. In step two, you can see that we need to update this Clerk dashboard with our endpoint. We got from Engroc There we will in our clerk, we will go there into webhooks. There we will click on at endpoint, and there what we will do. We will paste this URL from the Engoc. We will paste it there. And after we will do API, web hooks, clerk. And this is the endpoint URL we should use there. And what we want to subscribe to is user creation. We can put there user dot create, and also we can leave the selected updated, deleted, and so on. Let's click on Create, click on assigning secret and copy it from there. Now go back to our IDE, go to environment variables, and we will put it on display to our webhook secret. Next step, what we will do, we will go into our lip folder, and there we will create a new file. This file will be called db dot Ts. In this file, we'll basically create and export a Prisma instance, so we can then use it in our application. Let's start there with importing Prisma client from client library. Then we will define a type for the global object that will include the Prisma property GlobraFPrisma, global as unknown as and there we will set Prisma two Prisma client or undefined in case it's not found. Then we will create and export the prisminstans itself. There we will use the existing prism instance in case it exists. Otherwise, we will create a new Prisma client instance. And inside, we will configure logging to show database queries. In case, we will have non production environments, which is our case, we will save the Prisma instance to the global object. Global for prisma Prisma equals to Prisma. And last but not least, we will do export default Prisma. Now with having this, we can go back to web hook. There we will import Prisma from lip folder DB like this. And we will move down. Now we can delete this part. And instead of this part, we will do the if condition with the checking if the event is of the user created type. I event type is equal to user dot created, then we'll do constant ID email addresses, first name and last name equal to event data. You will do Trikageblock. Inside the Strikageblock, we will write to save the user to the database. We will do await Prisma dot user dot Create. There we will do data. For as well, it will be ID, email to email addresses first from this array because on clerk there can be more email addresses. First one should be the primary one which we are interested in. Then first name and we are actually using name. If you check our schema prisma, what we'll do is that we will create a constant above or that we'll just create constant in the spray block above, name it full name and set it there that this should be first name in case it's not there, we will just make this empty. And connect it with last name. Again, in case it's not there, we will make this empty and we will do dot trim on the end. Now for the name, we will set this full name and we will set there a new value in case it doesn't exist. We need the email and ID mainly. Main thing for us is the email. Below we can do console log user with ID was inserted into the database. And then in catch, we will do the error and we will put a console error there in case this will fail error saving user to the DB with the error, and we will return new response with error saving user and set status to 500. Otherwise, in case this will go through, it will set the response to status 200. Now we can save it and it's time to test it. This is currently our super base or Prisma, doesn't matter. Now we'll click on sign in. And we will again use some of our accounts to sign in. I can see I'm in. Let's check what happened and nothing happens, that will be because our user was not created. For example, with the user I currently logged in, it was already created in clerk. What I need to do is to go to clerk and delete the current two users I have in my clerk. There in clerk, users make sure there is not a user you are testing this webhook with. Let's repeat the process, sign in. Now again, I'm in, and it worked. I can now see my user in a super baase. Of course, as we are using Prisma O RM, it will be also in Prisma if we will refresh the Prisma. Actually, if it's not in Prisma, just do in terminal Sutter C and then do NPXPrisma studio again that should fix it for you. Then if you will go into Prisma, you can see the user also there. 9. Stripe Webhook: Now we will set up a stripe. First, you will login or sign up to Stripe, and then in Stripe, you will create a new product, and there in the new product, we will go into developers there we will go into API keys, and there we will take the publishable key. Then we will go to our IDE, paste it there, and we will go back for the secret key, we will click on reveal and then click again, so we will get it to clipboard, and we will paste it into our dot Nf file, so into our environment variables. I have the publishable key and the secret key, I will put a name for these environment variables. As this will be a public one, I will put the next public and then Stripe publishable key, and for the secret one, I will put Stripe secret. Then we will go back to stripe page. There we will go to Product Catalog and you can see I already have there two products, but I will create a new one with you. Let's click there on at product. I will put there name of SAS product. I will set there a price recurring and 1990 $9. It won't be monthly. I will set it as yearly and there I will click on at product. Now I'll click on it that will get me there. From there, if you will click, you can copy price ID, and then you can save this in your environment variables. You can see like this. I put it there. And last environment variable we will need from Stripe is the Stripe Webbook secret. So let's prepare it there. This is not the secret you should put in. For the secret, you will get this actually generated from the terminal. So what we need to do now, we will go there on web hooks. We will click on test in Local Environment, and there we will get a guide what we need to do in order to set up the stripe for webhooks. So first, we'll need to download the client there you will select your system for meets Windows. There I will download this zip file from Github. You will unzip it, then you will open the folder, then you will open environment variables in your computer and you will add a path to this dot ax file there. You will open your terminal. You will write stripe there, and you will get this information. That's how you will know you successfully installed the client. There we will go back to this page. Then we'll put there this first command, stripe login. We will copy the URL. Open it there, there we will see the word. We will click on Lo Access and access granted. Now if we go back to that page, we will see there completed, then we will copy this command and we will open there a new terminal. Now we will paste this to forward events to our webhooks. What we need to do is that we will change it to our local host. Also we will put the API webhooks stripe. We will ad Enter with this, we will get the stripe webhook secret. We will paste it and put it there. And now what we will do is that we will just try to trigger some event. We open your terminal and pase there this stripe trigger payment intent succeeded and hit Enter. You can see that this tried something, but as we don't have any code yet in this strpouttTs, of course, it won't work. Now what we will do is that we will code this part and we will make this work and then after we will again run this stripe trigger payment intent succeeded, this will work for us. But of course, we can trigger this also from the UI itself, where we will just try to buy the product. For now, let's just go and code the web hook. First, what we will do is that we will go into Lip folder, and in Lipfolder we will create a new file. This file will be called stripe dot ts. We will start there with importing Stripe Library. And we don't have Stripe yet. Let's open a terminal, and let's do NPM I Stripe. Now, it will be fine and we can continue. We will create and export a new stripe instance with a secret key from our environment variables. Let's type the export constant strip where we will create a new stripe instance. And as input parameter, we will send process dot dot Stripe secret key as spring. Inside, we will put API version that we need to set to 202-04-0620, and if this won't work for you, just check what the latest API version is and put it there. Also, I will set the typescript to true to enable typescript support. And we can see some error there. Let's put there the recommended one in case it will cause any issues, we will fix it later. Now as we are testing it, having this in developer mode, we are including there also a beta feature with dot Acacia and after we will be in production, it can just be with the actual API version. Currently, we will use this beta feature to include also. We will continue with defining an asynchrous function to create stripe checkout session. I will do the export constant get stripe session asynchronous. And inside, we will set the input parameters. It will be price ID, domain URL, and customer ID. And its types will be string. Domain URL will be also string, and customer ID will be also string. There we will continue like this and we will open a body where we will create a new Stripe checkout session with these specified parameters. I will create a constant for session. I will wait stripe dot checkout dot sessions dot Create. And there, I will set customer for this session, which will be customer to customer ID. Then I will set mode that will be to subscription. Then I will set payment methods types For us, this will be card, then billing address collection. There will be auto, then line items. We will set this to price where will be price ID and quantity, which will be one. Below, we will continue with customer update, and there we will set update of name to Auto and of address to Audo also. And last but not least will be the success and Cancel URL. These two URLs will be there after user will check out to Stripe, and he will buy the product, it will redirect him to this URL. And if the payment will fail, it will redirect him to this URL. And these two pages is something we will set in a while after we finish this stripe dotTs. The success URL will look like domain URL, payment slash success and the cancel one will look pretty similar to the first one, but it will be canceled. We will define these pages in a while. Now below this, we will put return session dot URL as string. That means we will return the URL of the created session. What we also do below this create checkout session is to define a customer portal session. When user will want to manage his subscription, we will create a portal for him, and when he will click the managed subscription, he will be redirected to Stripe and in Stripe, he will have the subscription management. He can cancel the subscription there and so on. Let's do Export async function, create customer portal with input parameter of customer ID as a string. We will create a promise there. And inside, we will create a new stripe billing portal session, constant portal session. Wait stripe dot Billing portal Sessions Create there we will send to customer ID and return URL to something similar like there. We will take this from our environment variables, next public URL. In our case, this will be local host slash Pricing. But after we'll get to production, we will change this environment variable of next public URL to the actual domain of our page. Now, as we have the promise of a string there, we need to return it. So we will return a string, something that is called portal session dot URL. Now we prepared even the create customer portal next to checkout session we have there. This should be it for Stripe Ds in our lip folder there. Now we can go to webhooks. In webhooks, we will go to Stripe and in stripe there, we will open the route dot Ds we will start coding the Stripe webhook there. There we can begin. First, we will import the stripe instance from our lip folder. Let's do Import stripe from the lip folder there, then we will continue with importing stripe for the typescript support. Then we will import the Prisma database client. We have also in our lip folder. Then we will import headers function from NextS so we can access request headers. What we will do next is to define an asynchronous post request handler function. We will put there input parameters of request like rec and it will be of type request. There we extract the raw body of the request as a text. Let's do constant body, elate request, text. Then we will get stripe signature from the request headers and we will save it into constant named signature. There we will do headers, dot get stripe signature, a string, and we will have it saved there in this signature constant. Then we will declare a variable to hold the stripe event. We will do ten stripe event. Below, we will create a Tricgblock In this stripe catch block, we will verify and construct the stripe event using the webhook secret. There we will do event equals to stripe dot webhooks dot Construct event. And we need to put there as input parameters, body, signature, and process dot N Stripe webhook secret as string. In case this will fail, we will catch it in this block, and we will return there in new response and set it to webhook error and set the status to 400. Then we will create a new constant session, and there we will cast the event data object as a stripe checkout session. Let's do event data object as stripe dot checkout session. To explain this, this event data object is accessing the object property within the data field of the stripe event. This object contains the full details of the event subject. And what we are doing there is that we are telling the typescript to treat event data object as if it were type of stripe checkout session and why we are doing it. For example, event data object could be a checkout session, subscription or invoice type, and typescript cannot automatically tell which one it will be. And because it could be any of them, we will define it as stripe checkout session. Let's continue with handling of the different events. First, we will start with handling of the event called checkout Session Completed. We will do their if condition and we will check the event type. This one will be checkout session completed as I set. First, for every event, we will retrieve the full subscription details from Stripe and we will save them into constant code subscription. There we will await Stripe subscriptions dot retrieve. And we will retrieve the session subscription as string. Then we will find the user in the database using their stripe customer ID, and we will save it into constant user await Prisma dot user find Unique, and there we will just select where the stripe customer ID is session dot customer as string. That means that will check our database and find the user that has this stripe customer ID. Now we will have it saved in the user constant, and we will continue. We will check if the user was found or not. In case he wasn't found, we will return an error, how to do this. Let's grade there and if condition with exclamation mark, user, this means that if the user is not found, we will execute this code block, and what we will do there is return new response. And in this response, we will put the message, user not found, and we will also put the status, and the status will be set to 44, which is for not found. Then we will continue with creation of a new subscription in case the user is existing and everything is prepared. We will wait Prisma dot subscription dot Create. And we need to create there the data, of course, and the data we'll be creating. We can also see in our schema dot Prisma. Let's start there with user ID, that will be set to user dot ID, which is ID of this user we have there. Then stripe subscription ID that will be set to subscription ID. This is there. Then we will continue with setting current period and we will set this to new date, and then we will put subscription current period end, multiplied by 1,000. Now let me explain this. As date constructor expects milliseconds, we need to multiply this by 1,000. Then we will save this date into our current period end and we will do the same thing for current period start. Again, you date, convert or first let's get to it, current period start, convert to milliseconds as well. We will continue with interval. This one we will set to subscription dot items, and now we are using data and zero to represent the first item in our array. There will be just one item, and that will be the one we want plant interval, then we will continue with plan ID. Then we will with similar style subscription dot items, data first from the array, plan dot ID. And last but not least status, that will be just subscription dot status. That will wrap the checkout session completed event type, and below, we can start with another one. We will create a if condition, event type invoice payment succeeded. Now for this events type, we will again retrieve the full subscription details from Stripe and save it into constant called subscription. There we'll do Avade stripe subscriptions, dot retrieve via session subscription as string. Now we don't need to check user. We will just update the subscription record in the database, and that will be it for this event type. How we'll do it is that we will do Awad Prisma dot subscription dot Update. And there we will select ones where the subscription ID or stripe subscription ID is equals to subscription dot ID. Which data we would like to update. We would like to update status, subscription dot status, and also current period with new date, and again, we need to convert this subscription dot current period and multiply it by 1,000. We can move to another event type, which will be the subscription update. Let's do a condition event type equals to customer dot subscription updated. And there, again, we will do the same thing. There will be constant subscription, weight stripe dot subscriptions dot retrieve session subscription as string. That means we are again retrieving the full subscription details from Stripe. I could basically copy paste it, but let me just code it. We can do it again for these two events. So you will remember it for the next time. Now we will just update the subscription record in the database. Then we'll await RsmA dot subscription dot update, and we will do this on records where the subscription is subscription dot ID. And with data, we will do that we will set current period end to new date. Subscription current period end multiplied by 1,000, again, for the same reason. Then we need current period start, which will be the same case, subscription current period start. Then we will update interval, subscription items data. It's repeating, I would say, it's just same thing over and over again with setting different fields and so on. Now we set interval, now we will set also plan ID, subscription dot items dot data. Again, this is an array. We will access the first item, plan dot ID. And there will be one interesting thing and you can set it or you don't need to set it. When a user will buy the subscription, he has the access for one month or for one year. Depends on what we will set. When the user will cancel the subscription, he still has the time that he bought left. For a month, if he cancels second today, he still have 28 days. For a year, if he cancels after one month, he will still have 11 months left. But what if you want to set some condition that when the user will unsubscribe, he will immediately lose access to our application. This probably isn't the best case or the best things to do, but we can do it. And in case you would like to do it, I can show you how, and we can set it for application also because it's just easy to remove. If you just remove this one line, it will be fine then. How to do this is that we will do their status. And for status, we will do subscription cancel at period end. And in case this exists, that means that the user really canceled the subscription because otherwise, this field is empty. And when this field is populated, that means that he canceled the subscription. If this exists, it will execute this true position, which will be canceling. If this doesn't exist, it will execute this subscription dot status. Whenever user will cancel the subscription, the status will be changed from active to canceling. And as we will be checking on our page for the product access that the user subscription needs to be active, then he won't have access to it because his status will be canceling instead of active immediately after he clicks on Cancel subscription. I hope you understood this, and we will show this on a real example. As we will be testing the application later, you will see how this exactly works, and you will also understand better how to work with these event types. And we will move to the last event, and it will be customer subscription deleted. Let's do if condition there. Event type, customer subscription deleted. There we again, save to constant name subscription, the full subscription details from Stripe, await stripe dot subscription. Dot retrieve session subscription a string. And there we will update the subscription record in the database. We will await Prisma dot subscription dot Update. And where, again, the same thing Stripe subscription ID is equals to subscription dot ID. And on data, we will update status to subscription dot status. I will wait for this event and below this event at the end of this body, we will do a return of a response, 200, which will be okay response, that will be it for this web hook. The message will be null in case and status will be just set to 200. You can see there the events. You can also now make there some comments. It's definitely handy for future, when you will be coming back to this code, now we can test our web hook. Of course, we want to test it on Y for now because we still didn't code it. But we will open our terminal and there we will do a stripe trigger payment intent succeeded. That will run. Now we will need to find this one exactly and it works. That means the webhook was coded successfully. There you can see we are getting 200 status request response, and now we can code DI and actually just go through the normal process, then check if our subscription is being set to active and also set the main product page and test the handling of displaying the content based on the subscription status. Let's open the File Explorer, and there we will go to pricing page TS six, and we will continue with coding the back end there. Let's first do there some imports. Next to button. We will also import the react. Then we will import Prisma there we have it in our lip folder and dbdt TS file. Then we will get stripe session that we defined in our lip folder stripe. We will get also the stripe itself there. Then we will get unstable no store from next cache, and we will use this to tell Next Gs that we don't want to cache some data. In our case, it will be data in G data function we will code. Let's do import unstable No store from next cache. And then we will import also redirect from next navigation. This one will come in handy because we will be redirecting our users in case he would like to subscribe and he won't be locked in. We will redirect him to sign in page. That will be for the imports and we can start with the first function. Right below imports, we will do async function and we will call it get the data. This will take user ID and take string or also empty value. Why is this important to also check for this new value? Because if this won't be there and it will be like this, whenever unlocked user will get on this pricing page, it will fail, and that's something we don't want. We want to let everyone on our pricing page check the price. But whenever he will want to buy the product, he will be redirected to sign in. There we will do the unstable no store. That means we are telling NextGS as I mentioned earlier, we don't want to cache this data. Why we don't want to catch this? Because subscription status can change, and we would like to show the most update information to the user, and that's why we will use it there. Then we will check if condition if we found the user ID or not. In case this will be false, we will return null, and I need to correct myself there, user ID, even if the user ID is null, but of course, then we will check it and we will just return now. That means this function won't return any value. Then we will look for a subscription in the database for our user, which is this one user ID. So in case this user ID will exist, it will just continue with this code execution, and there we can create a constant with subscription, and into the subscription, we will save RsmA, do subscription, find the Unique, and we will select where the user ID is user ID. There we would like status and also user from user, we will select Stripe customer ID like this. That means we will get there the subscription status and also the stripe customer ID. Now we can continue inside the main component and we can also delete this is subscribe In this main component, we will start with constant user ID, and this we will get from off and we will save into constant user, the current user. This is getting the user ID and full user object data. It looks like we didn't import it. Now, it should be fine. We will also get the user subscription data with calling the get data function we just did. We will save it into constant subscription way to get data with user ID. What we just did now is that we quote this function that we created there. We are sending there this parameter user ID, and it will return for us this status and the stripe customer ID of the user. Then we will create another new constant that will be this is subscribed, and we will check the subscription for status active. We have an error there and that's because we didn't return anything in our get the data function. We need to return the subscription, of course, save it. Now it will work, and it will work as before, but it won't be hardcdt anymore. We have there now this check of the subscription status. This value will be true or false depending on this output. What we want to do next there is another function, and this one will be asynchronous function, create subscription. There will be create subscription for this subscribe and then managed subscription for this other button managed subscription. Inside this function, create subscription, we will start with defining this as a use server. That means we will tell Next JS to run this function on the server. Below, we will check for the user ID. And in case there is no user ID, we will use the redirect. We import it there, and we will redirect user to sign in redirect URL pricing. Whenever he will click on great subscription, which will be there under subscribe button, he will be redirected to this URL. Then in case we have user ID and the user exists, so that means he signed in. We will save the database user, and we will await ismadtuser dot find Unique. Insight where the ID is user ID, and we will select stripe customer ID. We can do their additional check. If we are not able to find the user, we will throw an error. Let's do if condition. If database user is not found, we will throw new error we can do user or database user not found. Let's do database user not found. We know what happens in case we will be checking our logs after something will fail on our page. Now we can get the user's email from Clerk. Let's save it into constant email. There we will just search the user for primary email address, and there we will access the email address. This will be the primary one, and that should be always there because when he will login through Google, he will have it. And when he will login through email and password, it will be there also. In Clerk he can have more email addresses, but we will be accessing this primary one. Then below as we have this in case user doesn't have a stripe customer ID yet, we will create one, and this will be basically something like signing up for a new service and getting the ID number. In our case, getting the stripe customer ID. There we will do if condition, and if database user stripe customer ID won't exist, we will create a new constant for customer, we will await stripe dot customers dot create email to email. And we will update our database with the new Stripe customer ID as we got it. Let's do database user, await Prisma dot user dot create where the ID is in user ID or user ID is in ID for data. Stripe customer ID to customer dot ID. And select stripe customer ID. Now we can also add some Consolog for us database user database user. Now I missed something there because I have an error. And yeah, because I am not creating but updating the data or the user. Then we will do the double check that now we have a stripe customer ID. Let's do if condition database user Stripe customer ID. In case not, we will draw new error failed to set stripe customer ID for the user. Now we can finally create a stripe checkout session. That means we will send user finally to the payment page of Stripe where he will be able to buy our product. Let's do the constant subscription, URL. We will await get stripe session there we will set customer ID to database user dot Stripe customer ID. We will set domain URL to process dot enftnN in case this will be production. Let's use process dot N production URL as String, and in case not, we will use HTDP local host 3,000. And then price ID of our product, we saved in environment variables. We will do process dot dot strip price ID as string and that will be it. What we are doing there is that we are checking, we are on production, this can be read from this node N in case yes, we will set this domain URL as the production URL. And in case, no, it will just be for our local host, 3,000 where we are running our server. And then after this, we will return, redirect to subscription URL. And with this, we finish this create subscription. What we need to do below is to also define a function to create a new customer portal session. There will be the place where user can cancel or update his subscription. Let's do async function, create customer portal. And we will again define the use server. And then we will check for the user ID in case there is not, we will return redirect to sign in, redirect URL pricing and this shouldn't happen because we are having the check is subscribed and the user cannot be subscribed when he's not locked in. That means when the user is not subscribed or not logged in at all, he will see this subscribe button. This subscribe button will have OnClick function. This create subscription where this check already is. Now it's up to us if we want to do this check also in create customer portal because technically, it's not needed. Let's now create a stripe customer portal session. We will create a constant customer portal URL, and we will await stripe billing portal dot sessions dot Create what we said there is a customer from subscription user stripe customer ID as string, and also return URL, this will be there whenever user will click on a B button in the Stripe customer portal. He will be redirected there, and this will be again, same thing like before, rosst Noe N. In case, this will be on production. It will execute this position in case this won't be on production, it will return him on local host 3,000. Basically, in case this won't be deployed, and we will just have it on our computer. This is a turn operator, that means this is being checked, and when it is a true value, it will execute the first position, when it's false value, it will execute the second position. Now there, in case this is true, we will set the process dot Nf dot production URL as string. Now, last but not least, we will return redirect to customer portal URL. Now we prepare these two functions and we are ready to use them at our buttons. Also, what we will do there is a constant called B link, and there we will check if user ID exists in case, yes, we will again use this term operator in case yes, something will happen there, in case no, something will happen on this false position. When user will be locked in and he will have this user ID, that means when he will click back on pricing page, we will redirect him to a dashboard. When he won't be logged in, so it will be unauthorized user, he will be redirected on a lending page. Why to implement this is because we will have pricing page in root folder. Everyone can get to this pricing page, and to log the users will usually get to this pricing page from a dashboard. So when they want to go back from the pricing page, they will be redirected back to their dashboard. And when users are not logged in, they are going to this pricing page from a lending page. So when they will click on Back button, they will be redirected back to lending page because maybe they will want to check out the demo again and just check the lending page, and they will want to still decide if they will buy our product or not. Now, if we go into the render of this component, what we just need to do is set action to this form. For this managed subscription, it will be the create customer portal. And for this subscribe, it will be create subscription. Then on the card, I will add the B button. That means somewhere there, I will create a link. I can import it, and inside, I will put back with back arrow that should be this. If I'm not mistaken, let's see. For this link, the HRF will be B link and some classes also, we will tert end of text small, font medium, text, primary underline offset four and on our underline. Let's save it and let's go to our page and see how it looks like, and it works. Now we go back to Dashboard and we can test the world functionality. Let's click on subscribe and we got redirected to Stripe. We can see the price of our product is there. Email is there. Let's now fill the data. Now we got redirected to payments success, and we didn't code this page yet. Same story for payments cancelled. But being on page payment success means that our payment was successful. In our super baase, you can see that we got a new subscription there connected to our user. That means the payment and subscription status update was successful, so our Stripe webbook is working fine. Now we can go and go to the next functionalities. For example, we now need to tackle the successful and cancel page in our payment folder in case the stripe payment will end with a good or bad scenario. 10. Payment Pages: Now what we will do is that we will create the folder in app, we will call it payment. In this folder, we will create another one and it will be success. And then click there on the payment and create another one and call it canceled. Inside these two folders, we will create a page dot Tsix. Same here. And now we can start in canceled page T six, we will define this as use client as it will be on client site, and we can start with export default function cancelled. And inside, we will do the return, and in return, we will start with the dif. In this div, we will have heading one with payment canceled. Below, we will have a paragraph tag where we will have the description of what just happened. Your payment has been canceled. No charges were made. You can do something like this. And below I would do a button and our button that we imported from Chet CN, which will be this one, inside this button, we will do a link. We will import the link from next link. Now we will add their TF, and that will be to pricing. We will return to pricing. Now let's add some styling for the dith that wraps this. We will do flexbox layout, flex direction column, then items center, justify center. So we have it nicely centered horizontally and vertically. Then minimum height screen. Now if we will save it. We also want to see what we are doing. I will go there on my page, and in the URL, you will do slash payments CansLD Now we can already see it there. For payment canceled, we will add font, both and text to Excel. Now we will add the space Y six. For paragraph, we will add text Excel and I think that can be it. We will click on Return to Pricing, this should work, and it works. Now if you will go to actually, let's first take this, copy it, go to success, paste it there, rename this to success, save it. We can go back to page. There we will do slash payment slash Success. Now we will change this to payment successful. And we will change this paragraph tag to something like thank you for your purchase. Your payment has been processed successfully. Now we will save it and we can see how the page looks like. And maybe we can also add some div that will have width of 300 pixels will have height one will be background green, 300. Height, actually, let's change to something like ten pixels. Let's see what happens. Okay, one pixel, three or two. Yeah, now it looks better. That means the payment successful page will look like this. If I will copy this and paste it to canceled, I will change this to red. Let's check how this will be on a mobile phone. I will change this to iPhone 14, and we should add their text to center. Otherwise, it looks fine. Let's go back there. Let's put their text center to the main wrapping div. Now let's copy it also to a success page. Now let's check it again. We can do the inspect and we can see now it's fine. 11. Sign In, Sign Up: Next thing we will do is that we will go into app folder, and there we'll click on create a new folder. We will do the parenthesis and create there off. This means that this won't be visible in route. If we will put this sign in and sign up, the route won't look like off slash sign in, but just slash sign in. We will use it because better folder structure, so everything related to off of user will be in this folder. Now let's move it there. It won't be easy because we are not able to move the wall files, or at least I'm not able to do it. Let's move it like this. Then I will put there this sign up, and now we will put sign in into sign in and sign up into sign up. Now, it should be fine. We have there to sign in. We have there to sign up. And the next thing where we will do is not only just making the better structure there, but also making a styling for our sign in and sign up, even though it's from Clark, let's now go to it. What we will do is that we will click there on Sign Out and click again on sign in. And we have there two pages. First one is when we are clicking the sign in. But when user is not registered, you will click on Signup and it will change the page for us. Let's go back to our IDE, open the signup page. Let's make sure we have it opened also on our SAS page. And there we can start styling. Let's first start with creating parentheses for this return. We will still use this signup, but we will also create a dif and we'll put this signup tag inside this div. Now for the signup, we will keep it, but we will add more attributes to it. First attribute that we will add will be called appearance. Inside this appearance, we will do elements, and there we will do the separate styling for all of the elements that are in this sign up component. I will do an example here. I will put there footer, and for Footer, I will add styling of hidden. Now you can see the footer of our component of signup disappeared. And we will like this style all the elements that are inside the signup component. Maybe before we do this, let's start with the DIV. And in this div, we will do heading two, and we will call this create An account. Below, we will do paragraph tech, and inside, we'll do signup to get started. Now let's add some styling. So for the main div, we will add margin from top, flex Books layout items and Justify center, flex direction column space Y 12. And also I think this is it. For the dith below that is wrapping this heading and paragraph, we will put text to center. For heading, we will do text tree Excel, font bolt, and text foreground. And for the paragraph tech, we will put margin from top, even though this could be handled by space Y two, for example, text small, text muted, foreground as a color, save it. Now let's check how this looks on the page. Maybe we can do their text large. I think that's better. And now we can get to styling of this sign up component. Let's start there with styling of the card. For the card, we will put the background card. Then we will continue with border and border border. We will add some shadow for the light mode and rounded Excel with some bedding. Yes. Now the next element will be header title. We can make this hidden. For header subtitle, we can make this text muted foreground. Let me check out this looks like. Now, next we'll be social button, Block button, and Google. There we will set background to. Let's use white because it's really barely visible. Yeah, I think we will use white there, even for both dark mode and light mode. Also, we will use, I think we will just keep it like this. Our background white with 0.6 opacity. Yeah, I think this is fine. And for light mode, it will still look good. Maybe if we do foreground. But it won't look good for light mode. I would keep the background white. Now if we will continue, we will do the divider text, divider text. There we will set text muted foreground. Now, divider line. This one, we can set to background border. And on the page now, it's barely visible, but it's there as a nice dividing for Google App and email. Now let's continue with Form field label. For this, we will set text foreground. Now how to do the link to sign in on our own. We will create link. We will click there on Import. This way, we will have it there from Next Link library. And inside, we will put something like actually, let's just copy it from there. But first, let's edit the Hf. So it works to sign in. Now we will have it on the page. There we will copy this. We will put it there. And we will do it like this. We will put all of this sentence into paragraph tech, and we will leave darlink for the sign in. That will redirect user to sign in page. The styling of this, we will copy from this sentence of this paragraph tag, sign up to get started, put it there, save it. We will hide this scooter. Now we will check how the page looks like. We will add there for this link underline. Now, that will be it, if you will click on this link, we will get to sign in page there. That means we can now and we are ready to style the sign in page. Let's go there and sign in. And what will help us is to just copy this put it there. Then we can see what we can reuse. We can reuse this import of link, and we can just paste this sign in, delete these lines of code, put it there, and then save it. Now, remove this hidden footer. Go to the page, copy this. Don't have an account, sign up. Now we will put it there on the last paragraph tech. We will take this sign up and put it there instead of this sign in. What is important to mention is that we cannot have this single quote there for the paragraph tech, otherwise, this will fail deployment later. Let's add there this, and this is there for a sign of this single quote. Now, if we will check the page and add this footer as hidden, I think we have it for the sign in, and now we can try to click on Signup and it won't work because, of course, as we are copy pasting code, we usually forget something. So take care when you are copy pasting, and this should be sign up in this href of the link. Otherwise, of course, clicking on it would redirect us to sign in where we currently are. Now, let's try this, sign up, sign in. Everything looks fine. And in light mode, it looks fine. And now we can sign in 12. Subscription Check: And after we signed in, we can now see that we are on the dashboard page where you are not subscribe is shown to us. But if you click on subscribe, and click on Managed subscription. We can see we have an ongoing subscription, so we should see the product, of course, and that is something that we will code now. We don't have any functionality for showing our product because we will go there into Dashboard and page TS six, we need to do that check if the subscription is active, and in case it will be active, we will show the product. In case not, we'll just return this. You are not subscribed. We will import Prisma from our lip folder, DB then we will import redirect from next navigation and that will be it. Now above the return, we will create a new constant with user ID, and there we will use the off. It will be imported when we click it. Now we will check if the user ID was found, and there in case not, we will redirect to sign in page. Then we will query the database for the user's subscription. We will do constant subscription, awaits Prisma subscription dot Find Unique. The inside, we will do where user ID is user ID, and we will select status because we are curious if the status is active. If we will go into return, let's do the empty fragments. The check will look like that if subscription dot status is not active, then we will return this text. In any case, it is active, it will be returning this main dashboard content where we can for now put the similar text and right there, subscribed to the app, and we can delete the button. For now, we will just have it like this. Of course, then we will put there the main content of our product. Let's go and check the page, and we can see that we are subscribed to the app. Now let's sign out, and we will sign in with a different account, and we can see that we have there the information that we are not subscribed. Now next test we can do is that we will go into Super Base and we will change this to active. KK, for example, really doesn't matter. This is just a test and we will go back to page. We will see that we are no longer subscribed. Now let's go back to Superbse, change this back to active. And we are again subscribed. Of course, this was generated by stripe. Now we just tested it that it really reads the status value and it works. What we will do now is that we will go back to our IDE, and there we can delete these fonts, and we can prepare a few more folders. First, will be in dashboard, and there we will create a new folder with underscore components. That means we are creating a private directory for the dashboard, and in these components, we will be inserting only the components related to our dashboard page. Then in the components in the root folder, we will create a new folder and this will be called Landing page. Also, remember, let's do ending dash page because Next JS is using Kebab case and not Cam case, for example, like lending page. And we won't be doing the underscore there. As we will be styling the lending page, we'll put all components into this lending page folder. We will have there, for example, testimonials, product demo and so on, and for this purpose, we will use this folder to achieve a nice folder structuring in our project and whenever we will come back to it, we'll know where we can find each of our component. Seeing the page when we are signed out, we can still see there the product profile and pricing. Even though we should see only pricing because product and profile are some functionalities only for log in users. What we will do is that in our IDE, we will go to Navbar because there is the functionality, and there we have hard coded is signed. With Clark, this is really easy to handle. There we will just do and put this in curly braces like this and do use users. It will import it there from Clark use user, then we will rename this to assigned in. We will reuse it there. We will save it, and now this should be handled for us. And now we implemented the functionality. So whenever user is locked in or locked out, we will be based on it showing some menu items there in our Navbar. 13. Product: In the dashboard folder, I will go into the components, and there I will create the main component that I will call thumbnail previewer dot TSX. There, I will define and indicate that this is a client site component with use client. Also, I will import the necessary react hooks and other components. I will first import their use state and use effect. And I will also import the input from the custom input component we are using from Chet CN. Then I will continue with importing the button then with the laptop, tablet and smartphone for the icons, and also importing the use team as a hook for team management. As for the images that we will be showing in the YouTube Mc, we'll be using URL. I will define the constant of a placeholder image. That will be there as a placeholder image. In case there won't be any real image for the thumbnail, and there we should ideally put the URL of this placeholder image. I will be using placeholder dot SVG. With height 720 and width 1,280. Now you will need to define an array of random video objects for the initial display that we'll be showing on our product. I will create their constant of random videos. And there for every video, I will define a title channel we H and thumbnail itself. Into the stump nail, I will be putting the URL of the stump nail. How I'm doing this. I'm doing this manually because I'm not using any functionality for the admin to deploy thumbnails. It can be made. I also can be a good idea, but for our use, it's enough if we will just do this manually. Because we can preset this and just leave it there for our product, maybe updated every month. I'm using this page, uploadf.com. There you will just connect your Git up. You will click on Upload. You will put there some of the image. For example, I put there the thumbnail images, I download it. Then you will click on these three dots after it's uploaded and you will click on Copy file URL. After you will click on the Copy file URL, you will have it in your clipboard and you will just paste it there into Thumbnail URL. Then you will just put there some age, some views. Channel and title. Like this, I will now input there some of the videos I will be using to recreate YouTube UI for testing the thumbnails. You will have this in the project on my Git that will be linked in the description of this video. So if you don't want to now put the work into and upload all the URLs and paste them there into the thumbnail, you can just reuse mine. But be careful. There's a chance that these URLs are no longer valid because maybe they go delete it from my upload or so. If you want to be sure that these thumbnail URLs will work, just use yours or at the thumbnails into the assets somewhere there and put there the source files. Now we'll define the interface for the component props. Let's do their interface. Thumbnail reviewer. Where we will do channel name saved to string. Channel name saved is something we don't have yet, but we will define it in profile in while because to make our user not write his channel name all over again, we will save it for him in our database, and every time he will want to test the new thumbnail, we will display it. Now let's define the main reviewer component. There as a prop, we'll do channel name saved. That should be a string. We will start inside the component with defining the state variables using U State Hook. First, will be a title with set title and the default value will be empty. We will continue with Tumbil URL with set thumbnail URL, and default value again empty. Then with the channel name, that will definitely be again empty and then with the videos. There will be a state for the video list, and there we will input random videos, which is the array that we have there. We will continue with layout. For layout, the default value will be desktop. And let me explain. We will be using their multiple layouts. User will be able to select if you want to display this UI for the thumbnails as a desktop or tablet or mobile because when he will be testing the thumbnails, we want him to be able to test it for all the screen sizes. Let's continue with use effect to update video title, channel name or thumbnail URL. We will define use effect. And inside, we will set videos with Title two channel name used to zero age two now. By the way, this will be the setting for the user video. Thumbnail to URL or placeholder image in case he won't load any thumbnail image, and then we will set it with random videos. The dependency array will be whenever the title will change, channel name will change or thumbnail URL will change. Now we'll declare function to randomize the order of the videos because we will have their button that when clicked will be randomized disorder. So user then will be able if he can easily spot his thumbnail or not. Let's create a randomized order. And set videos where you do breath videos. Dot SO and we'll call math dot random -0.5. And what this does is that this function will randomize the order, as I mentioned, and it will create a copy of the previous video array using the spread operator. Then it will use a sort method with a random comparison number that will return minus five to 0.5. And then setting the new randomized array back to state using set videos. Next function we will need to declare is a function to get the appropriate grid. Based on the current layout, we'll create a function called Get grid class. There we will switch on layout and how switch works. In case this will be a desktop, we will return grid comes one with a small screen, grid comes two and a large grid comes five. Then we'll do in case of tablet we will return also grid calls one with small screen and above grid coals two. We will set maximum weight to thousand hundred pixels, and we will center this with mix auto. Then in case of mobile, we will return grid coms, maximum weight of 340 pixels and the mix auto the last one will be default. That means default, this switch will return Great columns one, small screen, great columns two, and large screen, great columns four. Whatever will be passed to this get grid class, we'll consider the desktop tablet or mobile or devolt of course in case it's other value, and then it will return and apply these talent classes we defined there. We will do their return, and inside, we will start with the Div. For this div, we will add class names. We will do their relative width and height to full, then G two background. And text to foreground. Inside, we will start with the input and preview section. We'll do the div. And for this dip, we will put a maximum weight to 1,200 pixels mix do to center it. Inside, let's start with another div where we will use the grid layout. On medium screen, we will increase it to grid calls too, and we will put there some gap. Inside, we will div that will hold the inputs and below this dith, we will create also a div, and this will hold the Tominal preview. Let's start in the upper div. There we will start with heading three input. Then the two inputs we will hold in the div for the inputs, we will use space Y or inside, we will do an input. For this input, the attributes we will add will be placeholder to title, value to title, and on change, it will set title to the target value. Then we will create another input. And in this input will be a type file. Then it will accept only images and non change, we will create a file where we will set a target files, the first in the array. And in case this file will be there, we will create a constant of reader, new file reader, and we will call this reader on load method. Where we all set thumbnail URL to the target of the file, we just load it. And we will read as data URL. Now we will save it and also to see this and test this, let's go to page there on the page. We just double check its dashboard page. We can add below the subscribed to app thumbnail per viewer. Import it, have it there. Now we need to input also the channel name saved, where I can put test for now, save it. Now it will be displayed on our page. And let's get a bit back to this input that maybe I need to explain a bit better. The type pile will create the input for us where we will be able to select the file from our PC. The except image will make on images being available to pick for us. This change will run whenever we will pick a new file. And what we will do there is that we will get the first file that was picked. Then if it's true, so if the file exists, we will create a special tool that can read the file reader, and when the file is done being read, we will save the image data as a URL string. Then we will start reading the file as URL. We can now go to our page. There you can see we can put some title, and there if clicked, I can pick an image. Now the image is not yet preview, I will leave it there and we can move to setting the image previewer there after this input and also after this div, let me show you where this starts. We will create an input. The attributes we will add there will be placeholder, that will be channel name saved, which is the probe we are sending to this component or just channel name. Then the value will be the channel name or a channel name saved. And on change we will set channel name to target value. Now we will head into this second div, and we will do the image preview. There we will start with heading three, and we'll put the thumbnail preview. Let's add the sum classes. Let's do textarge, font medium, leading six with margin bottom four, and that can be it for now. We'll continue with the diff. For this div, we will put the classes of aspect width 16 and aspect height nine. That means we want to maintain the aspect ratio of 16 to nine. Then we will use rounded large to increase the border radius. We will set overflow hidden, so nothing will get out of this dith and also we will set w to, let's say, 60%. Then inside this dip, we will create an image. Attributes we set there will be the source for thumbnail URL or placeholder image in case it will be empty. Then note thumbnail preview, and then class names with object to cover w and height the full. Now you will save it, you can see that there is the image I put there into the file. And that is there. Now we can style it further. I think I will start with taking this class name, space y four and putting it there. Also, between these two inputs, the input one and input two, we don't have any space because this should be actually put next to the inputs. And maybe we can even delete this wall Div. I mean this one. That means we can format it like this, put it there. This one like this, save it, and now it will look better. We have this nicely aligned with inputs and thumbnail preview where there are the inputs. There is the preview of the thumbnail we want to show there in our product that we will define below. And for now, it will be enough if we will put the border to bottom and border white with points to opacity. Maybe also we can add some padding to bottom, 12, Now, if you will check where this di ends and below, we will put some content and save it. We can see how it's being divided. We can name this or command this as an input input and preview section there we can take this command, and below, we can start with the product section. We will create a div there, and first, we'll do randomize order button with layout slider, where we will select the layout that we will want to see our thumbnail on and also we will have randomized button, where we can shuffle all the video cards that will be next to our thumbnail. Randomized order and layout selection. For this randomized order and layout selection, we will set the classes of margin to bottom six, Flexbox layout with items to center space X, so horizontal spacing, we will make there between arronments to four. Then we will set a maximum weight to 1,200 pixels and a mix order to center it. We will have the button first. And for this button on a clique, we will call the randomize order, and we will name it randomize order, which is kind of obvious. Now we will save it. Let's check if the button was edited and I can see it on our UI. Then we will continue with a div. And for this div, we will add classes of flexbox layout again, items to center, space X two, round it to we can do full as this will be some slider. Let's add some padding to it. We can shadow, and I think we can save it as is inside, we will add a button, and this button will have the laptop icon. For this laptop icon, we can just set something like height 24 with 24. Then let's add some classes there. For the button, we will be setting actually first some different attributes. And that will be a variant. We will set with the Turner operator. Let's check if the layout is set to desktop. In case yes, we will use default styling, in case no, we will use Ghost variant. Then we will continue to size where we will set icon. Then we will set OnClick function. That will be setting the layout. So in case user will click on this button for the desktop, he will be setting layout to desktop. And then we will label to desktop layout. Now below, we can continue with another button. There we will use the tablet icon again with some classes, high 24 with 24, and we will cose it. For the button, we will again add some attributes. I will do again the variant that will check with the turner operator the value of the layout. And in case it will be tablet the true position will be default and false position will be ghost. So in case this is not true, it will set the variant of this button to ghost. Size of this button will be icon, then on click will be setting the out state variable to tablet and label will be tablet layout. Now we will move to the last button, and again, there will be smartphone icon with classes high 24 and with 24, and the attributes will be again, a variant, where we will check the layout in case it will be mobile, we will execute the default and in case not, we will set a style of a ghost. For size, we will again set icon. For click, we will called the set layout, where we will set the state variable on mobile. Then the label will be mobile layout. Now, if we will go to our page, I can try setting a different layout. And it's working, you can also see how it's switching the variants of the buttons. So the selected one is a default variant, the not selected are the ghost variant. Of course, it will be switching also the styling of the UI for our Mc of the YouTube reviews. Let's move below this section. We will take the command there. We will put it above the div we will create and we will put there video cards for thumbnail reviewing. Below this command, we can create a div. And in this div, we will do class name where we will put back quote and we'll put the grade class name, and then next to this grade class name, we will put $1 sign and the values from Get grade class. There, based on the layout we will select will be desktop with these columns two or five, tablet with maximum weight and mobile with also different maximum weight. Now we will also s there a gap to six and also based on the layout. In case if the layout value is mobile, we will set the width to full. In case this will be false, we won't set anything. Now we will map over our wideos array. Widow will be the name of the current item in the array and index its position. There we will now open this and we will put there a div into this div we will add a key. This key will be an index. Then we can save this already. We will continue with adding their class names, and we will use their back quotes because there will be a variable check or turn operator on the layout as we will be checking if it's a mobile layout or not. Let's do curly braces and put their back quotes inside, and we will start with the normal tail end classes. Let me start with the first one and that will be overflow hidden to not get any content out of this div. Then some shadow. Then round it large. Also, we will put there now the check for the layout. So we'll do turn in operator there, and in case it's mobile, we will also return for this maximum weight of 340 pixels and mix to center it. Otherwise, if it's not mobile, just return nothing. Now we can go inside this div, create there another one. For this dip, we will add a relative class and some padding to bottom. I will put there something like let's say we will do 60. Then inside, we can start with image tag. And we will add the attributes for the source, which will be a video thumbnail. In case it's not there, we will use the placeholder image. We will continue with OT, which will be video thumbnail. Then we will continue with glasses. There we will put absolute position inside zero, width and height to full and object to cover to show the best of the image. Then we have closing of the div and below this div, we will create another div. Now you can already see we are displaying the video thumbinails on our page. So everything we loaded there is being displayed. But of course, it's still not in the shape we would like it to because currently, the image is taking the full width of the wall video card. This is not how it works. Instead of, let's say, 25% of what we can see on the one video card, which is the one square, we need to also display there the title views and when it was uploaded. Just the standard video card that is on YouTube, for example. Let's go back to this day we just created because we will do it there. For this new div, we will add a bedding and also we will add another div. Inside this one, we will put the class names with flexbox layout items start and spacex three. We will do a first paragraph tech that will hold the Widow title, then a next paragraph tech that will hold with the channel in case it's empty, I will put the channel name saved because that will be the channel name of our user. So he will have it pre filled. And next paragraph tag that will hold the video views views, and now video age and also we need to do period there between the views and video he and now it's looking a bit better, but of course, still some styling left. So let's now do it. And we also forgot the avatar. So we need to d it there. Let's add there a div. And inside this disk, we will put image, and we will again add the some attributes, which will be video thumbnail for now. We will use video thumbnail as an avatar, so we don't need to again load now the separate avatars for every channel. There would be much work on top of this because it's just about uploading the images and putting it there. I believe this is easy to do then, but it's just a lot of repetitive work to do, but everybody will probably do it themselves. It's just about loading there instead of the thumbnail, URL, also Avatar URL, but I don't want to again reload to the upload thing like eight images for Avatar. So I will just leave it there and I will reuse the video thumbnail. I believe on the testing of the thumbnail, it won't have any effect. So for Avatar, we will use video Tumnail in case it's empty. We will use a placeholder image, or it will be channel Avatar, and classes width to nine, height to nine and round it full. Now what we will also add for this avatar will be flex shrink, zero, and also what we will add there for this flexbox layout will be flex direction column. Moving there to these paragraphs, we will create a div for them. We will set to this dein with zero and flex one. Maybe now we can delete the flex direction column. Now we will see the page. It's already looking good on the tablet. We need to fix this for the desktop. Let's continue with the styling. Maybe I can also make it a bit bigger so we can see it better. Like this, and we can continue with the styling. For the paragraph, I will put there first classes. I will start with text small, font, medium, truncate, font heading, and I will use a text color of this code, which I had in my design file. Then for the next paragraph, I will again use Tex small. And now the color to have it exactly as on the UI of the thumbnails we want to recreate, I will put there the code of a really, really light gray color. Now I can just copy paste this also to the next paragraph. Let's see how it looks now. Now we are pretty close, I believe. I will What is the issue there, though, is the weight of the video cards for this test. Let me add some thumbnail. I will put there, for example, this one, first thing we will do is that we will remove a maximum weight from there to have it like this exactly. And that means I think in the end, we can also remove this div. Let's take the closing tag of the div there and remove it there so we don't need to keep the empty additional div. Now, if you go in the page, it looks like more UI with the video cards, but I guess we will still need to quickly check the proper width and height and set it as it should be. The ratio we would like there is nine to five. How we can achieve this is that we will add padding to bottom. That means let's go to code. Let's go to the thumbnail, which is there this one. Now we are using petting to bottom 60, but I will put there bedding bottom to 55%. I will save it, and now we have the video ratio we will use for our tumnails now it's finally looking like we are on some page and we are listening through the tumnails. Let's now, as we already filled in the data with the tumnail test the functionality itself. So I will randomize the order, which is working properly, so it's fine. Now I will write the tablet version, randomize it also there, so it's working. I will write the mobile version. And on mobile version, we can see that we have a smaller d. So we need to fix this da layout, mobile, maximum width, and Modo, and width to full. Save it, and it will be all right. 14. Landing Page - Animation Container: Container. This will be a component where we will put motion div and animation set, and we will be then just calling this and we'll be wrapping our content to it to have our landing page also animated. We definitely don't want to rewrite all the motion dive into all the components we'll use because there will be a lot of additional lines of code. We can just do it there, put it into global component, and then reuse it. Let's actually start with writing this animation container, so we can then reuse it in our hero section. Use client, so it's rendered on client site. Then I will import the motion from frame or motion. We don't have this library yet, so let's open the terminal. Let's run NPM I framer motion, install it, and now it will be fine. We will define the interface for animation container props. We will put the children will be react dot react note Also with a small N, then we will do delay, that will be a number, reverse, that will be a bulling, then class name will be a string, animate, that will be NA, then initial also NA exit, and mode, there will be a string. Then we need transition and onclick. So transition and onclick function. We will define this as white. Now we can continue with grading constant for animation container, and we will start defining the props. First will be children, then class name. Reverse I animate, initial exit transition, and that's it. Also on click. Then these are animation container props. And there we will be returning the motion div. And the attributes for the motion div will be a class name with class name initial with initial and in case it's empty, we will put the opacity to zero and white to operator of rivers depending if the reverse is true, we will put there -20. In case it's false, we will put there just 20. Then animate, again, we will set the animate. In case it's zero or doesn't exist at all, I mean, we will set opacity to one and Y to zero. This means that when the value is not there, so we are using this or, we will execute this value. So this animate will have this value, but in case we have some value for animate or initial they find there in the props, it will use that value. Let's continue to exit that we will set this exit, then viewport, where we will set one fast because we want the animation to reappear when we will be entering out and in the viewport, then we will set the transition we will check for the value in case it's not there. We will set the duration. So some base values for our transition animation, I will set duration to 0.2, then delay to delay is, I will set to is in out for some smooth acceleration type, I will set to spring. That means it's using some physics based spring animation. We will set also stiffness to 260 and damping 220. Also, for on click of this div, we will set the onclick prop then inside this div, we will render the children, and that will be it. We will then just export default animation container. And that's it. We have our animation component that we'll be using to wrap our content to have it animated. Let's go into hero component, and there we can finally start coding. I will start with imports, and I will import the link from next link. Then I will import the animation container, and that will be for now. We can move to creating export function hero and there we will be declaring everything into this return. Let's do this. And there we'll start with the relative class, then flexbox layout, flex direction, column items to center, and let's do some spacing. I will use space Y 20, and on medium screen, we'll use space Y 40 to have some even spacing between the elements on this page. Inside this div, we will start with the animation container. And the only thing I will say there will be the flexbox layout, flex direction, column items to center, justify center, and width to full. Then inside, I will create a div. For this div, I will add a margin from top on medium screen, I will increase it a bit and appendix to four. Now we can finally start adding the content itself. So again, animation container to have everything animated and there put the first property, that will be the delay which we will set there 4.2. And inside, we'll put heading one. That will be thumbnail reviewer. Now we will have it on our page very soon. Classes for this will be text three Excel, small screen text for Excel, medium screen text, six Excel, and fond boat and margin bottom. Now to have every component we will do on our page. We, of course, need to add it to the page. So an app, and this page, we will start in the components. So I will add their hero section. And like this, I will be adding there all the other components as well. You can see that the terminal perview heading now was displayed on the landing page. Behind, we have the grid layout. It's starting to look good and we have there only just two words. So hopefully this will go smooth. Now let's continue. What we will do next is that below this animation container, we will redo it. We'll again call our component Animation container. We'll put there a higher delay. Let's do 0.3. And inside, we will do paragraph tech. Inside this paragraph tech, we will write review your thumbnails in a realistic environment. Now we will do the spacing, Spen tech, and three easy steps because we need to do some nice promo for our product so people will actually buy it. We will start doing the styling. I will put the text Large text seven Excel. Text to Excel on small screen, text Excel, medium, text, to Excel, font to bolt, margin to bottom, maximum width Excel, and a mix auto. Maybe we don't need font bolt actually, and maybe we also do text center. Let's put a Spen tech on the next line because we will add the gradient text. And what is this gradient text? It's actually some custom gradient text we will now do in Globals dot CSS. So let's go into this file Globals dot CSS. There somewhere we can do it on the bottom. We will go to the CSS classes for gradient text, but also for the button. It will be easy. We'll just do the gradient text and put there at apply background gradient to right from and color number. Via again, color number. Two, again, a different color number. Now, I believe we have it, so we can just copy this and paste it below, call this gradient button. And actually, what we will do is that for text, we should also add text transparent and background clip text. Now it will be fine and it will work. We can go back to our hero section. There you can now see how it looks like on our page. Opacity to 70. And maybe that looks even better. Now as we did also the gradient button, that means we'll do the buttons itself. Of course, let's continue below this animation, and we will add there again animation container with D 2.4. And inside, we will do a div for this dip, we will add a flexbox layout with flex direction columO small screen and above, we will make it flex direction row, it's next to each other, justify center, then space Y four to have there some spacing between on smaller screen, we can reset this space Y to zero. Again, on smaller screen, we will just need to add some space X to four because the buttons get the different position. Inside, we can start with a button. Let's also import it. So if you don't have the button yet, just run this command N PX ChetcN at latest at button. And by this, you will add any component from the ChetsiN library. You can also make this command chest at card. You will add card to your components, and then you can reuse it like I'm using this button or not now, but very soon, yes. We need a some attributes, starting with variant where we will put default. Then with sizing, that will be large setting as child and also class names. For class names, I will put there the gradient button transition transform because I will be on Her increasing the scale to 105. Then I will set also text foreground and font both. Now let's add a link with HRF to most probably something like dashboard and get started. Now we can see the button. And below, we can continue with another one. Let's prepare the attributes. We will use variant outline now, then size again, large as child and also class names that will be with two full and on small screen with two auto. Now we need to add some content, so link with HRF two pricing, and it will say view pricing. Now we have both buttons on the page. We will move to the next component that will be right below our introduction on the landing page, and it will be steps component where we will demo user how easy is to use our product in three steps. 15. Landing Page - Steps Component: I will do export function steps with some return. I will go to page, put it there, Import it, and we can happily continue with coding. In the step section, we will first do some imports, and we will start with importing the image from next image. Now I want to put there some pictures, I will put assets folder into my app And from there, I will import the thumbnails, so I will import thumbnail one from app assets one dot BNG, and I want to also do it for thumbnail two. And the same thing for thumbnail, three, and that's it. Then I can import icons. I will be using pencil from lucid react, layout, and I. Then I will continue with importing the animation container, and I can go right to steps component into the return, and I can start there with the animation container as a main wrapper, put a class name of mix Auto, maximum weight to seven Excel. Margin to top and relative. Then I would also like to close the tech, of course. And inside, we can start rendering something. I will put there a div. And in this div, I will start with the top border. We'll be using their borders around our steps, and the first one will be in this div. So actually, it won't be even opened div, and we can start with absolute position, top zero, left zero, right zero, height two pixels. Background gradient to right from transparent via foreground with 0.5 opacity to transparent. Now you still cannot see it on our page, only we will put there something like this, and now you will check the page. You will see it there a little bit above it. But of course, as we will add the steps, it will be nicely visible. We will do their left vertical border. Again, it will be closed on the first line. And for the classes, we will at their absolute position, left to 33%. Then I will continue with setting top to 10%, bottom to 10%. Width to one pixel, background gradient to bottom from transparent, a foreground 50 and to transparent. Now one more diff and we are going straight to the content. So again, like this and put the classes of absolute. This one will be on right, 33%, top, also, 10% to bottom. With the same width. Now seeing it maybe I could just copy paste it, the ground gradient to bottom from the transparent a foreground with 0.5 opacity to transparent. Let's add the content now and we will see how this looks like. First, for this day I will add a grid layout. And in this grid layout will be the three steps. So on medium screen, it will take grid columns three. Inside, we can call the animation container. There we will put some delay 0.2 for class name, I will input group. And inside, we will do a div and there we will add classes of relative, bedding, eight, transition all duration to 300, BG background, with 0.3 opacity to change a bit on how we will make it 0.5 opacity, then a backdrop blur small, some shadow, and on how we will increase the shadow to Excel. Now, let's just first add some content to style the other things. What we should put inside is first the div that will hold the step one, which will be basically the icon. And next to the icon will be a text with step one. Then below this div will be a paragraph. So upload your thumbnail and details. And then below, we will also put the image. So I will create the div with image the image will have a source of the thumbnail, one out of Tumbernil one also, and then fill and the class name of object to cover transitional duration 500, group hover with scale one oh five to increase the size whenever we will hover over. Now we finally have it on our page, so we can style it better. And you can see the layout, how it will look like. So there will be the first step, there will be a second one, and there will be the third one. Of course, we will style it, so it will look even better. Let's now continue. Let's do the comment that we'll call steps. There we can start with the styling. So for this dish that holds this step one with the pencil, I will put their margin bottom. Inline flex. Then I will continue with items to center, some gap, and some padding. Then I will make it rounded to Excel with border and border primary with 0.1 opacity. Now to the dipth below that is holding icon, I will put some bedding, I will put some background with primary color and 0.1 opacity and rounded Excel. Now it's still not visible because the image covers it. Let's put the styling for the image, I would say. For the image, we will set relative height to 52 with the full overflow to hidden. Round it to Excel, border and border white with 0.5 opacity. Nice. Now the step is finally visible, so we can continue with the styling. Let's get back to this icon. But I think we actually have everything there. To icon itself, we will put height and width 25 with text primary. To the step, we will add the classes of text to Excel, font medium, text primary and tracking wider. And now only the paragraph text left there we will put text small, text, muted, foreground, and margin bottom eight. Now we also want to add step two and step three. But do not repeat our code. We will just grade the constant with steps. And inside, I will put the information about every step. First will be the icon, that will be a pencil, then a step, that will be step one, then a description that I will input there later, image that will be thumbnail one, then image t. That will be just thumbnail or I don't even need to put it there. I can just then do the image into old. Then D, I will make it 0.2. Actually, I don't need to even put it there. I can just leave it 0.2 for all the steps. Now, I will copy paste this two more times. I will make it step two and three. This will be layout. This will be I. This will be thumbnail two, and this will be thumbnail three. Now our component is named steps, so steps array. Then I will go there above this animation container, I will create the steps array dot map. Name of the item in the iteration will be step and index will be the position. There I will now put this code with the animation container. Now, I will put there the step step. The I will put step dot description. There, I will put Step dot image, and I will put there also key, which will be index only thing I will do is that I will remove this animation container I will leave just this div. I will move the animation container there. I will take these classes for the grid, put it there, remove this div. In this diff, I will put another animation container closing tag. Now we moved it like this. Let's save it and see what is on our page. And we have there the three steps. What we need to do is to increase the width. That means we will go there and we can do background white to see how this is currently going. We can remove this maximum width. With mixoto. And what we can do is that we will remove this maximum weight on AmexooF medium screen, we'll put x like 48. Now we can check how this looks like. And when testing this one additional thing, we need to move this group to this div. Now it should be fine. So let's test the steps section. Let's test the responsiveness. And that means we can move to another section. Next section will be demo section, and this section is actually, I think, easiest one. 16. Landing Page - Demo Component: Let's go there to the demo component, create the export function demo. Do a return, put it on our page. Now we can continue there this as a client component, and there we will import image from next image. We will import app from the assets one PNG for my assets. Then I will import some useful things from frame motion. It will be motion, it will be use scroll, it will be use transform from frame motion and then also import Rf from react because we'll be using these refs as we will be moving this image that is basically image of our app. So there below the imports inside the function of our demo, we'll create a const of app image rev, where we will call the use Rev hook and set the default value as null. Then we'll create a constant of scroll Y progress and the scroll from frame or motion where we will set the target. So this should go to our app image rev and offset where we will set from start to end and from end to start. Now we will create two variables. First one will be rotate X, where we will transform the scroll progress, zero to one into the rotation. Transform Y progress, zero to one transform to 14 minus ten. Below you'll create opacity variable where we again transform the progress zero to one, 20 to two. What it means. For the rotate, when scroll progress is zero, it will be 14 degrees and when it's one, it will be minus ten degrees. For the opacity, the same thing. When it's zero, it's actually still zero. And when the scroll progress is one, the opacity is two, so it's fully visible. Actually, probably one is enough there. Let's continue inside the return, and in a while we will see how this animation works. I will do the d for this day, we will set text foreground and we will set BY 20, and on smaller screen, we can increase it a bit more. Also, let's say there's a maximum width to 1,400 pixels and a mixed auto. Inside, we will do heading two with test your thumbnails without limits. And there we'll put the margin from top text to center. Text five Excel. Now on smaller screen, text six Excel, font both, maybe let's say some opacity. And below the heading two, we can add a paragraph tech. Inside we'll do review, review your thumbnails on desktop, tablet or mobile, UIs For the classes, we'll put text Excel, text center, margin top to five, and text for ground with 0.5. I mean 0.8 opacity. I think the opacity there we can change to 0.9 on the heading to leave like this, that's better. Now below this paragraph tag, we will continue with the motion diff because we'll be adding there something that I don't want to now add to the container, so we can maybe later refactor it. For now, I will just use one motion if that's fine. For the ref, I will set the app image ref. For the style, I will set the opacity, that I will set to my variable opacity, rotate X, that I will set to my variable, rotate X, and also transform perspective that I will set to 700 pixels. Let's also add a class name there, margin from top, rounded Excel, overflow hidden. Shadow to Excel, shadow purple. Let's add some nice color to the shadow. Then border and border foreground with 0.1 opacity. Now there, the final thing, we will add the image to the image we are the source of app, which is the image we imported. Old will be epidemo, for example, class name will be width to full and height to do. Now let's save it, and we will have the image even with the animation. So let's scroll down, and there is it. And there you can see how it's being barely visible and changes too. Actually, we should go there and change the opacity two. Save it. Yeah, that's better. So I can now refresh the page. Scroll down. There it starts and it gets like this on our page. You can see how it's moving even, and you can even see the shadow around it. Let's now go to light mode. Yeah, it works, of course, everything. The design is working also with the light mode. But of course, dark mode is much better, at least for this design, definitely. But if somebody wants to use just a light mode, he can. And that will be it for the demo section. 17. Landing Page - FAQ Component: We can move to another one, and it will be frequently asked questions. Let's open Explorer and there in Landing Page, there we will do Export function, FAQ, return, can do just empty fragments there. Go to page, put it below the demo. Import it and we are set. What we need to do there as client one, and we will import animate presents from frame or motion. Then we will also import state. And we will also import the animation container that we'll be using as previously. Now we will create a array with FAQs. And for every FAQ, we will do a question and answer. I will do the three of these. So I think three questions, three answers is enough for now, and let's put there some questions. So the first question would be something about our product. What is TumbnailPviewer? Then how does the preview system work? And the last one maybe, is there a plan available? In the component, we will first grade state variable. So selected question with set selected question to set it and use state number or null and default value of our state variable will be null. Now we can go right into the return. We'll wrap this in div, and we can start with the first class. Let's make this maximum width of 1,200 pixels. Let's make this x auto to center it, BI 32, to have some vertical spacing around and peaks to have some horizontal spacing. Now if we will continue, we will create the animation container. There we will include some delay. Let's do 0.1. And inside, we can do the heading two with FAQ. For this heading, we will put text three Excel on small screen text four Excel, on medium screen, text six Excel on font bolt, text center, tracking tight and now we have it there. Maybe we can put there also some opacity to 90. Below, you will continue with another div for this div. We will set a grid layout. We can set some gap. We will have the frequently asked questions. On medium screen, we will make this grid cat and some margin from bottom. Inside this dip, we will map over the array we created there. That means we will do FAQs dot map. We will name the current item in the array iteration FAQ, and index will be the position. Then inside, we will create animation container. For this animation container, we need to set the properties, and that will be key as index. Delay 20.2, and for every FAQ that we will be mapping over, we will increase this by index multiplied by 0.1. Then for the class name, we will have their turning operator because we'll be checking the selected questions, and in case the selected question will be currently selected or the question will be currently selected, it will have a different color than the unselected questions to have this differentiated. So let's actually do there the back quotes. And inside, we can start with Bereni to six, Berny to five, text to left, rounded to Excel, transition all duration 500 to use the animations, cursor pointer, backdrop, Blur, medium. Now let's continue on another line that we do the dollar sign, and insight, we will check for the selected question. Or more likely if the selected question is the current index, which means that is the current item in the iteration. In case, yes, we will execute disposition in case, no, we will execute this position. In case it will be a selected question, we will set the background to primary with 0.5 opacity, border primary with 0.2 opacity. And actually, this is not 0.5 opacity. This is 0.05 opacity. And some shadow with some shadow primary 0.0 0.05 opacity. Now we can move to another line. Let's actually do it like this. And on another line in case this is false, so it's not selected, we'll just set background to 0.2 opacity on our background, 0.05 opacity, border white, 05 opacity and on our border white 0.1 basidi. Also, after we can add the border class, we should at the border class, save it. And now we cannot see anything because we still need to add the question itself. Let's do the H three. Let's display there the question. So we have it at least on our screen, but we are not done yet with the attributes. We also need to put there transition, and we will set to transition the duration, which is 0.3, type of the animation which is spring for us, then stiffness and damping. Also, let's set there on click function in case user will click on this question, we will set the state variable, so set selected question. Send the index, correct number of the sected question. Let's say we select the third question, so it will be set to the state variable and that question will get selected. We will test it very soon. Let's just do some additional styling for the heading tree, which is just text large with font light and tracking white. And now let's select the question. So I selected the first one. You can see how everything now works together with a really light border shadow and so on, and how I can select the different questions and it stays selected. What it will do is that we will sag the question and then it will show the answer below. Below this mapping, we will continue with a new div, and into this div, we will put class names of relative height to 140 pixels, then flexbox layout items and justify center to have it centered vertically and horizontally. Round that Excel, border with border white 0.05 opt, background, we will set to 0.2 opacit and backdrop blur to medium. Inside this div, we will throw the animate present. And for the animate presents, we will set mode to wait. What is animate present from the frame motion? This is a special component that will help us make a smooth animation when things will disappear and, of course, also appear from our page. When we will click different questions, animated presence will make sure that the old answer fades out nicely before going away, and the new answer fades in smoothly. Now we can animate presence continue with checking the selected question. In case it's not null, we will render this animation container. Where we will need to set the attributes, key as selected. Question initial as opaciD to zero with Y to ten. We would also like their animate with opaciD to one and Y to zero and exit with opacD to zero and Y two minus ten. Then we will set a transition where we will set the duration to 0.4. And the class name where we'll just at some pedding. Inside, we can start with adding a paragraph tag where we'll put the FAQs, select the question dot answer. And we will display the answer to the question like this. Then let's add some styling. Let's put this actually on another line. And for the styling, we will put there text base, font, light, tracking, white, and text foreground with 0.9 opacity. We can test it and we can see the animation. And in case this is unselected, there will be nothing, but we will fix this below this mapping. We will do conditional rendering, set the question in case it's null, we will do animation container inside, we will display select a question above. For there we can reuse the styling we have on the FAQ above and we can also put there some animation or just leave it as is. Let's now check the page. Now we will fix the wit. Let's go there and we will do there instead of this 1,400 pixels and we also set it width to full. So now it will take the full weight, but also it won't take more than 1,400 pixels weight. Let's see how it looks like. And now you can see that it's not changing the weight as we are changing the questions. Also, you can see the animations, boom, boom, boom. And one more thing we will do is that we will do our FAQ, put margin bottom to 12. That will be for the frequently asked questions sections, and now we can move to the next one. And that will be the pricing. 18. Landing Page - Pricing Component: Let's go there to the pricing and to make there some difference between the other pricing component, let's name this pricing lending. So let's make export function pricing lending. Now we will edit. First, we need to do a return there. We will it on the page. Not pricing, actually. Pricing lending. Now, there what we need to do are first sum imports. So I will do Import Link from next Link. I will also import the animation container and I will also import check from Lucid react because we'll be using it as icon. There we can start with a section. And we can put their class name of maximum weight, seven Excel. I mix Auto, PY, 20, four, Px, four, and relative. Inside, we will do two empty diffs, and we'll put some classes for them. For the first one, I will put absolute position, top zero, left zero, and right zero to stretch it from line from side to side. Then I will put their height to two pixels. Background gradient to right from transparent, via foreground 50, 0.5 opacity to transparent. Now below, I will basically do similar things, but I will put it to bottom left zero, right, zero, height. Also, we can use two pixels and background gradient from transparent via foreground with 0.5 opacity to transparent. Now we scrolled section, we can already see the dot, but it's actually these lines, but we will see after we add some content as it will get expanded. So now let's start with animation container. For the animation container, we will first set some delay with 0.0 and let me do it like this. And we will start and we will start with some class names there. I will put there flexbox layout, flex direction column, then also items to center, maximum width l, and Amora, width margin to bottom 16. Now let's start adding content into this animation container. Inside, we will start with heading two, and this heading two will be named pricing or we'll be displaying pricing, the name of this section. And for this heading two, we will add up bedding to three background primary with 0.1 opacity, rounded Excel, and also text to Excel, font, medium, text, primary and tracking wider. Now it's on our page. We can see how it looks like. And actually, I think background primary rounded Excel, we will get rid of this. Let's leave it like this and maybe more likely find there some icon door sign maybe, then put it there. Dollar sign, see how it looks like. So what we will do actually is that we will create a div. For this div, we will add a bedding 2.5, background primary with 0.1 opacity and rounded Excel. We will put the dollar sign inside, and we will also create there another div. Put there the things. And for this day, we will do flexbox layout, flex row, so the pricing, we do dollar sign are next to each other, and also we'd items to center. Let's now see how it will look like, and maybe we can decrease the bedding there for the dollar sign. We can do there some gap between and my las do 0.5 0.05 opacity. And that's probably it. I think we can leave it like this. That means we can continue. And what we can also do there actually is to add some text below. One plan rules them all, maybe something like this. Text to center, text to arch, text muted, foreground. Let's see how this will look like. Yeah, of course, we need to put it below. So like this, Yeah, that's better maybe 0.8 opacity. And maybe I would also switch the dollar sign with the pricing below this animation container. We will start with another one. We will set there a delay 2.2, and also class name, flexbox layout justify center and width to full. Inside, we can start with a di and for this div, we will set width to full. On medium screen, we will set width to 500 pixels. Then we will set the relative class with bedding to eight transition to all duration to 300 and background with 0.3 opacity, with how background to 0.5 opacity. Now we will continue there, and we will say there a backdrop blur to small then some shadow on how we can increase the shadow and round it to Excel to increase the border radius and add some border itself also. Now we will add some content, finally, and we will then again, refine the styling a bit. Let's create the div. Inside this div, we will put a paragraph tech used for one year. Something like this, maybe we can then update it later. Then below, we will create a div. In this div, we will create two Spen tags will be for the price, let's say, $19. And here, Classes there will be flex items baseline and Gap 22. Now for the span, the styling, we will add will be text for Excel, font semibot and the text muted for ground. Let's see how this looks currently. Below this div, we can continue with another div. We will create an array, unlimited, upload, save your channel information. Then we will map over it. We will name the item feature, and we will check the position with index, then inside, we will create a div. In this div, the key will be index and the class names, we will use flexbox layout items to center gap three, text, muted foreground. Inside this div, we will put another div and this div will hold the check icon. For the check icon, we will just set height to four with 24 and also text to primary. Blow, we will create a spenteg that will show the feature we have there. For the div that is holding the check icon, we will add rounded full background primary with 0.1 opacity. Flexbox layout items to center, justify center to center it. And now we can check how it looks like. I would also increase the pedding. Let's put their padding two and let's also put there space Y two. Let's say the peding one. We will create the link. We will at HF to sign up and the class name with the full inline flex. Items to center justify center rounded XL, horizontal padding to four and vertical to three and transition all with duration 500. Of course, now we also need to put there some names so get started, and there on another line, let's finish the styling with background primary. Then on H background primary 20 and text primary, also with border and border primary with a 0.2 opacity and on H border primary with 0.3 opacity. Now we have it, so we can see it on our page there, and now we need to update the styling a bit as we need some spacings there because currently it's a bit everything on top of each other. Let's delete this div and let's add there space y six. So when we are hovering over it, it gets lighter, and then the button also. For the button, when a user clicks it, he will get redirected to a signup page. When he will sign up, then he will be able to buy the product. I think that's it for the pricing page, no more things. We will now add there, and we can continue to another section, which will be called to action. 19. Landing Page - Call to Action, Footer, Updates: Let's go back to VS code, open the Explorer, go to the call to action. Do export function, call to action, do return there, put it on our page. Call to action. Now we have it and we can continue. What we need to do there is to first use client and also make import of the image there from next image. Next thing would be also import the framer motion. Currently just for testing, I will put there import thumbnail one from the app assets and one PNG. And I will do it more times. I will use it like, I don't know, eight times. Because I need to make a full circle out of these thumbnails. So just now for testing and as a placeholder, I will put there eight imports like this with the same image, and later we will change it for actual thumbnails. So I will put there just eight imports of eight different images, and it will be all displayed in this call to action section because it will be basically a rotating circle. And every time on the screen, I think, like three or four images will be visible because the other images will be in the second half that will be hidden below because, of course, in this section, only the top of the ring will be visible. We can go directly to call to action, and there we can start with a di. For this div, we will put a relative class with full PI 240 and overflow hidden. We will add the great background. So let's do the div that won't hold anything. Just two class names, we will put the absolute position in set zero, and now we will also put there something we already have on our page. So let's take it from there. And basically, we want to copy this put it there, set the opacity to 25. That should be fine then. Now we can see it on our page already. And below, we will also do, again, empty Di where we will put just a class name, and it will be absolute inset zero background gradient to bottom from transparent via black with 0.5 opacity to transparent. With this, we'll make the darker line in our section like this. Now below, we will start adding the content. So I will put there a div. For this diff, I will set a relative class with index to ten, peaks to four, and height to 220 pixels. Then inside, we will add a motion div. I'm not adding animation container that we use because I will add a bit different properties and I don't want to update the component just for this specific case. I will just use motion div there. For class names, I will add absolute position, left to 50%, top to 50%, and translate X by 50% and translate Y by 50%. Then we will set the animate. Rotate by 360 degrees, transition with duration to 90, repeat to infinity is linear, and that will be it. Now we will map over our thumbnails. I will put the thumbnail one thumb nail two, thumbnail three, thumbnail four. And like this for all the thumbnails, there I will do map, and I will put there thumbnail and index. So thumbnail will be the name of the item in the array and index the position. And inside, I will start with the variable for angle where I will divide index by four, multiply by two, and by math dot BI. By this, we will spread the thumbnails evenly in a circle. Then variable for radius, I will say there are 750 and then return where I will return a dif. For this div, I will set a key that will be index. I will set a class name that will be absolute, and I will set the style, and that will be transform to translate -50% and -50%, rotate where we will again multiply angle by 90, divide by Mv dot PI, and we need to put our degrees. We can also close this like this and also after we need to put a translate, where we will again use these radios and pixels and we can continue inside where we will create another div and this div will hold an image. And this image will have the source of a thumbnail of thumbnail, and the class name of width to full height to fool object to cover opacity 2.9, and that will be it. For the styling of this div, we will put there a relative class with 480 pixels. We will group it. Now we can already see there. The thing we need to do is to put there rotate 90, and that's basically it. Now we can decrease the width, maybe even more. 340 pixels. And we can also decrease the radius. Let's use 650. Now we need to move this a bit down, but before we do it, let's also add some text to this section, and this text will be below this motion div. And there actually, we need to update this a bit. Let's say we can leave it like this, but there we will create the div where we will set absolute position top -50%, left zero wi full heights to 1,500 pixels and x auto now let's take the div and wrap this wall motion div. Now format it a bit. Yes, that's how it should be now. So you will see in our section, we have the thumbnails. And the last thing we will do there is that below these two divs, we will add a new one. Inside, we will add Heading two, test your thumbnails. And below, paragraph, experience your thumbnails in a dynamic review environment before going before going live. Now, text center to styling. For heading two, we will at text five Excel, font, volt. And actually, I didn't do Excel there. We can make it more responsive. So let's start with this for medium screen. Otherwise, let's do the text three Excel and text for Excel for small screen. For the paragraph, we will use the class names with text large, text muted foreground, maximum width to Excel and mix auto, maybe even large. Yes. And also, let's put there space Y two. This should be fine. There we will input the images of the thumbnails we want to show, and then it will create this rotating animation. Let's open footer. There we will export function footer with the return. Put it onto our page. For the Futer, we will first import link, and we will also import the animation container. Now in Putter itself, we will do the Putter tag and there the classes we will add will be margin bottom, relative border to top and border to border with 0.4 opacity. Padding top, we will set to 16, betting bottom to eight. On medium screen, we can reset it and horizontal padding to six. On large screen, we can increase it to eight. We can set it to full, and we will use background gradient bottom from transparent to background with 0.8 opacity and backdrop blur small. Now inside, we will create a di for this div, we will put maximum weight of seven Excel with Amex auto then for another div, we will create, we will put a grid layout with Gap 212, Excel and above, we will set grid columns to three and also gap to eight. Then inside, we will do animation container with Dla 2.1. And inside, we will put a span with Tumbernail reviewer. There we will put the styling of text Excel, font bolt and below this animation container, we can continue with a di to this day, we will set the grid layout with grid columns two, gap eight, and on Excel and above, we will set coal span to two. This means this will take specific columns on Excel screen size and above. Then inside, we will create a div. In this day, we will create animation containers, so we can do the first one with also a second one and there we will set medium screen above, grid layout with grid goals two on medium screen above, and also some gap. For the container, we will set a delay 2.2, and the content will be heading three with previewer then an ordered list with list item, link that we had to use two specific section, for example, steps. For Link, we should also have HRF and the class name that can be on Hard text, primary, transition, colors, and duration 200. Now we can copy this list item, paste it below, and instead of steps, we will put their pricing. For the nard list, we will put their margin from top four space y three, text small and text muted for ground. Now we have it there, and next thing what we will do is that now we will offset sling for the previewer, which will be text small, phone semibolt and text foreground. And we will basically copy this animation container, put it instead of the second one. There we can increase the delay to 0.3. We will change the previewer to socials, steps to Facebook and pricing to Instagram. Then we will take this Valdiv and we will paste it right below, so we will create additional two lines. Let's put there 0.4 and 0.5 as a delay. And also, let's put there instead of previewer contact, instead of steps support and delete this pricing so it can be like this. And for the last, we can put about us, and there something like privacy policy and terms and conditions. Now, let's save it and check it on the page. Let's see if everything is right. We have the introsection with the steps. We have the demo, animation where we are showing the demo of our application. Frequently asked questions with this interactive section, pricing, call to action and the footer. Now, of course, we also want to test the responsiveness. Now, the only issue that is creating the blank spaces around our page on a mobile screen is this demo section. So we need to go into VS code, and we need to fix it there. Let's put it there into this demo component in this motion div that is wrapping the image. With two fixed 300 pixels, and mix auto and on medium screen, we will set With two full. Let's scroll through the page and see how it looks like. M 20. Landing Page - New Navbar, Updates: And now we will also create a better Navbar, not a placeholder one we had on the start, but still it's good. You can keep it. If you don't want to do this upgraded version with me, the functionality will be the same. First, in the Navbar component, we will use client, and then we will import a few things. We will start with the link from next link. Then importing the mode toggle from Team Toggle. Then we will import signed in from Clark, also signed out sign in button, signo button, and use user. Then we will import use State and also we will import menu from the Lucid React and X. Also, we will import animation container. Then we will do export const Navbar. There we will create a variable as signed in. And we will use use user. For this use user, it will basically check if we have a user from Clark. But if you don't have clerk yet or if you're just doing the front end, you can do there just True. But then you need to delete this curly braces. We can do it now like this together. So hardcore the true value, and that's it. Then it will work like, yes, the user is signed in, and it's also prepared for your future implementation of sum of. Then we'll create a constant with a state variable, so it's open set is open. Defaultly well seduce state to falls. Then we'll create a function, Toggle menu, and there will set is open to the different value to the opposite value, I mean. Below, we can do the return, and there we can do Nap tech. Inside the Naftac we will put the classes of BG background and relative, and that index to 50. Inside, we'll create the for this div, we will put a maximum weight of seven Excel, Mx Auto, and sparing to four. Inside this div, we will put a div that will have a classes of flexbox layout justify between, we have even spacing between the elements, items to center, height to 16 and relative class. Inside, we will do the animation container with delay 0.1. There we will do link with HF to the desired path and classes of Bedding two and one medium. We will put there the name of the company. I will put there SAS. Now for the mobile menu button, we will create a div inside animation container with delay 2.2. And inside the button where we will check is open, in case, yes, we will display the icon with height six and width six. In case now, we will display the menu icon with height six, and we will also set some attributes to this button or there we will set on click to call the Toggle menu function, we created above. Then for the classes, we will set Bedding to two, and then for the label, we will set Toggle menu. Now we can move below. Below, we will create desktop navigation. There we will set hidden on mobile screen or medium screen, we'll display it. Flexbox layout items to center and SpaceX to four to have some horizontal spacing, then animation container with delay 2.3. And there we will check, is signed in. In cases, we will return these two lenksPduct and also profile. There will be HRF of the desired path and the class name of Bedding two font medium. Basically, we can copy paste this there. And in case he is not signed in, we will display now. Below, we will create a link that we can just copy from there and put it there and this will be pricing. That will be displayed every time user doesn't need to sign in for this. And we can move below this animation container, create another animation container with a delay 0.4. And inside, we will create a div with classes of space X four, flex, and items to center. And there will be the mode toggle. There will be from Clark signed out in case he is sign out, which clerk will check for us, he will see sign in button. In case he is signed in, which again, clerk will check for us. He will see sign out button. This saved us some lines of code because now we don't need to check if he's signing or sign out to show this button. We are checking the theoretically. But yeah, you have basically there are two options how you can do it. W is signed in, where you will check it there, and then in case yes or no, you will show this or with the text sign out or sign in, where you will then display the content inside. So it's true that we could tally get rid of this and put this text, signed in and then put there these links. But I believe there are these two options, how you can do this via this condition or via the clerk text if you want to use clerk for authentication. And there we will create a div that will be for the mobile navigation, and there we'll put on medium screen hidden, fixed, inset zero, that Index 40, and we will check is open with turning operator. In case it is open, so the value is true, we will do nothing. In case the value is false, we will do pointer events, none. So there are no so there are no pointer events. Then inside this div, we'll create another one. But just above this diff, we will create a dip that will just hold the class. And in this class, what we will do is that we will set the absolute position with inside zero, background to background with 0.8 opacity, backdrop blur to small, transition opacity, duration 300, and we will set there is open. In case, yes, set opacity 100. In case no set opacity to zero. Like this. This is empty div, so just close it on the end of the line. So there we will set absolute position, top 16, left 16, right to zero, Background to background, border to bottom, border to border with 0.4 opacity, shadow to large. And for animations transitional, duration 300 is in out. We are still not finished with this class. Let's continue. There we will do the dollar sign, and insight we will do, again, the Turner operator check. In case it's open, we will execute translate Y zero and opacity to 100. Fourth, we will do translate Y, full and opacity zero, so it gets away from the screen. Inside this div, we will call the animation container with D 0.2. There we will do a div with peaks four, PT, two, being bottom three, space Y one. And inside, we will check is signed in. And in CS, we will again show these two links we have there so we can basically copy this condition like this. And below the pricing link, which we can also copy. Then below, we are not done yet. We should also copy this. So basically the wall content of this animation container, we had there on the desktop. Let's use there also some bedding from top. And now I see we have there the icon. So let's go to the animation icon. There we need to set medium screen and above hidden and that index 250. And I will now open the menu navigation and we can see there this should be styled a bit. This should be styled differently. So there we are missing flex and flex direction column and also left zero, not 16. And there we will need to add HRFs. So let's do dashboard. For profile, we will do dashboard profile. Pricing is just pricing. And the same things here, dashboard dashboard with profile and pricing. Let's go to the global dot CSS and make the gradient text a bit more shiny. I would put something like this, then something like this and something like this. Also, I would go to the hero and I think three easy steps there gradients text, maybe decrease the opacity 2.9. And last but not least, we will create a button glowing effect. Let's go to our ID, and in our ID, we will open button glowing effect. There we will start and it won't be that long we will just import a link. We will import an icon, Chevron, right. And we will create an interface there for button glowing props, where we will need to define the text that should be as a string, and we should have the text every time, of course, because there should be something on our button and HRF, that is not mandatory, but would be a string if there is any. Then we will create export default function, button glowing, where we will take the text and HF as a pro button growing props. And we will do return there inside this function. What we will do there is a div. Inside this div, we will add a padding to eight item actually flex box layout and then items to center with ify center to center it horizontally and vertically. Inside this div, we will create the link for the link, we will set the HF to HF and some class names. We will group it, we will make it relative in line flex, items to center with Gap two, rounded full, background, black, horizontal padding to four, vertical padding to two, text small, text white, transition to all and on our background white let me put it on another line so you can see on our background white with 0.05 opacity. Now let's say the Spen tech. This Spenteg will be actually empty, will hold only the class name. For the class name it will hold absolute position in set zero rounded full, then background gradient to right from this color code that I have there. So it's FFE 56 via another color code, which is FF 00 FF and two last color code, which is 00 and four times F now let's set there also some opacity. We will set there opacity to 70, blur to small, transition to all, and also on a group however, we will make opacity 100. Let's go to our hero section. And in our hero section, there above the terminal previewer, we will call the button glowing as a prop, we will input there the text, starting price available 30% of with HRF that won't fill, and now we will have it on our page. Of course, we still need to add the styling. So let's go to button glowing effect, and let's finish there there below the Spentec I will put another one. Also without any content, just put there class name with absolute position in set 05 then round it full and background to black. Below, I will put a Spentec, but now it will have a content. It will also have a classes of relative flex items to center, Gap two, and font medium. Inside, it will show the text prop, and also next to the text, it will show the icon Chevron right. And for the class names, it will have size four, transition transform then group Her with translate X 0.5. Now we can go to our page and we have there the button. You can see how it's working on Her and we can also check it for the responsiveness. There we have it. We need to update the tonomble screen, and let's put there text to center. Also, I see in the hero section, we need to fix this heading. We can just do there. Text to center is that there we will set maximum weight to Excel, have it already there. So let's set there from a medium screen or from Excel. Otherwise, maximum weight, let's set too large, maybe even less. Yeah, we can leave it on a small and there we will change it to Excel. Then it will look like this on mobile or smaller screen devices. 21. Profile Page: Can move on and do the profile page. And during the profile, we will set our channel name, and the channel name will be automatically populated there. And it will be saved there for our user. So once they will set their channel name in the profile tab, they will have it there already when they will log into the application and we want to use it. So they will be just filling the title, and then of course, the thumbnail. Let's now go to the Schema dot prisma and there we will add a new value. We can do it there below the name. Let's do it like channel name. It will be string and optional. Now I will save it. I will do NPxPrisma DB push. Um, that will push it to my database. Now in my table, I also have this channel name and I can work with it, and then I will go to the profile page and we can start coding there. We will start with few imports there, first Prisma from our lip DB, then off and current user from Clark next J server, redirect and revalidate path. Then we will start with defining an asynchronous function to fetch the user data from the database. Let's do asynchronous function, get the data user ID as a string. And inside, we can start. First, we will query the database for a user with a given user ID. Let's save it into the user variable. There we will await Prisma dot user find Unique there where the ID is in user ID, and we will be selecting the channel name because that's what we want, so we are able to actually set it. And we will return user dot channel name in case it's not found, we will return empty string. We can continue with defining the main profile page component also as an asynchronous function. So export default async function profile page. And first, we will get the authentication session. So user ID from off, which we will be using from Clerk Library, and we will retrieve the authenticated users information and save it into the user variable, so we will await current user. That is also from the clerk library. Then we will check if the user is authenticated. We will be checking if user ID or user is not true, we will redirect to a sign in page. Then we can continue with fetching the user data from the database and we will save it into the channel name. We will await. Now we will call the function we created earlier there, get data and the parameter we will send there will be the user ID, which we are getting there from the clerk. This will then get the user ID. Query the database and return channel name of this user ID, and we'll save into this channel name variable. Now, you will define an asynchronous function to handle the form submission that means when the user will want to update this channel name. So let's do asynchronous function, post data. We will start with marking this function as a server action with use server. That means that this function will run on the server side only, and it will allow direct database access. Then we will get the channel name from the form submission, and we will save it into the variable channel name. So form data dot G channel name. If you are curious about this, form data, basically, that's the input user will fill into the textbox of the form. We will go in a second. Then we'll update the user's channel name in the database. So we will do their await Prisma dot user dot update, and we will be updating where the ID is user ID is string. And data will be the channel name set to channel name Oops, a string. And after this is done, we will revalidate path on dashboard with slash there. Nice. We now have also post data function. That means we now just need to return the TSX for rendering the profile page. So we will create the return. The we'll create there we will start with the Ditech. For this dftech, we will start setting the maximum width to Excel, and mix order to center it, PY and Px 24 to add some bedding. Also, important step we need to do is that we will go to the profile page. So in our navigation, click there the profile page. Site cannot be reached. Let me see why. Yeah, because I need to do NPM run Depth first as I somehow closed it, there you can see nothing is there, but soon this will be changed. So let's continue in the coding. The next thing that we will do is to add some page title. So I will do heading one with profile, and I will set there classes of text for Excel. Font extra bolt, tracking tight, and on large, I will increase the text size to five Excel, let's say, I will some margin to bottom. We can do six. Then I will continue with a div that will be there as a card container for the form. Into this div, I will put a form itself. First, let's put there some classes. Let's do round it large border, background to card, text to card, foreground, and shadow small and some padding. Something is already happening on our profile page. Let's continue there with the form. And for this form, the action will be post data. Then we will create a div there. We will set there space Y four. Inside, we can create another div, set there space Y two. In this div, we will create a label. To this label, we will add first that it's HTML four to tie it to the channel name. Below we will do the input. Let's put there the label itself, channel name, and now we need to do the classes. For the classes, we will do text small, font, medium, leading, none, and I think that's it. Below we will do the input. We can actually close it there, and attributes we will add will be type of text, then ID to channel name then name to channel name. Then on the default value, that will be the channel name in case user will already save this once. He will have it there for next time, and when he will want to change, it will still be there. Then we will set the class names. Let's do the flexbox layout, height to ten, width too full, round it too large, border input, BG background. Then some PX and PY, what else? Text too small, and now below this, DIV but still above this one. Let's check it. We have one div that holds label and input and the second div that will hold this label with input, and there we will hold also something like submit button. We don't have the submit button yet, but we will fix it now. So let's open the file exxplorer. There we will go into components. We will create a new file. We will call it submit button. And in the submit button, we can start creating the submit button that we will use on our profile page. First, we will define there it's a client component, then we will import the use form status from react doom. Then we will import the button. We have there from Chet CN, and we will import loader to from lucid react. We'll start with export function submit button, and inside, we will create a new constant pending, and we will use form status on it. So if this form will be pending, we'll be using this variable. Now let's do the return inside this button. We will check the pending variable. In case it's true, we will execute this position. In case it's false, we will execute this position that will be just submit. But in case it's true and the form is really pending, we will do the load there too. With classes of height four with four, then animate spin and margin to write two. Below, we will put updating. Then we will go to our profile page. We will start typing their submit button. We will import it. It will now get to our page. You can now see we have it also on the layout. Let's now test it. Let's put there testing channel name, I submit. You can see it's updating. The field was really saved. Testing channel name. 22. Displaying Channel Name on Dashboard: And what we need to do is to go to a dashboard page, Abashboard page Tsix. And there we will now send this channel name we have in our database to this prop channel name saved. So we need to first get it on this page, and then we will send it there. Let's start about the dashboard function, and there we will do asynchronous function. Get channel name, where we will send the user ID as a string, and there we will save into the user weight Prisma dot user dot Find Unique, where the ID will be user ID, and we will select the channel name and we will return the channel name in case it's there, otherwise, ampithe string. Now we have the function, get channel name, and we will scroll there, and above the return, we will create a variable channel name, and we will evade the get channel name function where we will send the user ID, we are getting there. Now we can take this channel name and send it as a prop there. Now we can test it. Let's go to our page. Let's first go to the product. There you can see the channel name. Let's go to profile. Let's change this. I will click Submit. Now I will go back to product, and you can see it's there. Let's change this, which I now just changed. So then I will fill there just some test video. I will put there the thumbnail and is working even with the channel name. So this is it also for the profile page. Now it's time to test our website. We will try to sign up. Then I will continue with Google. After we sign in, we can see that we are not subscribed yet, but also new items in our Navbar. These are for the product itself, pricing and also profile where we will set the channel name that we will use in the product. Let's click on subscribe. There we will fill in the data and we will get onto payment successful page, and there we have our product because now we are subscribed to the application. There you can see we can set the title for the video card, then the tabine itself, and the channel name. For the channel name, we will actually go to profile and as we will now be using this, we will set there our channel, something like this. I will submit it. Now I will go back to product, and there you can see I have it prefilled, and every time I will log into the application, I will have it there. Now that's the previewer itself. I will put there thumbnail for the title. I will also put there something, and then I can see the video card with the thumbnail. Now I can randomize the order, and also I can change this to tablet view or mobile view. And if you would like to manage the subscription, we have the button that will redirect us to Stripe where we can just simply manage it. And that will be it. Simple functionality for microsaS with one feature to test out the product. And of course, if it's successful, there can be more and more features added. 23. Deployment: Thing is ready, and we can go that last step, and that will be the deployment to Arsl. First thing, what we will do is that we will open a Git Ignore and make sure we have there and file because we definitely don't want to upload to get any of our environment variables. Then you can also check package dot JSON and make sure that in scripts, you have this set for your death build and start. Now we need to publish our project to Get up, so we will publish to GU. Now on Git up, we can see everything got published and pushed in case from now on, you do any changes, for example, there, you will then just stage it in your source control. There you will put a commit message update off. Git Ignore, for example, you will commit it, and then it will get to Git up. And after we will connect it with Versal, it will get also automatically there because Versal will automatically run the deployment round for you and will deploy it to the live there onvrslot com. You will choose how you want to log in. I will continue with Git AP. And there on this dashboard, I will click on a new project, and I will set the one I pushed to Git up. It will be this one. I will click on Import. And there now you need to set all the environment variables, where you put the key, which will be the name of the variable and value, which will be its value. And you will go into your file and from there, you will take these values. You will put it there, you will click on Add More and all the values from the clerk to stripe and so on, you will put there. I put there all my environment variables, and there is the last one next public URL. And this one we will fill with value after we will deploy it with the domain name we will get from Versal. Now I will click on Deploy. And I will wait until the build will be done. Now you can see it during the deployment. So let's wait a bit. We can see that we have error defined but never used in Stripe route Ts. Let's go to VS code. That means in VS code, we will go to Stripe route and we will check for the error that is defined but never used. We will just at the use of the error, so we will put console dot error. We will put there some message. Webhook signature verification failed, and we will put there the error. Next error is with use team there we will just delete the import. Then the button and link in page TS six. Again, we will delete the imports. Now the next error was in animation container, so I will again open the VS code, and there I will import also animation props. We had there the type of ANA for transition, exit initial and animate. Instead of the type of ANA, we will put the animation props, and for animate, we will do animation props for initial initial for exit exit, and for transition transition. For the other errors, we will go into input first, and there we will just redefine this and we will put there type of input probes to react, and there we can copy paste this input HTML attributes, and we can delete the input probes before this. So t's delete it there, save it, and we can move to text area. And in text area, we will do similar thing. We will put there type text area probes it goes react dot Tex area HTML attributes, and we will delete the one before, leave there just this one, and that will be it. Now for fixing the other issues, you will create a file called nexdot config dotgs and put there this code. Also, we can remove the dot js. So in this one, we will set the next config. Next file we will create is versal dot JSON. And in VrsalJSN, we will put built command and install command and set there these commands. For the first one, Prisma generate and next built, and for the second one NPM install. Then we will go into package dot JSON, and there below the Lind in script, we will also add post Install and set there Prisma generate. And what we'll do also is that in package JSON, instead of that build command, you will put there for build this command, Prisma generate and next build. After you have all these changes, you will go into source control. You will stage them all, put there some message, and commit it. Then you will go to Versal and you don't even need to start the new deployment. You just click on your project, click there on Deployments, and there the new build should start. If not, just repeat the process deploy again or find the button for redeploy. Everything should be fine or at least with my code and changes I shown you, everything was working for me. What we will do is that we will take this domain and we will go into our project. They're into settings. They're into environment variables. I will just click there on the new variable, and I will put there the value of the domain that I copied and you also need to put there HDDPS Next public URL was the name, I believe. Now we will click on Save it got edited and just a small heads up, make sure database URL and direct URL are without the quotes on the beginning and on the end and it's just pasted like this. In our project, we will go to settings. There we will go to deployment protection, and we will turn this off. Now we will save it. When setting the endpoint in clerk, we also need to do their API webhooks clerk and save it like this. And also, right after you deployed, make sure you are testing this with the user that is not in both clerk or Superbse Just with a brand new Google account, for example, that you don't have neither of them to test this properly. Now, we will test also the stripe, so I will do stripe login. And there I will need to put the domain with API webhooks, stripe. And now on the pricing page, when we are trying to subscribe, we got an error, and that's because we have some issues with this success and Cancel URL. Let's actually go to lip slash ScripTs and at there these new changes. Check there for the domain URL, and at there equals true at the end of the success and Cancel URL and also metadata customer ID. Then in app pricing page, you will create this new variable for domain URL. Then we will check for the domain URL. In case it's missing, we will throw an error and also instead of this domain URL that was there in the subscription URL for Stripe, we will set domain URL to just domain URL now that we set there. With these two changes in app pricing page dotix and also in stripe dot Ts, there you can see it in the actual repo by the way, we will go to pricing page DTAix and there are the other changes, and there we are setting the domain URL. Now we will make sure that you commit all changes and push them to your repository. Then you will wait there for the deployment, and now we are ready to test even the stripe. I will click on Subscribe. There, I will fill the information. And after successful payment, we can see we are now subscribed and we can use the application. And we have our subscription active in SUPAbase. And from my side, that's it for the tutorial.