This tutorial demonstrates how to build a full-stack Software as a Service (SaaS) AI platform, integrating multiple AI tools, user authentication, subscription management, and customer support.
Mind Map
Click to expand
Click to explore the full interactive mind map • Zoom, pan, and navigate
hey there my name is Antonio and welcome
to the newest video on my channel in
this tutorial I'm going to teach you how
to build a full stack software as a
service AI platform and you're going to
learn how to build not just one but five
different AI tools so let's go ahead and
let me show you exactly what this
amazing application is capable of let's
start with the image generation I think
that's one of the coolest AI models in
here for example a horse
in Swiss Alps and I can select the
amount of photos I want to generate
let's pick four photos in the lowest
resolution so they load fastest we have
a prompt that genius the name of our app
is thinking and after a couple of
seconds you're going to see what amazing
images this AI will come up with look at
this absolutely amazing now let's do the
same thing but for video generation
right here I'm gonna write the clown
fish swimming around a coral reef and
I'm going to click generate again and
after a couple of seconds you're gonna
see what this AI will come up with
look at this absolutely amazing let's
play the video to see what it looks like
can you believe an AI has generated this
absolutely amazing now let's check out
the conversation model right here but
before I write anything here I just want
to quickly bring your attention to my
lower left corner right here where it
says that I've used them two out of five
of my three generations so what does
that mean well let me remind you this is
not going to be your average AI tutorial
we are going to build a full stack
production ready software as a service
platform meaning that I'm going to teach
you how to create a free tier as well as
a monthly subscription tier using stripe
for your users so let's go ahead and
let's use up this the rest of these
models right here so we can fill up
these three generations I'm gonna ask
the conversation model what is the
radius of the sun right here we have a
similar thinking prompt right here and
there we go look at the answer amazing
and look at this now it says 3 out of 5
five free Generations because we just
used one great now let's go ahead and
let's fill this up to 5 out of 5 so I
can show you what happens then I'm gonna
test the music Generation Now for
example piano solo right here I'm gonna
press enter and after a couple of
seconds you're gonna see that this AI
model can actually come up with audio files
files
look at this absolutely amazing you can
play it you can change the volume you
can download the file change the
playback speed amazing I'm not gonna
play it just in case someone decides to
copyright AI music in the future and now
let's take a look at the last Model
right here which is code generation I'm
gonna go ahead and write a model using
react Hooks and Tailwind I'm going to
press enter and after a couple of
seconds you're gonna see that this AI
model is capable of writing code for you
look at this not only did it give you a
nice explanation it also wrote the code
in markdown so it's nice and easy to
read absolutely amazing but what happens
now that we've used up 5 out of 5 of our
three generations but let's go ahead and
let's try to generate another image for
example I'm gonna write a shark in DC
and I'm going to press generate and look
at this it's blocking us from using the
AI That's because you're going to learn
how to build this we are going to
protect our free tier so the users who
are not subscribed can only use the AI
model five times after that they have to
upgrade so I'm gonna click upgrade right
here and that is going to redirect us to
the stripe checkout page right here I'm
going to write a fake credit card number
some more fake information I'm going to
write my name right here and I'm going
to click checkout and in a couple of
seconds we're going to get redirected to
the settings page
there we go look at this absolutely
amazing now in our settings it says that
we are currently on a Pro Plan and we
can of course manage our subscription
from here if we want to cancel it so
let's go ahead and test how that looks
right here again this time it's not
going to redirect us to the checkout
page but to the billing page so I can
see all of my information I can see how
long this lasts how much I've paid and I
can of course cancel my plan but now I'm
gonna go back and I'm gonna test if this
subscription actually works let's go
ahead and let's go into an image
generation and write I don't know a
pretty sunset now let's go ahead and
generate five photos right now we have a
similar prompt that genius is thinking
and you can already see this time we are
not blocked by the premium model prompt
instead it successfully generated a
pretty sunset beautiful let's try the
conversation again what is the radius of
the Earth
there we go we are not blocked again so
our subscription model is actually
working perfect and what would a
software as a service be without
customer support in this tutorial I'm
also going to teach you how to build
beautiful customer support using crisp
you can go ahead and write any problem
you have
just like this and that is going to
appear on the crisp dashboard in real
time so you can respond back to your
customers and we are also going to have
authentication this time using clerk
which I am extremely excited to say is
this video's sponsor and also my first
sponsor ever but that is not all because
every software as a service also needs a
beautiful landing page so I'm gonna
teach you how to create this as well so
without further Ado let's get started
so let's get started and let's set up
our application I'm going to follow the
chat cnui setup instructions you can
find those by Googling chat cnui
clicking on the website right here and
just go ahead into the documentation and
click installation after that you have
to select next JS or whatever you are
using but in this tutorial we're going
to be using next.js so that's why I have
this opened right here so the First
Command we have to run is the create
next app command this command is
actually not related to chat cnui this
is the next 13 command but it is written
in this tutorial because this is a setup
for next JS so here on the left side I
have my visual studio code and I'm going
to go ahead and I'm going to open my
terminal and I'm going to go ahead and
write npx create next app at latest and
I'm going to name this AI Dash SAS you
can name it whatever you want and go
ahead and give it the follow with x dash
dash typescript
dash dash tailwind and dash dash s lint
like that or you can simply press copy
here and select npm but I'm going to
write it out so you can clearly see what
I'm doing and now we can go ahead and
press enter and I got a prompt that I
need to install the newer version of
next app so go ahead and just press yes
if this is the prompt you have there's a
chance you just don't get that prompt at
all and you immediately have this
question right here so the first thing
it's asking us is whether we want to use
the source directory for that select no
for the app router this is very
important you have to select yes
for the import areas you can select no
that is going to keep the default at
sign and there we go now it's starting
to install our application so just wait
a couple of seconds and you will have
your app ready
after a couple of seconds you're gonna
get a message similar to this saying
success and that it has created a
project called AI Dash SAS or whatever
you named it in your command at this
following location so I'm going to click
open right here and I'm going to select
AI SAS right here and there we go now
I'm inside of that folder but before I
start this application I want to run the
rest of the commands followed by the
chatsea and instructions because chat CN
is the library we are going to use for
styling so let's go ahead and let's open
the terminal again right here
and I just have to quickly update this
so I'm going to pause the video
all right now I have to run the
following command npx chat cn-ui at
latest in it so let's go ahead and run
that npx shadesian Dash UI at latest in
it like this and now we're gonna get a
set of questions so would you like to
use typescript for that we select yes
because we initialize our next 13
project with typescript now it it's
asking us for the style I'm going to use
the default style and I highly recommend
you do the same you can choose New York
if you want so use arrow keys up and
down to select the option if you select
New York it can look slightly different
you can still follow the tutorial but
your icons are going to come from a
different package than that what I will
be using in the tutorial so if you don't
want that confusion just choose default
and press enter now for the base color
you can select any color you want it
doesn't really matter it won't affect
the project but it will look a little
bit different than mine so for mine I'm
going to choose slate like this is is
asking us where are Global CSS file is
and this is the correct answer app slash
Global CSS now would you like to use the
CSS variables for colors select yes as
well it's asking us where is our
Tailwind config it's at the root folder
named exactly like this so press enter
for that and configure the import Alias
for components this looks fine I want it
to look like that and you can press
enter for this as well and lastly it's
asking us whether we are using server
components since we are using the app
router the answer for that is yes and
now it's asking us to confirm all of
those options so we pretty much didn't
change absolutely anything you can just
press enter through all of these options
and now just press Y and now it's going
to initialize chat cnui inside of your
project there we go just like that it
has added uh chat cnui and now we can go
ahead and run npm run Dev and your
project is running on localhost 3000 so
I'm going to click on this link right
here and I'm going to show you how your
project looks so I'm going to expand the
screen and you should see something like
this so now let's go ahead and let's
quickly clean up our application because
there is a lot of stuff inside of here
that we don't actually need so I'm going
to collapse everything and as you can
see we have the app folder where all
most of our routes I mean all of our
routes are going to be we have the
components which are currently empty but
this is where the components from chat
CN are going to appear we'll have the
lib folder which was generated by chat
CN UI and we're going to use this to
merge Tailwind classes I'm going to
explain that when we come to that part
and the rest is just the configuration
for the project so let's go inside of
the app folder and let's take a look at
what we have here so we have two
important files page and layout.dsx our
layout.tsx can stay pretty much the same
for now we can change that later but now
in page.dsx what I want to do is I want
to clean everything inside of the return
function so go ahead and go to the top
all the way to the bottom and just clean
everything in side and you can also
remove this import and you can just
write a paragraph hello AI SAS like that
and there we go look at this it's right
here hello AI says but the font looks
kind of small let's see if we can
increase it using Tailwind go ahead and
text-6l like this there we go now the
text is much much larger and let's try
and change the color text green Dash 500
there we go so our Tailwind is
successfully set up before we move on to
the next part I want to show you how
easy it is to add components from chat
CN to our project so I'm going to go
back in here I'm going to zoom out a
little bit and I'm going to go all the
way down to the components in the
sidebar and one of the components we are
certainly going to need is the button
component and right here is the command
we have to use to edit but one cool
thing about chat cnui is that you can
also manually add it if you want to so
you don't have to use the CLI why am I
choosing chat CN and why not chakra or
material UI kit or all of these other
amazing CSS Frameworks well the reason
I'm using chat cnui is because it works
in a different way chat cnui is not a
component Library instead it is just a a
I don't know exactly what is the correct
phrase for that but what it allows us to
do is to keep the components inside of
our components folder usually when we
use material UI or chakra we have no
access to the components we can import
them and we can edit them using the
props they've given us but we have no
access to the actual code that there
that the way those components are
working they are in node modules but
with chat cnui they're going to be
directly in our components folder so we
can modify them in any way we want so
let's test this out I'm going to go
ahead and click copy here so I advise
you that every time I am on the chat
cnui page I advise you to do the same
because there are some parts that we
cannot install as easily as this but
we're gonna have to copy a code snippet
so I just want you to be on the same
page as I am so it's easier for you to
follow this tutorial so I'm going to
copy this npm Command right here and I'm
going to go into my terminal right here
you don't have to shut it down but I
will because I'm using only one terminal
and I'm just going to expand this a
little bit and I'm going to paste this
command so the command is npx chat cn-ui
at latest add button and I'm going to
press enter like this and now it's
asking us whether we are ready to
install that so just press Y and there
we go it's installing the button inside
of our project I'm going to run MTM run
Dev again and let's see if we can
actually use this button now so what has
happened in our project if I refresh
right here not much has changed we still
have the hello AI SAS but let's take a
look at our components folder right here
you can see that now we have a new
folder inside called UI and inside of
that folder we have a button.tsx and now
if you look inside you can see that we
have this amazingly uh strictly typed
written and area of written button
component so this is a much more
advanced button than what would usually
be if we were writing it ourselves and I
think that's absolutely amazing and
what's cool about it is that you can
rename absolutely anything you want
inside so whatever you don't like you
can rename so you have complete
ownership of your component system
that's why I really like chat cnui so we
have just added this button and
technically we never have to look at it
again you can just close this all
together and let's go back into our home
right here and I'm going to replace this
and I'm actually going to use that
button so I'm going to write button like
this and I'm going to import it from add
slash components slash UI slash button
like this and make sure you destructure
it like that and I'm going to write
click me like this and I'm just going to
increase my zoom a little bit so you can
see better there we go look at the
button right here and let's see how easy
it is to change the variant for example
I can go ahead and say destructive like
this there we go now it's red and we can
use that for when we are deleting some
stuff and I just want to show you how
cool it is for example you can go back
into components UI button and this is
the destructive style that you're using
right now let's say you don't like the
word destructive you can go ahead and
change that to Danger so you don't have
to do this I'm just demonstrating now
you can change that and you can see now
our code is not working and you can see
I have a typescript error here so I can
change it to Danger right here and there
we go now it works so that's what this
component Library well it's not a
component library but that's what chat
cnui offers us I think it's really cool
that we have this kind of customer
custom ability here so just make sure
you bring this back to destructive I'm
not going to change the button component
in any way but I'm just going to bring
this back so destructive
like that and I just want to show you
that you also have a couple of other
props like size so you can change the
size to large for example and now the
button is a little bit larger like that
great so this is how we are going to add
components in our project and then we're
going to style them and we're slowly
going to create our UI great start you
did an amazing job and now we are ready
to go ahead and start developing uh some
other stuff
let's continue with the structure of our
project so I'm going to go back inside
of my app folder and I'm gonna go inside
globals.css right here so everything
that you see right here has actually
been generated using chat CN UI but this
is fine I just want to add one thing
here and that is the height for our HTML
and our body so let's go ahead and write
this HTML comma body and root element
like this and I just want to write
height 100 and that's not going to
change anything right now but it is
going to help us in the future great and
now I want to go back inside of my
layout.tsx file right here and I want to
change the title of my application to
genius and I want to change the
description to AI platform like this but
with the capital AI like this and now
you can see that my title right here has
changed to genius previously it was was
let's see it was create next app but
after we do the changes it now says
genius great so what I want to do now is
I want to organize my routes in a
specific way but before I do that I want
to give you a quick explanation of how
routes actually work inside of next so
right here we have this page.thesx file
but how do we know that that is located
right here at the slash well that's
because if you have a page that CSX
plainly put inside of your app folder
that is going to result in the URL slash
or just your domain like this but what
happens if I create a new folder for
example called test and inside I create
a new file page.dsx I'm going to quickly
go ahead and write test page right here
and I'm going to write a div test page
like this so make sure you have the test
page and Export default fast page at the
end it's important that you use export
default now how do I find this page
where is this well it's located at slash
test in your url right here so now we
know that every folder we create inside
of the app folder which has the page.tsx
inside of it is a route on its own but
there is also a way that you can use
folders and page.tsx without actually
affecting the URL this is a cool feature
because sometimes we want to organize
our routes in folders but not
necessarily change the url structure so
for now I'm going to go ahead
and I'm going to shut down my
application because we're going to do
some changes in here so I recommend you
shut it down as well so let's go ahead
now if you refresh nothing's gonna work
but that's fine first thing I want to do
is I want to delete the test page great
and what we're going to do now is
something called route groups so right
here in my right side I have the
explanation for that so route groups are
is especially named folder which does
not affect the URL so you can go ahead
and read more about that just type in
route groups next JS and you're going to
find this exact documentation you can
see the convention the convention is to
write the folder inside of parenthesis
that way it's not going to be affecting
the URL so you can see that right here
they have a folder called marketing but
the URL is just slash about nowhere in
this URL do you see the marketing that's
because they are just using it to
structure your files and it's exactly
okay what I want to do as well so what
I'm going to do I'm going to go back
inside of my app folder right here and
I'm going to go ahead and I'm going to
create a new folder called dashboard
like that and inside of that dashboard
well I made a mistake here right now
this is affecting the URL so we have to
rename this right click go ahead and
rename this and make sure you add
parentheses around the dashboard like
that now it's not affecting the URL so
what I want to do now is go ahead and
create another route group inside called
routes like this what this is going to
hold is all of the routes for our AIS so
inside we're going to have a route for
image Generation video generation our
general dashboard code generation and
settings so inside we can actually go
ahead and write the route which is going
to affect the URL this route is going to
be called dashboard like that so this
one won't matter for the URL neither
will the routes but this one will and
inside I'm gonna go ahead and create
page.tsx and what I'm going to do is I'm
going to go back to my old page.vsx that
is inside of the root of the app folder
so go inside of here and just copy
everything inside and paste it in this
new dashboard
page.phsx right this and you can rename
this to dashboard page like that so just
make sure you export the default you
will sometimes see me using the function
and sometimes you will see me using the
uh well this const dashboard page the
arrow function and I will export default
dashboard page it really doesn't matter
it's gonna have the same effect it's
just your preference of course there are
differences between Arrow functions and
plane functions but that is not the
topic of this tutorial but just to ease
up some confusion it doesn't really
matter what you used but you can always
follow exactly what I do so you have the
same result so for the dashboard page
I'm going to write const dashboard page
Arrow function and Export default the
dashboard page the naming of the
component does not matter for the URL
you can name it whatever you want but I
like the conversion of using the entity
name and then capital P page beautiful
and now that we have this I actually
want to remove this root page because we
don't need it so you can move that to
trash great and what happens now well we
have a problem because this is a route
slash dashboard but we don't have our
slash route we don't have the root so
let's go ahead and create that for that
I'm going to create another route group
called Landing like this that's going to
be our landing page if you remember from
the intro of this tutorial and inside go
ahead and create another
page.dsx I'm gonna go ahead and create
the landing page like this div landing
page and I'm gonna write in parenthesis
here unprotected so every user whether
they are logged in or not are going to
be able to see this landing page great
so now that we have these two let's go
ahead and let's run our project and
let's see if we made any mistakes or if
everything is working as expected so I'm
going to refresh this right here and I
am at slash test so I got a 404 so I'm
going to go back to my root and I should
see the landing page right here perfect
great so how do I see this dashboard
let's see this is not affecting the URL
routes is not affecting the URL either
but dashboard is that means that all I
have to do to visit this page I'm going
to change this now I'm going to write a
paragraph saying
dashboard page like this so in order to
visit this page all I have to do is
write slash dashboard like this there we
go now I have the dashboard page but on
the root I have the landing page and I
just want to add here protect it so only
authorized users and you can remove the
import per button We're not gonna need
it now so only users who are authorized
are gonna be able to see the dashboard
page for now of course that is not true
because we have not added authentication
so that's what we're gonna do in the
next part but for now this is great
you've done a great job so far so let me
just recap what we've done we have
removed the page.tsx inside of our app
folder and we've moved it inside of
Landing page.tsx but because Landing is
inside of parenthesis that means that we
are using the route group convention
right here you can see it's in the
parenthesis meaning it's not affecting
the euro L it's just a folder where we
decided to keep our root page for easier
structure and then in dashboard we used
a bit of a different structure so again
we used route group so it's not
affecting the URL but we did not put
page directly inside instead we created
another route group called routes that's
because besides dashboard we're going to
have many folders inside of this route
and inside of dashboard right here we're
going to have another file called layout
so this way we have structurally
separated our routes from our other
stuff don't worry if this is a bit
confusing It's Gonna Get Easier and
easier the more you work with next
now it's time to add authentication to
our project so before we start anything
what I want to do actually is shut down
our application so we don't have any hot
reloading errors so I'm gonna shut it
down and I recommend you the same great
and we're gonna add authentication using
clerk so you can either visit clerk.com
or visit the link in the description or
just use clerk elf right here and it's
the first result on Google great so go
ahead and find the sign in or sign up
button depending on whether you already
had an account so I'm going to guide you
through this process you can use GitHub
or Google or regular registration I'm
going to use Google for this one so I'm
going to pause the video a bit and register
register
there we go now you're gonna see a
screen similar to this and now it's time
to name our application so I'm going to
use AI Dash SAS for this right here and
you can play around and add as many
providers as you want but for now I'm
only going to enable Google and the
email address but feel free to enable as
many of this if you want to play around
clerk is truly amazing when it comes to
how easy it is to build with it now
let's go ahead and click create
application right here and now you can
see that we have a documentation to how
to start implementing this in our app so
right here we have dot environment.local
right here that we have to copy and put
in our environment file this file is
going to hold our secrets which clerk
library is going to use to enable
authentication in our project so go
ahead and click the copy right here go
ahead back inside of your project and I
want to create a new file instead of dot
environment.local I'm going to use Dot
environment this is because we're gonna
need dot environment for Prisma so go
ahead and just paste that inside so make
sure you have the next public clerk
publishable key and clerk secret key
basically what is written in this
documentation right here and make sure
you save your dot environment file great
and now just make sure that next JS is
selected right here and we're gonna
click continue in docs and what I love
about clerk is that they have support
for the app router that gives me
confidence that it's going to work in
this project and I already used clerk in
my last e-commerce project and if you
saw that then you know how easy it is to
implement Clerk and what amazing UI
components it offers they are
beautifully designed and they fit almost
every single project so let's continue
and let's follow this documentation and
see exactly what we have to build so
first it's telling us to install clerk
next.js so I'm going to copy that and
I'm going to go inside of my terminal
and I'm gonna install that package so
let's go ahead and write npm install ad
clerk slash next JS like this and after
a couple of seconds our package is going
to be installed
great now let's continue and follow what
the documentation is telling us to do so
it's telling us to set our environment
keys but that is something we already
done so we have them right here so we
can skip that and go to the next step
which is Mount the clerk provider and
this is what I was talking about so if
you're using Pages for any reason you
can just click pages and follow that but
we are using the app router so make sure
you're following the documentation for
the app router so what we have to do is
we have to import clerk Provider from
adclerk in xjs so I'm going to close the
terminal for now and I'm going to go
back instead of my app folder inside
layout.dsx right here because that is
the component they are looking at here
so let's go ahead and copy this line and
let's go ahead and import it right here
there we go clerk Provider from add
clerk slash next JS and what we have to
do now is we have to wrap our entire
application inside of that clerk
provider let's go ahead and write clerk
provider like this and at the end like
that and I just want to indent
everything inside beautiful and now
let's go ahead and add our middleware
file so go to your sidebar right here
I'm going to close everything again make
sure you're at the root and just create
a new file called
middleware.ts and go ahead and copy this
entire file from the documentation and
just paste it here there we go beautiful
and now what we have to do is we have to
create our sign up and our sign in page
and they have the exact steps to do that
right here so let's go ahead let's go
inside of our app folder and let's go
ahead and create a new folder I'm going
to go ahead and create another route
group here called alph like this
beautiful and inside I'm going to create
another folder called routes because
we're going to have two routes the sign
up and the sign in and I'm also going to
add a layout inside so let's go ahead
and create a new folder inside of this
route group routes and we're going to
call this
sign Dash up like that and then inside
of that we have to create another folder
go ahead and open square brackets then
again open square brackets inside so
double square brackets this is another
next 13 convention that allows a clerk
to have all the necessary routes it
needs for authentication and inside
you're going to spread using three dots
sign Dash up like that and then go ahead
and create a new file called
page.dsx there we go just like that and
then you can go ahead and copy this
example and paste it inside beautiful so
it's that simple to create a sign up
page great and we have to do the same
thing for the sign in so you can just
copy this entire folder paste it inside
routes so now you have sign Dash up and
sign Dash up copy just rename this the
dash sign in like this and inside don't
forget to rename this folder as well
like this Dash sign in beautiful go
inside of that page.thesx and you can go
ahead and copy this example and paste it
right here I'm having an error here but
that is because of my visual studio code
so I'm going to press command shift and
P and I'm going to write reload window
and I'm going to press enter so this has
refreshed my visual studio code because
sometimes cache gets in the way and
shows us errors that aren't actually
there you can see that now everything
works just fine so let me show you the
exact layout right here so I created a
new folder called out which is a route
group meaning it will not affect the URL
inside I created another folder called
routes again in parentheses so not
affecting the URL and then we have the
sign in and this sign up with a special
convention folder inside of it so it has
all the necessary routes for clerk there
we go that's how easy it was to add our
sign in and sign up pages and now what
we have to do is add some more
environment variables so clerk knows
where to redirect us after we log in or
where to go in general for sign in and
sign up so go to this section called
update your environment variables and
I'm just going to copy this right here
I'm gonna go back in my DOT environment
file and after this too I'm going to
paste this so make sure you have the
sign in url sign up URL after sign in
url and after sign up URL and one thing
I want to change immediately is that
after we log in where do we want to be
redirected let's take a look so we said
that our landing page is going to be
unprotected but our dashboard page is
going to be protected so obviously what
I want to do in my environment file is
that after user has logged in I want to
redirect to slash dashboard like that we
don't want our user to stay on the
landing page beautiful how do we know
that this is slash sign in and that this
is slash sign up and can we change it of
course we can but it has to match
exactly what you write in your out
folder so if you want to change this to
login you can do that but make sure you
change the dot dot login as well if you
want to change this to register you can
do that as well and make sure you change
that and it has to match this to
environment variables if you're
following these tutorials you don't have
to do anything like that just follow along
along
beautiful and now I'm going to show you
a really cool thing I want to go back
inside of my middleware so go inside
middleware.ts and I'm going to show you
how easy it is to add a public route so
right now all of our routes are
protected but I want to add public
routes like this and I just want to give
it a slash meaning our landing page is
now unprotected meaning that both logged
in and logged out users can visit it so
let's go ahead and let's run our
application and see how that looks right
now so I'm going to go ahead and write
npm run Dev again and I'm gonna go and
visit my localhost 3000
and I should be able to normally visit
the landing page there we go but if I go
to slash dashboard
what's going to happen is that I'm
redirected to sign in right here
beautiful so it fully Works what I want
to do now is I want to Center this so
it's uh not right here in the corner so
let's go ahead and do that now in order
to do that we're gonna have to go back
inside of our
I'm going to go back inside of our ad folder
folder
inside of our out right here I'm going
to close the routes
and inside of the out folder create a
new file called
layout.dsx like this go ahead and write uh
uh
Health layout like this
and it's going to accept children and
those children have a type of children
react dot react node like that and
inside I'm going to write a div and I'm
going to render children inside and now
our error has gone away and all we have
blacks items Dash Center justify Dash
Center like that and you can give it an
H dash pool as well and now you can see
it's nicely in the middle beautiful so
this now works for both sign in and for
sign up because we have added a common
layout file which is going to affect all
of the routes inside we're going to do a
similar thing in the dashboard so that's
why I separated this in a folder called
routes so there's a very clear
distinction that the routes are only
inside of this folder and this layout
thing is inside this main group folder
right here perfect so let's go ahead and
I want to go to the landing page right
now and I want to show you how to add a
button which is actually going to
redirect to our authentication so let's
go ahead and just below that I want to
add another div and I'm going to add a button
button
like that and there's a couple of ways
you can do this so I'm gonna go ahead
and write uh login for example here and
I'm gonna wrap this in a link from next
and I'm going to add an href slash sign
Dash in like this so now when I click
here you can see that I am on the sign
in page great I'm gonna go back and I'm
gonna copy this entire thing like this
and I'm going to change this to sign
Dash up and this is going to be register
great so now we have the login and the
register so once I click login you can
see I'm in sign in when I click register
you can see that I'm in the register
beautiful and one more cool thing I want
to show you while we're already here is
that you can play around and customize
stuff as much as you want inside of your
clerk for example click on customization
right here go and check out The Branding
so you can see that once I click here it
says sign in to continue to AI Dash SAS
but we said that our name is going to be
called genius so let's go ahead and name
it genius and just click apply changes
and now once I go back and change it here
here
you can see that it says to continue to
genius the name of our application
that's how easy it is to work with the
clerk and you can play around and change
whatever you want you can look at these
hosted Pages if you want to you can
change the colors a bunch of stuff you
can play around with it as much as you
want but now let's go ahead and let's
actually show you how it looks when we
log in so I'm going to click login right
here I'm going to use Google and since I
have only one account I'm immediately
going to get redirected to the dashboard
page so this is now fully working we are
officially logged in that's how easy it
was to use Clerk and let me show you a
cool component that we can use now so
let's go inside of the app folder inside
dashboard routes dashboard page.esx and
I'm going to go ahead and write this
entire thing inside of a div
and just below this I'm going to add a
component from the clerk Library called
user button so user button from add
slash Clerk next.js and look at this now
we have the currently logged in user and
from here you can sign out and yes right
now we are redirected to this page but
I'm going to show you how to control
where we are redirected once we sign out
so let's go back to localhost 3000 let's
log in again using Google
we are back here and I'm gonna add
after sign out URL to be slash and now
if you try and refresh and sign out
again you can see that we're back on the
landing page and if I go to slash
dashboard you can see that I'm uh
triggered I've triggered the sign in
button and once I log in I can freely
visit the dashboard page so that's how
easy it was to use clerk you can go
ahead and play around and see everything
it has and they're constantly updating I
really like using Clerk and I'm very
happy that they're sponsoring this video
because I want to use clerk regardless
if they were sponsoring this or not you
saw that in the e-commerce video it
really helped us save some time when I
want to focus on more important stuff
than Authentication
let's continue and let's start creating
the layout for our dashboard routes so
first thing I'm going to do is just zoom
in the code a little bit so you can see
a bit better great now what I want to do
is I'm going to close everything I'm
going to go inside of my app folder
inside of dashboard right here and
inside of there so not inside routes but
inside dashboard I'm going to create a
new file called
layout.dsx like this and I'm going to go
ahead and I'm going to create a
component called dashboard layout
just like this and the props is going to
have is children and we're gonna write
the types for those so children is a
type of react.react node like this
perfect and inside of this dashboard
what I'm sorry inside of this dashboard
layout what I'm going to do is I'm going
to create a div and I'm going to give
this a class name of H dash full like
this and I'm also going to give it a
class name of relative because we're
going to use some absolute elements in
the future so it's going to be very
useful to have this great and now what
I'm going to do is I'm going to create a
div for our sidebar so let's go ahead
and let's write class name
hidden by default so on small devices we
are not going to show this sidebar we're
going to have a toggle button which is
going to open that in a sheet component
also known as drawer maybe you've heard
it like that and let's give this an H4
let's go ahead and give it an MD of flex
so it's going to be hidden on mobile
devices but when we come to a medium
screen we're going to use flex that's
mean it's going to be visible using the
flex element now let's go ahead
and let's write the following MD is also
going to have a Plex Dash call like that
and MD is also going to be fixed on the
side let's also write MD in set Dash Y
dash zero and let's give it the Z index
of 80 like this sorry like this
and let's write VG Dash gray Dash 900
like that for now great and now inside
what you can do if you want to it's just
a div like this and write hello
sidebar like that and now you can see
that we have a sidebar which has this BG
gray color right here and if you
collapse your screen enough you can see
that it disappears because on mobile
it's going to be hidden great so just
keep it open for now make sure you are
not if you're zoomed in it's also going
to disappear so make sure you're not too
zoomed in and make sure you can actually
see this sidebar because that's the way
we want to develop for now of course
we're going to replace this div with the
actual sidebar component when we get to
creating that but before we do that I
want to create a main element right here
and I'm going to leave this a class name
on medium devices I'm gonna go and give
it a padding left of a 72. that's
because this um this element right here
something I forgot to put here it seems
so let's see I put MD fixed and MD inset
but one thing I forgot to do after MD
Flex is give it a width so go ahead and
just after this MD Flex give it an MD W
Dash 72 like this so great now you can
see that it has filled up more of my
screen so these are the classes needed
for the container which is going to hold
the sidebar hidden H4 mdflex this is
important MD
w-72 MD Flex code fixed and the
positioning for it great and now it
looks much better and now inside I'm
giving this main content a padding of
left of 72. so if I write hello content
inside like this you can see that it's
not overlapping with the sidebar if we
don't have this class you can see that
it disappears it's behind the sidebar so
this way we push it for the amount of 72
which is the same value of the width of
the sidebar meaning that it's always
going to be visible because it is going
to be pushed further than the width of
the sidebar great and now what I want to
do is inside of this main is actually
render the children like this so now you
can see that we have this dashboard page
rendered inside if you're not seeing any
of this just make sure you're on the
dashboard page that's very important
great now I'm going to replace this
hello content with a navbar component
and if we save of course we are going to
get an error because navbar component
does not exist so let's close our app
folder let's go inside the components
and I'm not going to do this inside the
UI folder I'm going to reserve the UI
folder for chat CN components so this is
going to be our custom component so
let's create a new file then let's name it
it
navbar.psx so just make sure it's not
inside of the UI folder it's still going
to work if you put it inside and if you
want it you can do that but I'm gonna do
it like this and let's go right and
right nav bar like this it's not going
to have any props let's give this a
class name of flex items Dash Center
mp-4 like that and for now all I'm going
to do uh for the toggle button for
mobile sidebar is going to be a button
so I'm going to import that from dot
slash UI button but I'm going to replace
this from slash components because I
want to use this Alias rather than
relative Imports I think they look nicer
both is working so you can also use of
course dot slash UI button but I just
prefer this way I want to be consistent
and I'm going to use the menu icon from
Lucid react if you're wondering where
did this cut package come from we got it
when we installed chat CN UI and that's
what I mentioned in the beginning if you
chose a New York style instead of
default style you you will not have
lucid react installed you're going to
have Radix icons so if you want to use
that go ahead and find the equivalent to
Radix I icon for that but if you follow
the tutorial exactly as I did then no
problem you have this and you can just
save the file and in this button I'm
going to give it a variant of ghost and
I'm going to give it a size of Icon and
a class name is going to be
and the hidden
like that okay so we have the basic nav
bar right here ready so let's go back to
our dashboard layout and now we can go
ahead and import this from add slash
components in navbar like this and now
when I save this uh we cannot see
anything but if I Collapse there we go
you can see that I have a toggle button
which later is going to open a mobile
sidebar but on desktop it's not visible
because we don't want it to be visible
great now I just want to quickly clean
up my dashboard route so go into the
dashboard folder into routes dashboard
page.tsx and remove this user button and
remove the Imports so a very clean
dashboard page like that so now we can
go back into our components inside
navbar.dsx right here and we're gonna
actually add that uh user button here
instead so go ahead and open a class
name here sorry a div with a class name
of flex W Dash full
and justify Dash end and go ahead and
write the user button from add slash
clerk next JS like this so now you can
see that our user button is in our nav
bar right here at the top perfect and
don't forget to give this a prop of
after sign out URL to go to slash
perfect Let's test it out so if I sign
out I'm back oh I did not refresh my
apologies so I'm going to go back to
localhost I'm gonna I'm gonna refresh
this time I'm going to click login I'm
going to use Google login and if I try
again there we go everything is working
fine so just log in and make sure you're
on the slash dashboard again see you can
continue developing this great so now
that we have our navbar setup
what we're going to do is we're going to
actually create this sidebar component
so let's go ahead and do that I'm going
to replace this div saying hello sidebar
with an actual sidebar component right
now of course this sidebar does not
exist so we are gonna get an error
we're gonna create our sidebar in the
very same place where we created our navbar
navbar
so I'm going to close the app folder and
inside of the components folder I'm
going to create a new file called
sidebar.tsx like this perfect so let's
go ahead and let's start developing this
the first thing I want to do is I want
to mark this as use client because this
is going to be a client component since
it's going to have some route names and
a bunch of other stuff like that great
what I want to do now is I want to well
let's actually just start developing so
we'll slowly change things up how they
need to be done so go let's go ahead and
write this shorthand for sidebar like
this we're going to leave the props
empty for now
my apologies I added this okay let's go
inside of this return function let's
write a div right here let's go ahead
and write class name space Dash Y dash 4
by 4 Flex Flex Dash call H dash full
BG Dash open square brackets and write a
hex code of
111827 so it's just a specific
background color that I like and text
white like this and inside I'm going to
write hello sidebar component
like this so make sure you have at least
this and then you can go back into app
folder dashboard
layout.ksx and you can actually import
this sidebar component from add slash
components sidebar the same way you did
with navbar right here perfect
let's go back in our sidebar component
and let's continue developing this so
I'm going to remove this text hello
sidebar component and what I'm actually
going to do is I'm going to create a div
with some spacing so let's go ahead and
give it a padding on both sides of three
and on top sides for two and flex dash
one like this and inside I'm going to
use a link component
from next slash link like this
let's go ahead and inside I'm going to
write our logo text let's give it an
hrep of Slash dashboard
so when users click on that they are
gonna get redirected back to the
dashboard so once I click here well we
are already here so no effect seen but
it's going to be an effect when we have
more routes and let's give this some
class names so class name here is going
to be Flex items Dash Center and pl-3 and
and
mb-14 like this and instead of just a
logo let's go ahead and write a div here
with a class name of relative
w-8h-8 and mr-4 like this and inside I'm
going to use an image component from
next slash image like this and let's go
ahead and give this a fill property an
out property of logo and the source is
going to be slash logo dot PNG if we
save we're gonna get this broken image
because this image has not been added to
our project we're gonna add images
inside of our public folder right here
so to find the logo you can either find
anything you want any image you want or
you can visit my GitHub repository link
is in the description go into my public
folder and just find
logo.png and you can just save that file
like this and drag and drop it inside of
public and make sure it's named logo.png
not logo one like it was in my case and
now when you refresh there we go you
have a beautiful logo in the corner perfect
perfect
and now just outside of this div right
here holding our image so below that go
ahead and open an H1 element genius like
that and let's give this some class
names so I'm going to style it by saying
uh text Dash to Excel and font Dash bold
like that but one thing I want to do is
I want to change the font of this text
but I want to keep the same font that it
already is on the entire website so I
only want to change the font for this
one H1 tag so in order to do that I'm
going to use uh a specific package which
we already have from next so let's go
ahead and write const coppins which is
going to be the name of the font I want
to use oh my apologies it's actually
going to be Monster Rat
is going to be Monster Rat which you can
import from next slash font slash Google
like this so make sure you destructure
it and import it from next slash font
slash Google like that now let's go
ahead and give it a weight of 600
of Latin like this
I'm just going to collapse this so you
can see it in a better way
there we go so these are the properties
of the Montserrat constant right here
perfect and what I want to do now is I
want to append that to this class name
right here so I'm going to do that using
the CN Library which we have in our
utils right here which we got from
chatsy and UI so let's go back in our uh
sidebar where is it it's right here okay
and I'm gonna modify this so instead of
just the strings what I'm going to do is
I'm going to wrap this inside curly
brackets like this and I'm going to add
CN and I'm going to import it from add
slash lib slash utils like this so great
now that we have that I'm just going to
separate it because I like to keep my
personal inputs below and Global inputs
at the top like that and how CN works is
that it accepts class names inside of
its parenthesis but you can add both the
default class themes like this and then
you can add a comma and in here you can
add conditional class names or specially
generated class names like this constant
right here so I'm going to write
monsterat which is this class with this
constant that we added right here dot
class name like this and once I save you
can see that my font has changed perfect
so why am I using CN why not just
template literal strings or backticks as
maybe that's how you know them well
that's because this CN library is a
specially made Library which uses
Tailwind merge and clsx to ensure that
there is a proper way we are adding
additional Dynamic class names to
Tailwind elements meaning that it's
going to override them if they already
exist here and it's not gonna create
conflicts great
so now that we have a debt we can go
ahead and continue uh rendering the
actual routes inside of here but before
we render the routes we actually have to
generate an array which is going to hold
all of our routes so let's go do that
here at the top const routes is equal to
a couple of objects in size so make sure
it's an array which holds object the
first object is going to have a label of dashboard
dashboard
like that it's gonna have an icon of
layout dashboard which you can import
from Lucid react right here
href is going to be slash dashboard like
that and we're going to have a color of
text Sky Dash 500 you're gonna see what
color is going to be used for uh in a
second great so I just added my first
item here we're going to add some more
items but before we finish this I just
want to render this out so you can see
how it's going to look like let's go
back here
I'm going to expand this as much as I
can before it collapses to Mobile so
like this so you can see more of the my
code alright so outside of this link
component right here create a new div
with a class name of space Dash Y dash
one so each element inside is going to
be spaced evenly using this class name
and inside I'm going to write routes
which we just created dot map we're
going to get the individual route right
here and I'm gonna open an immediate
return function we're going to wrap
everything in a link component which we
already have imported right here
and it let's go ahead and let's give it
an href of route.href and let's give it
a key the same route.href because it's
guaranteed that that is unique perfect
sorry not clay but key like this great
and now inside of that let's write a div
with a class name
of flex items
Dash Center plex-1 and let's go ahead
and render route dot whoops sorry
route dot icon
which is a self-closing tag and we're
going to give it a class name open curly
brackets we're going to use CN again so
we already have it imported default
class names are going to be h-5 w-5 and
margin right 3 and dynamic class name is
going to be route dot color so that's
the color that we're going to use there
we go you can see how now our little
icon is displayed right here with its
specific color and we load the route
icon element we're just going to render
route that label like this so there we
go now it says dashboard what I want to
do now is I want to give my link some
specific class names so let's go ahead
and write class name
right here and we're gonna write text SM
we're gonna write group
blacks padding Dash 3 W Dash full
justify Dash start font Dash medium
cursor Dash pointer like that hover is
going to be text Dash White
hover is also going to be BG Dash white
slash 10 meaning we are giving it an
opacity rounded LG and transition at the
end like that so now if you hover you
see you have a nice effect for each of
your route
great so now what we can do is we can go
back to our routes and actually create
the rest of the routes so let's go ahead
and do that I'm going to go ahead and
copy this and for my second route I'm
gonna name this conversation like this
I'm going to change the icon to be
message Square from Lucid react which
I've imported at the top right here
great and I'm gonna change the color to
be Violet like this great now let's copy
this again and for the third route let's
write image generation
like that and let's give this an icon of
image icon from Lucid Dash react so
these are my icons so far I have an
image icon I have layout dashboard and
message Square from Lucid react like
that and let's go ahead and change the
color of this to a pink
700 like that great let's copy this
again and let's name this video
generation and let's use the video icon
again from Lucid react right here and
let's change the color of this to Orange
700 like that I'm gonna copy it two more
times so this one is going to be music
generation and it's gonna have an icon called music so just go ahead and import
called music so just go ahead and import that from Lucid react as well and change
that from Lucid react as well and change the color of this to Emerald
the color of this to Emerald 500 like that perfect and last one is
500 like that perfect and last one is going to be code generation sorry not
going to be code generation sorry not last one we also have settings so this
last one we also have settings so this one is going to have an icon of code so
one is going to have an icon of code so you can import that from Lucid react as
you can import that from Lucid react as well like that and give it a color of
well like that and give it a color of green
green 700 like that and our last one is going
700 like that and our last one is going to be simple it's just going to be
to be simple it's just going to be settings
settings icon is going to be settings as well so
icon is going to be settings as well so make sure you import that from Lucid
make sure you import that from Lucid react as well it's not going to have any
react as well it's not going to have any color like this perfect so that looks
color like this perfect so that looks much much better now and what I want to
much much better now and what I want to do now is just change each of their
do now is just change each of their routes the dashboard is fine
routes the dashboard is fine conversation is going to lead to slash
conversation is going to lead to slash conversation image generation is going
conversation image generation is going to lead to slash image don't worry about
to lead to slash image don't worry about this this is just hot reload adding you
this this is just hot reload adding you can refresh and it's going to be normal
can refresh and it's going to be normal so don't worry about that uh for video
so don't worry about that uh for video is going to be slash video for music is
is going to be slash video for music is going to be slash music
going to be slash music uh for code is going to be slash code
uh for code is going to be slash code and settings is going to be slash
and settings is going to be slash settings like that and just refresh all
settings like that and just refresh all of this so you don't have those things
of this so you don't have those things great and now if you try and click on
great and now if you try and click on something other than dashboard you're
something other than dashboard you're gonna get a 404 because none of those
gonna get a 404 because none of those routes exists yet but they are gonna
routes exists yet but they are gonna exist in the future uh perfect so now we
exist in the future uh perfect so now we actually have our working sidebar what I
actually have our working sidebar what I want to do now is I want to enable it on
want to do now is I want to enable it on mobile as well because if you go ahead
mobile as well because if you go ahead and collapse you only have the toggle
and collapse you only have the toggle button but no sidebar opening so let's
button but no sidebar opening so let's see how we can do that
see how we can do that let's go back inside of our navbar
let's go back inside of our navbar component so I'm gonna find it like this
component so I'm gonna find it like this it's inside of your components folder
it's inside of your components folder right here and what you want to do now
right here and what you want to do now I'm still going to expand this just like
I'm still going to expand this just like this what you want to know is you want
this what you want to know is you want to replace this entire thing with its
to replace this entire thing with its own component so I'm going to copy this
own component so I'm going to copy this button which holds the menu icon and I'm
button which holds the menu icon and I'm going to go ahead and create a new
going to go ahead and create a new component called mobile Dash sidebar dot
component called mobile Dash sidebar dot ESX like this let me just show you the
ESX like this let me just show you the name mobile Dash sidebar make sure it's
name mobile Dash sidebar make sure it's use client and let's just quickly export
use client and let's just quickly export that so mobile sidebar
that so mobile sidebar like that it's not going to have any
like that it's not going to have any props for now and you can go ahead and
props for now and you can go ahead and just paste this inside and make sure you
just paste this inside and make sure you add the imports from UI button like this
add the imports from UI button like this but I'm going to replace it with
but I'm going to replace it with components and menu from Lucid react
components and menu from Lucid react like that and you know I like to
like that and you know I like to separate my imports great now we have
separate my imports great now we have that mobile sidebar and now we can go
that mobile sidebar and now we can go back inside of navbar and replace this
back inside of navbar and replace this with mobile sidebar like this and import
with mobile sidebar like this and import it either from dot slash sidebar or I
it either from dot slash sidebar or I like to use components like this and you
like to use components like this and you can remove the import from menu like
can remove the import from menu like that great and now make sure you are in
that great and now make sure you are in mobile view because we're going to work
mobile view because we're going to work on mobile now so either zoom in the page
on mobile now so either zoom in the page or collapse your screen so you don't see
or collapse your screen so you don't see the sidebar and you see the toggle
the sidebar and you see the toggle button great so we can continue working
button great so we can continue working in the mobile sidebar now so I'm going
in the mobile sidebar now so I'm going to close everything besides that
to close everything besides that what we have to do now is we have to add
what we have to do now is we have to add a specific component from chat CN so go
a specific component from chat CN so go ahead and go inside chat CN Library so
ahead and go inside chat CN Library so either use the Google or Link in the
either use the Google or Link in the description go inside components and
description go inside components and let's find the component we need which
let's find the component we need which is a sheet so you can see how it works
is a sheet so you can see how it works it opens like a drawer on the side which
it opens like a drawer on the side which is exactly what we want and the way we
is exactly what we want and the way we install that is by using npx chat cn-ui
install that is by using npx chat cn-ui at latest add sheet so I'm going to
at latest add sheet so I'm going to click copy I'm going to select npm I'm
click copy I'm going to select npm I'm going into my terminal I will shut down
going into my terminal I will shut down the app and I'm going to press enter and
the app and I'm going to press enter and I'm just going to confirm this
I'm just going to confirm this installation by pressing y like this
installation by pressing y like this there we go so now it's installing sheet
there we go so now it's installing sheet great and after a couple of seconds we
great and after a couple of seconds we can run the app again so if you shut
can run the app again so if you shut down the app just make sure you refresh
down the app just make sure you refresh your application so it's up to date and
your application so it's up to date and collapse it of course on the mobile view
collapse it of course on the mobile view perfect
perfect and now what you're going to do is
and now what you're going to do is you're going to add this sheet component
you're going to add this sheet component from dot slash UI sheet like that and
from dot slash UI sheet like that and wrap the entire component inside of that
wrap the entire component inside of that but I'm gonna replace this from slash
but I'm gonna replace this from slash components like this it's still going to
components like this it's still going to work and I'm going to replace this with
work and I'm going to replace this with sheet trigger sorry I'm not going to
sheet trigger sorry I'm not going to replace anything but I'm going to wrap
replace anything but I'm going to wrap it inside of sheet trigger like this and
it inside of sheet trigger like this and one thing I just want to tell you is
one thing I just want to tell you is don't accidentally import stuff from
don't accidentally import stuff from Radix because there are similar renamed
Radix because there are similar renamed components from Radix which are the
components from Radix which are the underlying library that chat CN uses so
underlying library that chat CN uses so whenever you import stuff from chat CN
whenever you import stuff from chat CN like sheet or button or sheet trigger
like sheet or button or sheet trigger make sure it's from add slash components
make sure it's from add slash components UI sheet or dot UI like this so just
UI sheet or dot UI like this so just make sure there's no Radix in your
make sure there's no Radix in your Imports you are not going to work with
Imports you are not going to work with Radix directly great and just below that
Radix directly great and just below that add sheet content also from UI
add sheet content also from UI components like this so I'm just going
components like this so I'm just going to collapse this so it's importing in
to collapse this so it's importing in that way and inside of my sheet content
that way and inside of my sheet content right here what I'm going to do is I'm
right here what I'm going to do is I'm going to give it a property side to be
going to give it a property side to be left and a class name of e Dash is zero
left and a class name of e Dash is zero so I want to remove any pre-made padding
so I want to remove any pre-made padding inside and I'm simply going to render
inside and I'm simply going to render this sidebar component from dot slash
this sidebar component from dot slash sidebar like this or from slash
sidebar like this or from slash component sidebar like that and if you
component sidebar like that and if you click now look at this absolutely
click now look at this absolutely amazing do you see how cool this looks
amazing do you see how cool this looks exactly what we wanted and of course on
exactly what we wanted and of course on desktop there is no toggle button
desktop there is no toggle button perfect this is exactly what we wanted
perfect this is exactly what we wanted and one more thing let's see if we can
and one more thing let's see if we can improve this
improve this uh actually you know what it's fine for
uh actually you know what it's fine for now let's leave it as it is we're going
now let's leave it as it is we're going to change the colors later on you can
to change the colors later on you can see that our x button is actually dark
see that our x button is actually dark but we're gonna solve that later for now
but we're gonna solve that later for now this is what I want to do for this part
this is what I want to do for this part of the tutorial uh great amazing one
of the tutorial uh great amazing one thing that we're gonna add later in the
thing that we're gonna add later in the sidebar when we add subscription is that
sidebar when we add subscription is that little feature on the bottom that is
little feature on the bottom that is counting how many free Generations we
counting how many free Generations we have but we're gonna get to that once we
have but we're gonna get to that once we import and stripe and all the other
import and stripe and all the other things great great job so far
things great great job so far let's continue and let's actually create
let's continue and let's actually create our dashboard page right here but before
our dashboard page right here but before we do that I'm going to refresh a couple
we do that I'm going to refresh a couple of times I want to bring your attention
of times I want to bring your attention that I'm getting this hydration errors
that I'm getting this hydration errors right here so let's quickly fix that
right here so let's quickly fix that they're coming from this const mobile
they're coming from this const mobile sidebar right here so what I'm going to
sidebar right here so what I'm going to write is I'm going to write const is
write is I'm going to write const is mounted
mounted set is mounted right here use state from
set is mounted right here use state from react default value is going to be false
react default value is going to be false then I'm going to write a use effect
then I'm going to write a use effect which I will import from react the same
which I will import from react the same place I did with use State like this and
place I did with use State like this and I'm quickly going to return an arrow
I'm quickly going to return an arrow function I'm going to add an empty
function I'm going to add an empty dependency array and I'm just going to
dependency array and I'm just going to write a set is mounted to true
write a set is mounted to true and in here I'm going to write if it's
and in here I'm going to write if it's not mounted
not mounted return now like this and now you can see
return now like this and now you can see that our hydration error has gone away
that our hydration error has gone away so this is a simple trick you can fix
so this is a simple trick you can fix components which are causing hydration
components which are causing hydration Errors By the way they are rendered
Errors By the way they are rendered perfect so now that we have that and
perfect so now that we have that and still before we go and do something on
still before we go and do something on the dashboard page I quickly want to go
the dashboard page I quickly want to go back in my components inside
back in my components inside sidebar.tsx right here and what I want
sidebar.tsx right here and what I want to do here is I want to mark this as
to do here is I want to mark this as this client all right we already did
this client all right we already did that and then what I want to do is add a
that and then what I want to do is add a path name so cones path name
path name so cones path name is equal to use path name like this and
is equal to use path name like this and we have to import that from next
we have to import that from next navigation so go ahead and import use
navigation so go ahead and import use path name from next slash navigation
path name from next slash navigation like this perfect and now that we have
like this perfect and now that we have that I'm gonna go ahead and I'm going to
that I'm gonna go ahead and I'm going to click a command which is going to
click a command which is going to collapse all the code inside uh so it's
collapse all the code inside uh so it's not like spreading around so you can see
not like spreading around so you can see everything in one file right here and
everything in one file right here and I'm going to find my route.map link
I'm going to find my route.map link component and you have seen this huge
component and you have seen this huge class name that we have well we have to
class name that we have well we have to make it Dynamic that's because right now
make it Dynamic that's because right now in my sidebar you have no idea what
in my sidebar you have no idea what route am I on right but I am on slash
route am I on right but I am on slash dashboard so what I would expect is that
dashboard so what I would expect is that dashboard is looking like this like when
dashboard is looking like this like when I'm hovering on it right but I want it
I'm hovering on it right but I want it to be like that regardless if I'm
to be like that regardless if I'm hovering or not I want it to show to my
hovering or not I want it to show to my users that that is the currently active
users that that is the currently active page so what I'm gonna do is I'm going
page so what I'm gonna do is I'm going to find the start of this class name the
to find the start of this class name the end of this class name and I'm going to
end of this class name and I'm going to wrap the entire thing in curly brackets
wrap the entire thing in curly brackets like this and then I'm going to use this
like this and then I'm going to use this very same CN tool so CN I'm going to
very same CN tool so CN I'm going to open parenthesis and I'm going to end
open parenthesis and I'm going to end them by the end of the annotations so
them by the end of the annotations so now the entire class name is inside of
now the entire class name is inside of the CN if I refresh everything is
the CN if I refresh everything is staying exactly the same then I'm going
staying exactly the same then I'm going to add a comma to add a dynamic class
to add a comma to add a dynamic class name here and I'm going to expand this
name here and I'm going to expand this as much as I can like that and I'm going
as much as I can like that and I'm going to write if path name so if current path
to write if path name so if current path name is equal to this route href that
name is equal to this route href that means obviously it is uh it is currently
means obviously it is uh it is currently active and we have to highlight it in
active and we have to highlight it in some way but I'm having an error here
some way but I'm having an error here let's see I think I made a mistake yes
let's see I think I made a mistake yes so const path name like this
so const path name like this great so now that we have the cons path
great so now that we have the cons path name I can compare that I can add a
name I can compare that I can add a question mark and I can add a dynamic
question mark and I can add a dynamic class name which is going to be text
class name which is going to be text Dash white and BG Dash white slash 10
Dash white and BG Dash white slash 10 else I'm going to use text sync Dash 400
else I'm going to use text sync Dash 400 like that so now you can see that my
like that so now you can see that my dashboard is highlighted by default
dashboard is highlighted by default because I am on slash dashboard if yours
because I am on slash dashboard if yours is not highlighted make sure that it's
is not highlighted make sure that it's not misspelled right here in the routes
not misspelled right here in the routes constant beautiful so now that we have
constant beautiful so now that we have that
that let's go ahead and let's actually create
let's go ahead and let's actually create our dashboard page so I'm just going to
our dashboard page so I'm just going to expand it a little bit I'm going to
expand it a little bit I'm going to close everything I'm gonna go inside the
close everything I'm gonna go inside the app folder inside dashboard routes
app folder inside dashboard routes dashboard and page.dsx right here where
dashboard and page.dsx right here where we have uh this page right here let's go
we have uh this page right here let's go ahead and let's remove this text and
ahead and let's remove this text and let's create a div with the class name
let's create a div with the class name of text my apologies margin bottom Dash
of text my apologies margin bottom Dash 8 space Dash Y dash four and inside
8 space Dash Y dash four and inside let's create an H1 element uh maybe
let's create an H1 element uh maybe better H2 element instead
better H2 element instead and let's just write explore the power
and let's just write explore the power of AI like this and let's give it a
of AI like this and let's give it a class name of text-2 excel so that's
class name of text-2 excel so that's going to be on small devices but on
going to be on small devices but on medium devices we can increase it even
medium devices we can increase it even more so text-4 Excel like that let's
more so text-4 Excel like that let's give it a font bold and let's give it a
give it a font bold and let's give it a text Center like this there we go below
text Center like this there we go below that I'm gonna add a paragraph which is
that I'm gonna add a paragraph which is going to say chat with the smartest AI X
going to say chat with the smartest AI X experience the power of AI or whatever
experience the power of AI or whatever text you want it doesn't really matter
text you want it doesn't really matter and let's give this a class name of text
and let's give this a class name of text muted Dash foreground
muted Dash foreground like this and you can see how now it's a
like this and you can see how now it's a bit muted and if you're wondering where
bit muted and if you're wondering where did this class name came from that's
did this class name came from that's because this is not a class name from
because this is not a class name from Tailwind CSS this is a class name from
Tailwind CSS this is a class name from chat CN UI so that's why it's working
chat CN UI so that's why it's working here now let's use Font light and let's
here now let's use Font light and let's give it the text of small on mobile
give it the text of small on mobile devices but on medium we're gonna use
devices but on medium we're gonna use text LG so a bit of a larger text and
text LG so a bit of a larger text and let's use text Dash centers it looks
let's use text Dash centers it looks nice and in the center perfect now
nice and in the center perfect now outside of this div right here open
outside of this div right here open another div the class name of ex-4 on
another div the class name of ex-4 on mobile devices on medium is going to be
mobile devices on medium is going to be px20 on the large it's going to be px32
px20 on the large it's going to be px32 and space Dash Y dash four beautiful now
and space Dash Y dash four beautiful now let's go ahead and let's mark this page
let's go ahead and let's mark this page as use client because we're going to
as use client because we're going to have some interactive elements inside
have some interactive elements inside what we have to do now is we have to
what we have to do now is we have to create our tools array so we can iterate
create our tools array so we can iterate over them right here so let's write the
over them right here so let's write the cons tools is equal an array of objects
cons tools is equal an array of objects it's going to have a label of
it's going to have a label of conversation
conversation like this icon of message Square
like this icon of message Square and you can import message Square
and you can import message Square from Lucid react like this let's give it
from Lucid react like this let's give it a color of text
a color of text violet-500
violet-500 let's give it a BG color of text
let's give it a BG color of text violet-500-10 my apology is not text but
violet-500-10 my apology is not text but BG and let's give it an hrap of Slash
BG and let's give it an hrap of Slash conversation like that
conversation like that and now inside of here
and now inside of here let's go ahead and let's iterate over
let's go ahead and let's iterate over our tools
our tools so tools.map
so tools.map tool
tool and immediately go ahead and return a
and immediately go ahead and return a new element that we need which you can
new element that we need which you can get from chat CN UI so we have to go to
get from chat CN UI so we have to go to chat cnui and add a new component
chat cnui and add a new component so let's go in here and in the sidebar
so let's go in here and in the sidebar I'm gonna go ahead and I'm going to find
I'm gonna go ahead and I'm going to find the card element right here so this is
the card element right here so this is what we want I want this element right
what we want I want this element right here so I'm going to use this command
here so I'm going to use this command ntx chat cn-ui at latest add card I'm
ntx chat cn-ui at latest add card I'm going to copy the command as npm and I'm
going to copy the command as npm and I'm gonna go inside of my terminal
gonna go inside of my terminal and I'm going to paste the command right
and I'm going to paste the command right here
here I'm going to confirm that I want to
I'm going to confirm that I want to install it and I'm going to run npm run
install it and I'm going to run npm run Dev like this so make sure you refresh
Dev like this so make sure you refresh your project after that beautiful so now
your project after that beautiful so now we have a new component in our uh
we have a new component in our uh components style great so go ahead and
components style great so go ahead and add that so card from add slash
add that so card from add slash components UI card make sure you've
components UI card make sure you've imported it like this and I'm going to
imported it like this and I'm going to separate my imports beautiful and let's
separate my imports beautiful and let's go ahead and let's give it a key of tool
go ahead and let's give it a key of tool dot href like this and I'm just going to
dot href like this and I'm just going to collapse this element like this because
collapse this element like this because I'm going to add a bunch of class names
I'm going to add a bunch of class names so it's a bit more readable for all of
so it's a bit more readable for all of us let's go ahead and let's write
us let's go ahead and let's write last name
last name to be
to be b-4 border Dash Black slash Five
b-4 border Dash Black slash Five Plex items Dash Center
Plex items Dash Center justify Dash between hover Shadow Dash
justify Dash between hover Shadow Dash MD transition and cursor Dash pointer
MD transition and cursor Dash pointer like this
like this beautiful so now you can already see a
beautiful so now you can already see a little box right here that has appeared
little box right here that has appeared because I have one element in tools and
because I have one element in tools and I am iterating over it and rendering
I am iterating over it and rendering this card with this class names and this
this card with this class names and this class name has a class that when we
class name has a class that when we hover we add a little Shadow to it right
hover we add a little Shadow to it right here so I can even zoom in so you can
here so I can even zoom in so you can see a bit better it's very subtle but I
see a bit better it's very subtle but I think it looks nice great now inside of
think it looks nice great now inside of that card create a new div with the
that card create a new div with the class name
class name or Flex items Dash Center and GAP Dash
or Flex items Dash Center and GAP Dash x-4 like this and inside of that you're
x-4 like this and inside of that you're gonna create a new div with a class name
gonna create a new div with a class name open curly brackets use the CN library
open curly brackets use the CN library from add slash Libs urals like this and
from add slash Libs urals like this and go ahead and open parenthesis let's
go ahead and open parenthesis let's write some default classes so that is
write some default classes so that is going to be p-2 W Dash fit and
going to be p-2 W Dash fit and rounded-md and a dynamic class name is
rounded-md and a dynamic class name is going to be tool.bg color like that
going to be tool.bg color like that beautiful and inside we're going to
beautiful and inside we're going to render tool dot icon which is a
render tool dot icon which is a self-closing tag and I'm gonna give you
self-closing tag and I'm gonna give you the class name again curly brackets
the class name again curly brackets opencn and parenthesis inside
opencn and parenthesis inside w-8 and h-8 for the default class and
w-8 and h-8 for the default class and dynamic class is going to be two dot
dynamic class is going to be two dot color like this there we go so you can
color like this there we go so you can see how nice that looks perfect and now
see how nice that looks perfect and now just below this div which is rendering
just below this div which is rendering our our icon go ahead and create a new
our our icon go ahead and create a new div with the class name of font semi
div with the class name of font semi bold like this and inside you're going
bold like this and inside you're going to render tool dot label like that
to render tool dot label like that beautiful and now outside of this last
beautiful and now outside of this last div but still inside the card element
div but still inside the card element you're going to render Arrow right
you're going to render Arrow right component from Lucid react like this and
component from Lucid react like this and it is a self-closing tag just make sure
it is a self-closing tag just make sure you've imported it here at the top and
you've imported it here at the top and let's go ahead and give it a class name
let's go ahead and give it a class name of w-5 and h-5 like this beautiful and
of w-5 and h-5 like this beautiful and now let's go ahead and let's actually
now let's go ahead and let's actually add some more tools right here so I'm
add some more tools right here so I'm going to copy this same way we did with
going to copy this same way we did with the sidebar so I'm going to write for
the sidebar so I'm going to write for the second one to be music generation
the second one to be music generation the icon I'm going to use is music so
the icon I'm going to use is music so import that from Lucid react the color
import that from Lucid react the color is going to be Emerald like this
is going to be Emerald like this and the href is going to be slash music
and the href is going to be slash music like that let's go ahead and copy that
like that let's go ahead and copy that again and don't forget to add a comma
again and don't forget to add a comma the third one is going to be image
the third one is going to be image generation it's going to have an icon of
generation it's going to have an icon of image icon so import that from
image icon so import that from lucidreact as well I'm just going to
lucidreact as well I'm just going to collapse this so it's a bit nicer to
collapse this so it's a bit nicer to look at
there we go so we have the image icon now uh let's change the color to be pink
now uh let's change the color to be pink and I'm not going to use 500 but 700 for
and I'm not going to use 500 but 700 for both of these colors and href is going
both of these colors and href is going to be slash image beautiful let's copy
to be slash image beautiful let's copy that don't forget a comma
that don't forget a comma this one is going to be video generation
this one is going to be video generation so video Generation image is going to be
so video Generation image is going to be video icon so again make sure you have
video icon so again make sure you have that imported from Lucid react the color
that imported from Lucid react the color right here is going to be orange 700
right here is going to be orange 700 like that and let's go ahead and copy
like that and let's go ahead and copy the last one which is going to be code
the last one which is going to be code generation the icon is going to be code
generation the icon is going to be code so again make sure you have imported
so again make sure you have imported that from lucidreact and the color is
that from lucidreact and the color is going to be green like this and href is
going to be green like this and href is going to be code and we also have to
going to be code and we also have to change the href for video to slash video
change the href for video to slash video like that beautiful absolutely amazing
like that beautiful absolutely amazing you can see how nice this looks even on
you can see how nice this looks even on desktop and on mobile as well perfect
desktop and on mobile as well perfect and just one more thing I want to add
and just one more thing I want to add before we wrap up the dashboard page is
before we wrap up the dashboard page is that when we click on this card so go
that when we click on this card so go ahead and find the tools.map find the
ahead and find the tools.map find the card element and write on click to Be an
card element and write on click to Be an Arrow function and right now we actually
Arrow function and right now we actually can't do anything we have to add the
can't do anything we have to add the router so const router is equal to use
router so const router is equal to use router but not from next slash router we
router but not from next slash router we have to use next slash navigation like
have to use next slash navigation like this so make sure you have imported use
this so make sure you have imported use router from next slash navigation and
router from next slash navigation and I'm gonna move that to the top right
I'm gonna move that to the top right here perfect and now that you have this
here perfect and now that you have this constant use router let's go ahead and
constant use router let's go ahead and finish this Arrow function it's going to
finish this Arrow function it's going to write router dot push
write router dot push tool dot href like this there we go so
tool dot href like this there we go so now when I click on conversation we are
now when I click on conversation we are redirected to slash conversation but we
redirected to slash conversation but we get a 404 because that does not exist
get a 404 because that does not exist yet and that is true for all of those
yet and that is true for all of those here beautiful you have finished the
here beautiful you have finished the dashboard page for your application you
dashboard page for your application you have a working sidebar and a mobile
have a working sidebar and a mobile cyber as well you also have implemented
cyber as well you also have implemented authentication great great job we can
authentication great great job we can now finally go ahead and create our
now finally go ahead and create our first AI tool which is going to be the
first AI tool which is going to be the conversation great great job so far
conversation great great job so far now it's time to create our conversation
now it's time to create our conversation page so what I'm going to do is I'm
page so what I'm going to do is I'm going to close everything I'm going to
going to close everything I'm going to go inside of my app folder inside the
go inside of my app folder inside the dashboard route group inside routes and
dashboard route group inside routes and on the same level as dashboard I'm going
on the same level as dashboard I'm going to create a new folder called
to create a new folder called conversation like this and inside I'm
conversation like this and inside I'm going to create a new file
going to create a new file page.dsx and let's go ahead and let's
page.dsx and let's go ahead and let's quickly export default a component
quickly export default a component called conversation page like this and
called conversation page like this and all I'm going to do in the return is a
all I'm going to do in the return is a div saying hello conversation like that
div saying hello conversation like that and now that you have this conversation
and now that you have this conversation route right here you can go ahead and
route right here you can go ahead and click on conversation either in the
click on conversation either in the dashboard or in the sidebar or manually
dashboard or in the sidebar or manually go to slash conversation and you are
go to slash conversation and you are going to see that route right here so
going to see that route right here so you can try it from here and from here
you can try it from here and from here it should be exactly the same because
it should be exactly the same because the href is matching perfect now what I
the href is matching perfect now what I want to do is I want to replace this
want to do is I want to replace this text hello conversation
text hello conversation with a heading component so let's go
with a heading component so let's go ahead and do that so I'm going to
ahead and do that so I'm going to replace this with heading like this and
replace this with heading like this and now I'm going to get an error because
now I'm going to get an error because the heading component does not exist so
the heading component does not exist so let's go ahead and let's create that
let's go ahead and let's create that inside of our components folder here
inside of our components folder here create a new file called
create a new file called heading.psx like that and in here I'm
heading.psx like that and in here I'm going to export const heading like this
going to export const heading like this which is going to just return a simple
which is going to just return a simple div saying heading component like that
div saying heading component like that perfect and now that we have that we can
perfect and now that we have that we can go back inside of our conversation page
go back inside of our conversation page and import heading from add slash
and import heading from add slash components heading like this and once I
components heading like this and once I save you can see that now it's rendering
save you can see that now it's rendering the text from that very same component
the text from that very same component now let's create an interface for this
now let's create an interface for this heading so interface heading props like
heading so interface heading props like this is going to have a title which is a
this is going to have a title which is a type of a string it's going to have a
type of a string it's going to have a description which is a type of string as
description which is a type of string as well it's going to have an icon which is
well it's going to have an icon which is a type of lucid icon from lucidreact now
a type of lucid icon from lucidreact now when I did this in the first iteration
when I did this in the first iteration of this project I actually didn't have
of this project I actually didn't have this import I used icon but for some
this import I used icon but for some reason now it's a lucid icon so if
reason now it's a lucid icon so if you're just having any trouble with this
you're just having any trouble with this you can just put any and save yourself
you can just put any and save yourself any trouble if you're getting errors
any trouble if you're getting errors here but for now this seems to work
here but for now this seems to work perhaps a package has updated and
perhaps a package has updated and changed that type or maybe I did
changed that type or maybe I did something wrong in the initial project
something wrong in the initial project but regardless if this is working fine
but regardless if this is working fine for you you can just continue like that
for you you can just continue like that if you're having any problems just
if you're having any problems just replace this with any okay besides icon
replace this with any okay besides icon we are also going to have an optional
we are also going to have an optional icon color so put a question mark it's a
icon color so put a question mark it's a type of string and an optional BG color
type of string and an optional BG color like this which is also a type of string
like this which is also a type of string now let's go ahead and let's destructure
now let's go ahead and let's destructure these props so title description icon
these props so title description icon icon color
icon color and VG color like that and let's go
and VG color like that and let's go ahead and assign the props heading props
ahead and assign the props heading props like this there we go beautiful and now
like this there we go beautiful and now let's go back inside of our conversation
let's go back inside of our conversation page and let's assign these props right
page and let's assign these props right here so we can better see what we are
here so we can better see what we are developing so the title is going to be
developing so the title is going to be conversation the description is going to
conversation the description is going to be our most advanced conversation model
be our most advanced conversation model or whatever you want really icon is
or whatever you want really icon is going to be message Square from
going to be message Square from lucidreact and I'm going to separate my
lucidreact and I'm going to separate my inverse like this great the icon color
inverse like this great the icon color is going to be textlash violet
is going to be textlash violet 500 and VG color is going to be BG Dash
500 and VG color is going to be BG Dash violet Dash 500 slash 10 like this so
violet Dash 500 slash 10 like this so nothing much to change now but you can
nothing much to change now but you can see that there are no errors in this
see that there are no errors in this component meaning that we passed all the
component meaning that we passed all the correct props if you're having an error
correct props if you're having an error with the icon that probably is referring
with the icon that probably is referring to what I said before just replace this
to what I said before just replace this with any but it seems to work fine so
with any but it seems to work fine so you can just follow along now let's use
you can just follow along now let's use these props to actually create something
these props to actually create something in this heading component let's go ahead
in this heading component let's go ahead and let's wrap this entire thing into a
and let's wrap this entire thing into a fragment first like this and now let's
fragment first like this and now let's go ahead and let's give this div a class
go ahead and let's give this div a class name
name of tx-4 on large you're going to have a
of tx-4 on large you're going to have a bigger padding so px-8 Flex items Dash
bigger padding so px-8 Flex items Dash Center
Center get Dash x-3 and margin bottom of 8 like
get Dash x-3 and margin bottom of 8 like that great now inside of this instead of
that great now inside of this instead of that text create another div with a
that text create another div with a dynamic class name so open curly
dynamic class name so open curly brackets and go ahead and import the CN
brackets and go ahead and import the CN library from our Lids like that so make
library from our Lids like that so make sure you have that open parenthesis
sure you have that open parenthesis let's give it some default classes in my
let's give it some default classes in my case it's going to be W10 and h10 and
case it's going to be W10 and h10 and pass the dynamic icon uh oh my apologies
pass the dynamic icon uh oh my apologies I made the uh I wrote the wrong line so
I made the uh I wrote the wrong line so first thing we have to do is actually
first thing we have to do is actually the container for the icon that was the
the container for the icon that was the class name for the icon my apologies so
class name for the icon my apologies so this is the correct class name p-2
this is the correct class name p-2 W fit and rounded Dash MD and the
W fit and rounded Dash MD and the dynamic color is BG color like this
dynamic color is BG color like this perfect and now inside of that go ahead
perfect and now inside of that go ahead and render the icon like this and we
and render the icon like this and we don't have this icon so we have to remap
don't have this icon so we have to remap this icon to a capital icon so go into
this icon to a capital icon so go into your props right here where the icon is
your props right here where the icon is and just remap it to Icon like this nice
and just remap it to Icon like this nice and now let's go ahead and let's give
and now let's go ahead and let's give this a class name
this a class name of CN like this w-10 h-10 and icon color
of CN like this w-10 h-10 and icon color like this
like this there we go so now you can see how that
there we go so now you can see how that very same icon from the dashboard is
very same icon from the dashboard is here as well that's exactly what we
here as well that's exactly what we wanted beautiful now what I want to do
wanted beautiful now what I want to do is I want to go outside of this div
is I want to go outside of this div right here
right here I'm going to create a new div
I'm going to create a new div and I'm going to create an H2 element
and I'm going to create an H2 element inside with a class name
inside with a class name of text-3 Excel and font Dash bold like
of text-3 Excel and font Dash bold like that and let's create a text rendering
that and let's create a text rendering title like this but we made a mistake so
title like this but we made a mistake so I created this div outside of this main
I created this div outside of this main div and what I think we want to actually
div and what I think we want to actually do is render it inside of that so not in
do is render it inside of that so not in uh the bottom of our fragment but right
uh the bottom of our fragment but right here like this there we go that's what I
here like this there we go that's what I wanted to do my apologies so I will just
wanted to do my apologies so I will just indent this to look as it should and
indent this to look as it should and what I'm going to do inside of this div
what I'm going to do inside of this div is just below the H2 element I'm going
is just below the H2 element I'm going to create a new paragraph in which we're
to create a new paragraph in which we're going to render the description like
going to render the description like this and I'm going to add a class name
this and I'm going to add a class name here text SM
here text SM tax Dash muted Dash foreground like this
tax Dash muted Dash foreground like this there we go so now we have a nice
there we go so now we have a nice heading component that we can reuse
heading component that we can reuse throughout all of these models right
throughout all of these models right here let me just expand this so you can
here let me just expand this so you can see exactly how this looks and I think
see exactly how this looks and I think we actually don't need this fragment
we actually don't need this fragment there we go yeah we don't need a
there we go yeah we don't need a fragment so just create a div which
fragment so just create a div which defines our padding on both small
defines our padding on both small devices and large devices it is as Flex
devices and large devices it is as Flex to Center the items and add some
to Center the items and add some additional spacing between these items
additional spacing between these items then we have the first div holding our
then we have the first div holding our icon and its background and the second
icon and its background and the second div holding the title and the
div holding the title and the description and you can see how it looks
description and you can see how it looks nice on both mobile and desktop nice
nice on both mobile and desktop nice great I'm just going to expand this as
great I'm just going to expand this as much as I can so we can still develop
much as I can so we can still develop here and now let's go back inside of our
here and now let's go back inside of our page.tsx because the heading component
page.tsx because the heading component is finished and there's nothing more we
is finished and there's nothing more we can do here so just below this heading
can do here so just below this heading component we create a new div inside of
component we create a new div inside of your conversation page with last name of
your conversation page with last name of vx-4 but an lgbx-8 like this and what
vx-4 but an lgbx-8 like this and what you're going to render inside of here is
you're going to render inside of here is our form but we have no form elements
our form but we have no form elements yet so what we have to do is we have to
yet so what we have to do is we have to go inside our chat CN UI right here and
go inside our chat CN UI right here and let's go ahead and find the form
let's go ahead and find the form component right here react hook form
component right here react hook form like this so whoops I'm just going to
like this so whoops I'm just going to expand it a little bit so you can see
expand it a little bit so you can see better and let's go ahead and let's find
better and let's go ahead and let's find how to install that so we are using npx
how to install that so we are using npx chat cn-ui at latest add form I'm gonna
chat cn-ui at latest add form I'm gonna copy that as npm and I'm going to go
copy that as npm and I'm going to go inside of my terminal right here I will
inside of my terminal right here I will paste that and I'm going to confirm the
paste that and I'm going to confirm the installation like this and it's going to
installation like this and it's going to install a couple of packages so this is
install a couple of packages so this is a bit of a larger component so we're
a bit of a larger component so we're gonna get react hook form we're going to
gonna get react hook form we're going to get all the form elements and we're also
get all the form elements and we're also going to get some validators so go ahead
going to get some validators so go ahead and refresh your application if you've
and refresh your application if you've shatted it down and and just make sure
shatted it down and and just make sure it loads normally and what we can do now
it loads normally and what we can do now is we can actually start building our
is we can actually start building our form but before we do that let's go
form but before we do that let's go ahead and let's actually create some
ahead and let's actually create some functions that the form is going to need
functions that the form is going to need so const form is equal use form from
so const form is equal use form from react to cook form which is a new
react to cook form which is a new package that we now have thanks to this
package that we now have thanks to this command that we just run so they that
command that we just run so they that installed this for us inside of this use
installed this for us inside of this use form let's go ahead
form let's go ahead and let's define the default values
and let's define the default values my apologies
my apologies default values are like this let's give
default values are like this let's give it a prompt which is an empty string so
it a prompt which is an empty string so we are only going to have one input
we are only going to have one input which is going to take this
which is going to take this prompt right here and now you see that I
prompt right here and now you see that I have an error because I'm using use form
have an error because I'm using use form which is obviously in the hook meaning
which is obviously in the hook meaning it uses a context so for that I have to
it uses a context so for that I have to mark this entire component as use client
mark this entire component as use client and once I save the error has gone away
and once I save the error has gone away perfect what I want to do now is import
perfect what I want to do now is import Zod so there is a specific way we have
Zod so there is a specific way we have to import Zod which we are going to use
to import Zod which we are going to use to create our schemas and a bunch of
to create our schemas and a bunch of validation in our forms so import
validation in our forms so import asterisks as Z from Zod like this
asterisks as Z from Zod like this beautiful and now what I want to do is I
beautiful and now what I want to do is I want to create a constants file where we
want to create a constants file where we are going to keep our form schema so
are going to keep our form schema so let's go ahead and inside this
let's go ahead and inside this conversation folder create a new file
conversation folder create a new file called
called constance.thes like that and go ahead
constance.thes like that and go ahead and write again import asterisk as Z
and write again import asterisk as Z from zot and expert const forms schema
from zot and expert const forms schema to be Z dot object
to be Z dot object open an object inside prompt which is
open an object inside prompt which is our one of our default values if you
our one of our default values if you remember right here so let's go ahead
remember right here so let's go ahead and give it a type so it's going to be Z
and give it a type so it's going to be Z dot string it's going to be required at
dot string it's going to be required at least one character and let's add a
least one character and let's add a custom message if that is not true to be
custom message if that is not true to be prompt is required like this
prompt is required like this beautiful so just make sure you export
beautiful so just make sure you export const this form schema and now we can go
const this form schema and now we can go back in page DSX right here and let's go
back in page DSX right here and let's go ahead and let's actually import that
ahead and let's actually import that from our constants so I'm going to write
from our constants so I'm going to write import
import one schema from dot slash constants so
one schema from dot slash constants so no need to use the add sign here because
no need to use the add sign here because we are only going to use it inside of
we are only going to use it inside of this folder there we go so now that we
this folder there we go so now that we have that we can actually Define the
have that we can actually Define the types for this use form so go ahead and
types for this use form so go ahead and just before the first parenthesis open
just before the first parenthesis open this curly brackets sorry this pointy
this curly brackets sorry this pointy brackets and write z dot infer like this
brackets and write z dot infer like this go ahead and open pointy brackets one
go ahead and open pointy brackets one more time type off form schema like this
more time type off form schema like this and then besides default values we can
and then besides default values we can also add a resolver like this and for
also add a resolver like this and for the resolver we are actually going to
the resolver we are actually going to use Zod resolver
use Zod resolver like that and we're going to pass in
like that and we're going to pass in form schema now let's go ahead and
form schema now let's go ahead and import the Zod resolver from another
import the Zod resolver from another package that we got thanks to installing
package that we got thanks to installing uh the form component from chat cnui so
uh the form component from chat cnui so go ahead and write import
go ahead and write import Zod resolver from add hook form slash
Zod resolver from add hook form slash resolvers slash Zod like this so I just
resolvers slash Zod like this so I just want to explain this that this at sign
want to explain this that this at sign and this at sign is just a coincidence
and this at sign is just a coincidence so this is the actual name of the
so this is the actual name of the package from npm and this is just our
package from npm and this is just our Alias to go to uh the root of our
Alias to go to uh the root of our project so don't confuse the two you can
project so don't confuse the two you can see that there is a difference so this
see that there is a difference so this one is exactly next to the name and our
one is exactly next to the name and our has a slash so that's the difference
has a slash so that's the difference this is the actual name of the package
this is the actual name of the package and this is our own component so I just
and this is our own component so I just want to explain that in case you're
want to explain that in case you're confused great now we have a Zone
confused great now we have a Zone resolver which is going to control the
resolver which is going to control the validation for this form right here and
validation for this form right here and now let's go ahead and just write two
now let's go ahead and just write two more things regarding the form that we
more things regarding the form that we are going to need before we start adding
are going to need before we start adding some elements here so I want to extract
some elements here so I want to extract the loading State usually in my past
the loading State usually in my past tutorials I was using use state from
tutorials I was using use state from react to control the loading state but
react to control the loading state but thanks to some of your comments I
thanks to some of your comments I figured out that use form actually has
figured out that use form actually has its own the loading state so I'm going
its own the loading state so I'm going to write a constant is loading here to
to write a constant is loading here to be form.form state that is submitting
be form.form state that is submitting like this
like this and we're going to use that throughout
and we're going to use that throughout this form and let's write a simple const
this form and let's write a simple const on submit form it's going to be an
on submit form it's going to be an asynchronous arrow function which takes
asynchronous arrow function which takes the prop of values
the prop of values like this which is a type of Z dot infer
type of form schema like that and it's just a simple arrow function and for now
just a simple arrow function and for now all I'm going to do is console log the
all I'm going to do is console log the values like that because we have no API
values like that because we have no API ready to send it to beautiful so we have
ready to send it to beautiful so we have all of that now and now we are ready to
all of that now and now we are ready to actually build our form so let's go
actually build our form so let's go ahead and inside of this div create a
ahead and inside of this div create a new div and then you're going to add
new div and then you're going to add form component from add slash components
form component from add slash components slash UI form so just make sure you've
slash UI form so just make sure you've imported this like that now that you
imported this like that now that you have your form component here go ahead
have your form component here go ahead and pass in
and pass in spread form like this so we're going to
spread form like this so we're going to pass in all of the functions this form
pass in all of the functions this form constant has which uses the react hook
constant has which uses the react hook form so that is instead of us passing it
form so that is instead of us passing it all the props manually we can just do
all the props manually we can just do this and it's much quicker
this and it's much quicker now inside of that go ahead and write
now inside of that go ahead and write the native HTML form element like this
the native HTML form element like this and inside go ahead and add an on submit
and inside go ahead and add an on submit prop which is going to be form dot
prop which is going to be form dot handle submit go ahead and open
handle submit go ahead and open parenthesis and then we're going to pass
parenthesis and then we're going to pass in this constant on submit that we've
in this constant on submit that we've created above there we go and now let's
created above there we go and now let's go ahead and add some class names to
go ahead and add some class names to this form so class name
this form so class name is going to be rounded LG border W Dash
is going to be rounded LG border W Dash full p dash 4 PX 3 on medium devices is
full p dash 4 PX 3 on medium devices is going to be
going to be X-6 so a bit of a larger spacing on
X-6 so a bit of a larger spacing on larger devices Focus dash Within
larger devices Focus dash Within is going to be Shadow Dash SM
is going to be Shadow Dash SM grid and grid Dash course 12 and gap-2
grid and grid Dash course 12 and gap-2 and you should see a very small
and you should see a very small container visible inside like that nice
container visible inside like that nice now let's go ahead inside of this native
now let's go ahead inside of this native Four Element and let's add a form field
Four Element and let's add a form field so form field like this and you can
so form field like this and you can import that again from components UI
import that again from components UI form make sure you have it right here
form make sure you have it right here like that and form field is going to be
like that and form field is going to be a self-closing tag so let's go ahead and
a self-closing tag so let's go ahead and write a name for this field which is
write a name for this field which is going to be prompt
going to be prompt so it's going to control this value
so it's going to control this value right here and we have the validation
right here and we have the validation for that value right here great so this
for that value right here great so this form field is going to control that
form field is going to control that value and now let's give it a render
value and now let's give it a render prop like this go ahead and open
prop like this go ahead and open parenthesis go ahead and immediately the
parenthesis go ahead and immediately the structure a field from that and just
structure a field from that and just open an arrow function which is
open an arrow function which is immediately going to render an element
immediately going to render an element and that element is going to be our form
and that element is going to be our form item again from add slash components UI
item again from add slash components UI form like this make sure you've imported
form like this make sure you've imported form item from add slash components UI
form item from add slash components UI form like that let's go ahead and give
form like that let's go ahead and give this a class name
this a class name of call Dash span
of call Dash span 12 so that's going to be for mobile
12 so that's going to be for mobile devices but on large is going to be call
devices but on large is going to be call Dash span-10 like that inside of that
Dash span-10 like that inside of that form item add a new component form
form item add a new component form component whoops form control again from
component whoops form control again from add slash components UI form just check
add slash components UI form just check that it's imported right here so I'm
that it's imported right here so I'm just going to collapse all of this so
just going to collapse all of this so you can clearly see and don't have to
you can clearly see and don't have to skew to see it great so we have the form
skew to see it great so we have the form control now and this form control is
control now and this form control is going to have a class name
going to have a class name of margin 0 and padding zero like that
of margin 0 and padding zero like that and inside we have to add another
and inside we have to add another component called input but our input
component called input but our input does not come with our uh hook uh this
does not come with our uh hook uh this hook at this ad form uh CLI so we have
hook at this ad form uh CLI so we have to add it manually by finding it here
to add it manually by finding it here let's go ahead and let's find the input
let's go ahead and let's find the input right here there we go and let's see how
right here there we go and let's see how we can install it using npx chat CNY
we can install it using npx chat CNY latest add input so I'm going to copy
latest add input so I'm going to copy that as npm as well I'm going to go
that as npm as well I'm going to go inside of my terminal and I'm going to
inside of my terminal and I'm going to run that Command right here I'm going to
run that Command right here I'm going to press yes and I'm going to run the
press yes and I'm going to run the project again and of course I'm going to
project again and of course I'm going to refresh to make sure everything is
refresh to make sure everything is running smoothly
running smoothly now that we have that let's go ahead and
now that we have that let's go ahead and let's add the input from our add slash
let's add the input from our add slash components UI input which is a
components UI input which is a self-closing tag so there we go so
self-closing tag so there we go so import input from add slash components
import input from add slash components UI input I'm just going to move it
UI input I'm just going to move it alongside all of my components right
alongside all of my components right here beautiful so now that we have that
here beautiful so now that we have that let's go ahead and let's give this input
let's go ahead and let's give this input some class names so I'm going to write a
some class names so I'm going to write a class name border Dash 0 outline
class name border Dash 0 outline Dash none Focus dash visible
Dash none Focus dash visible ring Dash zero Focus dash visible ring
ring Dash zero Focus dash visible ring Dash transparent like this because I
Dash transparent like this because I want it to be especially styled input I
want it to be especially styled input I don't I want it to look like the whole
don't I want it to look like the whole container is an input so it's just a bit
container is an input so it's just a bit of my style preference if you want to
of my style preference if you want to you can completely remove these class
you can completely remove these class names but then the input is clearly
names but then the input is clearly visible and I kind of don't like it so
visible and I kind of don't like it so that's why I added these class names
that's why I added these class names because I just think it looks cooler
because I just think it looks cooler like it's a magic input inside of this
like it's a magic input inside of this box great and now that we have that
box great and now that we have that input I'm gonna add a disabled prop to
input I'm gonna add a disabled prop to it and disable is going to be activated
it and disable is going to be activated when we are loading the form so we're
when we are loading the form so we're going to use this constant that we
going to use this constant that we defined right here so just pass it
defined right here so just pass it inside like that nice and for the rest
inside like that nice and for the rest let's give it a placeholder which is
let's give it a placeholder which is going to be for uh you can write
going to be for uh you can write whatever you want here but I want to
whatever you want here but I want to give it a prompt so the user knows what
give it a prompt so the user knows what to ask this AI model for example how do
to ask this AI model for example how do e how how do I calculate the radius of a
e how how do I calculate the radius of a Circle for example so that's going to be
Circle for example so that's going to be one of the prompts that the user can
one of the prompts that the user can write inside and let's go ahead and
write inside and let's go ahead and let's spread field inside which we've
let's spread field inside which we've destructured right here in the form
destructured right here in the form field so what is this spreading of the
field so what is this spreading of the field doing well if you play around and
field doing well if you play around and go through these types right here you
go through these types right here you can see that that field has on change on
can see that that field has on change on blur value name and ref so what we've
blur value name and ref so what we've done essentially is replaced manually
done essentially is replaced manually writing on change manually writing uh on
writing on change manually writing uh on blur manually writing value and all of
blur manually writing value and all of that stuff by simply spreading field and
that stuff by simply spreading field and we are trusting chat CN and react hook
we are trusting chat CN and react hook form that is going to handle it as it
form that is going to handle it as it should beautiful so very very simple and
should beautiful so very very simple and now let's go ahead and just outside of
now let's go ahead and just outside of this phone control outside of the form
this phone control outside of the form item and outside of the entire form
item and outside of the entire form field actually but still inside of the
field actually but still inside of the Native HTML form element add a new
Native HTML form element add a new component button from add slash
component button from add slash components eui button like this so make
components eui button like this so make sure you've imported that here I'm going
sure you've imported that here I'm going to move it alongside all of my imports
to move it alongside all of my imports and let's go ahead and just write
and let's go ahead and just write generate like this but we have to give
generate like this but we have to give it some Styles so I'm gonna go ahead and
it some Styles so I'm gonna go ahead and write class name here
write class name here call Dash span-12 on mobile devices and
call Dash span-12 on mobile devices and LG is going to be call Dash span-2 like
LG is going to be call Dash span-2 like that so right now it's not on large so
that so right now it's not on large so it's collapsed but if I expand a bit you
it's collapsed but if I expand a bit you can see how it looks so depending on
can see how it looks so depending on whether you are on a bit of a smaller
whether you are on a bit of a smaller device I decided to collapse it because
device I decided to collapse it because it just looks uh better and so yeah we
it just looks uh better and so yeah we kind of shared the same design for our
kind of shared the same design for our mobile and for our medium screens if you
mobile and for our medium screens if you want you can change this LG and LG here
want you can change this LG and LG here to medium but I in my experience it
to medium but I in my experience it looks better like this because there is
looks better like this because there is a chance that some of our models like
a chance that some of our models like image generation are not only going to
image generation are not only going to have an input and a button we're also
have an input and a button we're also going to have some select options so
going to have some select options so that's why it's better to just collapse
that's why it's better to just collapse everything like this immediately on the
everything like this immediately on the medium and the not on only in large
medium and the not on only in large great
great so now that we have that let's go ahead
so now that we have that let's go ahead and let's also give it a w Dash full
and let's also give it a w Dash full property just in case because we're
property just in case because we're going to need it later let's go ahead
going to need it later let's go ahead and let's give it a disabled prop of is
and let's give it a disabled prop of is loading as well beautiful so now we have
loading as well beautiful so now we have that done
that done uh and that pretty much finishes our
uh and that pretty much finishes our form so what we have to do next is
form so what we have to do next is actually create the axios call
actually create the axios call well the axis coil that is going to
well the axis coil that is going to generate something here but before we do
generate something here but before we do that let's go ahead and let's actually
that let's go ahead and let's actually prepare for what's next so outside of
prepare for what's next so outside of this form with the capital F and outside
this form with the capital F and outside of this div right here go ahead and
of this div right here go ahead and create a new div the class name
create a new div the class name space Dash y-4 and margin top 4 and for
space Dash y-4 and margin top 4 and for now all I'm going to write is messages
now all I'm going to write is messages content
content right so this is where we are going to
right so this is where we are going to render our messages once we actually
render our messages once we actually have something to load beautiful great
have something to load beautiful great great job so far
great job so far now it's time for us to add an API route
now it's time for us to add an API route which is going to connect to open Ai and
which is going to connect to open Ai and actually make this site functional so in
actually make this site functional so in order to do that what you have to do is
order to do that what you have to do is go ahead and create an account for open
go ahead and create an account for open AI so either go to open ai.com or Google
AI so either go to open ai.com or Google open AI find the menu and click on login
open AI find the menu and click on login or sign up depending on whether you have
or sign up depending on whether you have an account or not so I already have an
an account or not so I already have an account so I'm going to use my Google
account so I'm going to use my Google email right here and then I'm prompted
email right here and then I'm prompted with these three options go ahead and
with these three options go ahead and click on API like this and you should
click on API like this and you should see an API platform just like this if
see an API platform just like this if this is your first ever time using open
this is your first ever time using open AI that means so if you had to register
AI that means so if you had to register for this that means you have a free tier
for this that means you have a free tier and you don't need to add your credit
and you don't need to add your credit card to use this and you can check that
card to use this and you can check that very quickly by clicking on personal at
very quickly by clicking on personal at the top click on manage account and
the top click on manage account and click on usage right here so you can see
click on usage right here so you can see that I don't have a free tier so I had
that I don't have a free tier so I had to pay because during the development of
to pay because during the development of this tutorial I intensively used open AI
this tutorial I intensively used open AI but you can see that even during my
but you can see that even during my three weeks of using open Ai and
three weeks of using open Ai and rigorous testing I barely spend five
rigorous testing I barely spend five dollars so it's not that expensive even
dollars so it's not that expensive even if you end up having to add your credit
if you end up having to add your credit card but if this is your first time
card but if this is your first time creating this account you are probably
creating this account you are probably going to see an entire bar grayed out
going to see an entire bar grayed out and it's probably going to say 0 out of
and it's probably going to say 0 out of five dollars that means that you have
five dollars that means that you have five dollars for free that you can use
five dollars for free that you can use without adding your credit card but you
without adding your credit card but you have to use it within the first three
have to use it within the first three months if you wait longer than that it's
months if you wait longer than that it's going to be expired and then you're
going to be expired and then you're gonna see a red line for this usage
gonna see a red line for this usage right here so what happens if you during
right here so what happens if you during this tutorial you end up needing more
this tutorial you end up needing more credits well you go ahead and click on
credits well you go ahead and click on billing right here and add a payment
billing right here and add a payment method and after you do that go ahead
method and after you do that go ahead and click on usage limits and make sure
and click on usage limits and make sure that you add a hard limit and a soft
that you add a hard limit and a soft limit so this is not going to allow you
limit so this is not going to allow you to spend more money than what you enter
to spend more money than what you enter here so right now I'm ready to spend ten
here so right now I'm ready to spend ten dollars and I'm gonna click save and you
dollars and I'm gonna click save and you can see in my usage I'm not able to
can see in my usage I'm not able to spend more than ten dollars so they do
spend more than ten dollars so they do have security measures in place for you
have security measures in place for you to not overspend but again if this is
to not overspend but again if this is your first time creating this account
your first time creating this account you most certainly have a free tier and
you most certainly have a free tier and you don't need to add a credit card so
you don't need to add a credit card so let's go ahead I'm going to zoom out a
let's go ahead I'm going to zoom out a bit and now I want you to click on
bit and now I want you to click on personal again and click on view API
personal again and click on view API keys and in here I already have one
keys and in here I already have one secret key but which I used for initial
secret key but which I used for initial project and go ahead and click on create
project and go ahead and click on create new secret key and I'm going to name
new secret key and I'm going to name this tutorial video it doesn't matter
this tutorial video it doesn't matter what you name it but what does matter is
what you name it but what does matter is that you copied this secret immediately
that you copied this secret immediately and don't close the model just yet
and don't close the model just yet instead go into your environment file
instead go into your environment file like this and add open AI underscore API
like this and add open AI underscore API underscore key and paste that key right
underscore key and paste that key right here if you accidentally did close this
here if you accidentally did close this model don't worry just click create new
model don't worry just click create new secret key again perfect so now that we
secret key again perfect so now that we have this that is actually it we no
have this that is actually it we no longer need open AI at all and we can go
longer need open AI at all and we can go back inside of our application and now
back inside of our application and now it's time for us to create an API route
it's time for us to create an API route so go ahead go into the ape app folder
so go ahead go into the ape app folder right here
right here and one more thing uh before we continue
and one more thing uh before we continue so what I want you to do is I want you
so what I want you to do is I want you to add your dot environment file to git
to add your dot environment file to git ignore that's very important so go ahead
ignore that's very important so go ahead in your git ignore file and just add
in your git ignore file and just add under this dot environment.local just
under this dot environment.local just add dot environment as well and then
add dot environment as well and then your dot environment file is not going
your dot environment file is not going to be committed to GitHub perfect now
to be committed to GitHub perfect now let's go ahead and let's go inside of
let's go ahead and let's go inside of our app folder let's go and create a new
our app folder let's go and create a new folder called API and inside create a
folder called API and inside create a new folder called conversation like that
new folder called conversation like that and inside go ahead and create a new
and inside go ahead and create a new file called route.ds like that and now
file called route.ds like that and now we have to install a package for open AI
we have to install a package for open AI so go ahead in your terminal I'm going
so go ahead in your terminal I'm going to close the app and write npm install
to close the app and write npm install open AI like this and after that I'm
open AI like this and after that I'm going to run the project again and
going to run the project again and refresh my page now let's go ahead and
refresh my page now let's go ahead and add the configuration for open AI so
add the configuration for open AI so import configure
and open AI API from open AI like this now write constant configuration
now write constant configuration foreign
foreign like that a new configuration and the
like that a new configuration and the objects are API key which is
objects are API key which is process.environment and it has to be
process.environment and it has to be this one in your open AI key like this
this one in your open AI key like this and now just write const open AI to be
and now just write const open AI to be new open AI API and pass in the
new open AI API and pass in the configuration and now we can go ahead
configuration and now we can go ahead and write in the post route so export a
and write in the post route so export a synchronous function post like this
synchronous function post like this which is going to accept a request which
which is going to accept a request which is a type of request
and go ahead and open a try and catch block like this so let's resolve the
block like this so let's resolve the error first I'm going to console log I'm
error first I'm going to console log I'm going to add a string saying
going to add a string saying conversation
conversation underscore error and I'm going to log
underscore error and I'm going to log that error so this is going to help us
that error so this is going to help us in development and then just return new
in development and then just return new next response which you can import from
next response which you can import from next slash server and just go ahead and
next slash server and just go ahead and write internal error and just pass in
write internal error and just pass in the status of 500 like that
the status of 500 like that now in try let's go ahead and check if
now in try let's go ahead and check if we are authenticated so const
we are authenticated so const user ID from out and you can import out
user ID from out and you can import out from add clerk slash next JS like that
from add clerk slash next JS like that perfect
perfect now let's go ahead and let's destructure
now let's go ahead and let's destructure the body so const body is equal to a
the body so const body is equal to a weight request.json like that and cons
weight request.json like that and cons messages are equal to body like this now
messages are equal to body like this now let's check for authentication so if
let's check for authentication so if there is no user ID in that case we are
there is no user ID in that case we are going to return new next response
unauthorized and passing the status of 401 like that
and passing the status of 401 like that after that go ahead and write if there
after that go ahead and write if there is no
is no configuration.api key
configuration.api key return new next response
return new next response open AI API key not configured
open AI API key not configured which is the status of 500 like that
which is the status of 500 like that now let's go ahead and check if we
now let's go ahead and check if we haven't passed the messages to this
haven't passed the messages to this route so if there is no messages in that
route so if there is no messages in that case return new next response
case return new next response messages are required like that with a
messages are required like that with a status of 400
like that and now just write const response and now we're going to use the
response and now we're going to use the open AI model so we're going to write a
open AI model so we're going to write a weight open AI dot create chat
weight open AI dot create chat completion we're going to choose the
completion we're going to choose the model the model we're going to use is
model the model we're going to use is GPT Dash 3.5-turbo
like that and we're gonna pass in the messages model like that and all we have
messages model like that and all we have to do in the end is return
to do in the end is return nextresponse.json
response dot data dot choices first in the array Dot message like that
the array Dot message like that beautiful so you finished an entire
beautiful so you finished an entire connection to open Ai and you checked
connection to open Ai and you checked for authentication beautiful and now we
for authentication beautiful and now we are ready to go back inside the page of
are ready to go back inside the page of our conversation and actually make that
our conversation and actually make that request so let's go ahead and let's go
request so let's go ahead and let's go back inside of our dashboard routes
back inside of our dashboard routes conversation page.vsx right here and
conversation page.vsx right here and first what I want to do is I want to
first what I want to do is I want to install a package called axios so let's
install a package called axios so let's go ahead in our terminal
go ahead in our terminal and write npm install axios like this
and write npm install axios like this and run the project again and refresh it
and run the project again and refresh it if you've shut it down and I'm just
if you've shut it down and I'm just going to import that at the top so
going to import that at the top so import axios from axis like that because
import axios from axis like that because of course we are going to use it so now
of course we are going to use it so now what I'm going to do is I'm going to
what I'm going to do is I'm going to open a try and catch block on this and
open a try and catch block on this and submit so try
submit so try and catch like this error is a type of
and catch like this error is a type of any
any like that and for now let's just log
like that and for now let's just log this error right here
this error right here and then finally what I'm going to do is
and then finally what I'm going to do is I'm going to refresh the router so all
I'm going to refresh the router so all of our server components are going to
of our server components are going to update this is going to be useful in the
update this is going to be useful in the future and I'm going to explain why when
future and I'm going to explain why when we get to that part so go ahead and add
we get to that part so go ahead and add const router to be used router from next
const router to be used router from next slash navigation so make sure is next
slash navigation so make sure is next slash navigation and not uh next slash
slash navigation and not uh next slash router and I'm just going to add it to
router and I'm just going to add it to the top like this and just make sure you
the top like this and just make sure you have the router right here and then in
have the router right here and then in finally you can use router.refresh like
finally you can use router.refresh like that
that perfect now what we want to do in our
perfect now what we want to do in our try block is we want to do some
try block is we want to do some modifications with the local messages
modifications with the local messages and we want to create a post request to
and we want to create a post request to the new API router that we just created
the new API router that we just created so let's go ahead first and let's create
so let's go ahead first and let's create a state for our messages so I'm going to
a state for our messages so I'm going to go ahead and just below the router right
go ahead and just below the router right const messages set messages like this to
const messages set messages like this to be use state which you can import from
be use state which you can import from react
react and go ahead and give it an empty array
and go ahead and give it an empty array like this but I immediately want to give
like this but I immediately want to give a type to this use state which is going
a type to this use state which is going to be chat completion
to be chat completion request
request message and it's going to be an array
message and it's going to be an array and you can import this from open AI so
and you can import this from open AI so go ahead and import
go ahead and import from open AI like this so chat
from open AI like this so chat completion request message in the use
completion request message in the use State and make sure you put an array at
State and make sure you put an array at the end of this type otherwise it's not
the end of this type otherwise it's not going to work so this is how it looks in
going to work so this is how it looks in one line you state chat completion
one line you state chat completion request message make sure it's an array
request message make sure it's an array otherwise it's not going to work and
otherwise it's not going to work and then on the empty array inside perfect
then on the empty array inside perfect so now that we have that we can go ahead
so now that we have that we can go ahead and actually
and actually start assigning some messages here so
start assigning some messages here so what I'm going to write is const user
what I'm going to write is const user message to be a type of chat completion
message to be a type of chat completion request message again it's going to be
request message again it's going to be an object
which is going to have a role which is going to be user and content is going to
going to be user and content is going to be
be values.prompt so it's going to be
values.prompt so it's going to be whatever we have written in this input
whatever we have written in this input right here that's going to be the user
right here that's going to be the user message that's what we are sending and
message that's what we are sending and then we're going to add and create an
then we're going to add and create an array of new messages so cons new
array of new messages so cons new messages is going to be an array which
messages is going to be an array which is going to use all the existing
is going to use all the existing messages which right now are empty but
messages which right now are empty but think of it that we are going to have
think of it that we are going to have many messages in this chat so we have to
many messages in this chat so we have to use all the existing message and add the
use all the existing message and add the new user message
new user message like that and now let's go ahead and
like that and now let's go ahead and let's create an API call for this so
let's create an API call for this so const response is equal to a weight
const response is equal to a weight axios which we have imported right here
axios which we have imported right here so axios dot post
so axios dot post slash API slash conversation that is
slash API slash conversation that is because in our app folder we have
because in our app folder we have created a new folder called API
created a new folder called API conversation route TS so that results to
conversation route TS so that results to slash API slash conversation and go
slash API slash conversation and go ahead and pass in an object messages to
ahead and pass in an object messages to be new messages like that perfect and
be new messages like that perfect and now that we have our response you're
now that we have our response you're going to use set messages it's going to
going to use set messages it's going to take the current message value like this
take the current message value like this open an array spread the current
open an array spread the current add the user message
add the user message and add
and add response.data like that and make sure
response.data like that and make sure you do form dot reset at the end so the
you do form dot reset at the end so the input is cleared perfect
input is cleared perfect and I just want to do a comment inside
and I just want to do a comment inside of the sketch function so I'm going to
of the sketch function so I'm going to add to do open pro model like this so
add to do open pro model like this so this is going to help us later when we
this is going to help us later when we add subscriptions that if we get a
add subscriptions that if we get a specific error we're gonna have to know
specific error we're gonna have to know that we have to trigger a premium model
that we have to trigger a premium model there we go and what we can do now is we
there we go and what we can do now is we can actually modify this messages
can actually modify this messages content right here to display our
content right here to display our messages so let's go ahead inside
messages so let's go ahead inside and let's create a new div instead of
and let's create a new div instead of this messages content so div last name
this messages content so div last name Lex flat slash call
Lex flat slash call Dash reverse
Dash reverse the
the gap-y-4 and inside what we're going to
gap-y-4 and inside what we're going to do is we're going to iterate our
do is we're going to iterate our messages so messages that map take the
messages so messages that map take the individual message and we're going to
individual message and we're going to immediately return a div which is going
immediately return a div which is going to render message dot content like this
to render message dot content like this and the key is going to be message dot
and the key is going to be message dot well whatever we want let's give it
well whatever we want let's give it content as well like this so let's see
content as well like this so let's see if this works right now it's going to be
if this works right now it's going to be very simple right now but I'm going to
very simple right now but I'm going to open my network tab so I can see if
open my network tab so I can see if everything is working correctly and if
everything is working correctly and if maybe if we are getting any errors for
maybe if we are getting any errors for example what is the radius
example what is the radius of the Sun and I'm going to click
of the Sun and I'm going to click generate and you can see that we fired
generate and you can see that we fired up an event on conversation and look at
up an event on conversation and look at this we have an answer so this is our
this we have an answer so this is our question and this is the answer the
question and this is the answer the radius of the Sun is approximately well
radius of the Sun is approximately well this many kilometers beautiful so our
this many kilometers beautiful so our open AI model is officially working
open AI model is officially working amazing amazing job look at this all
amazing amazing job look at this all that's left is to style this and to add
that's left is to style this and to add some loading States and some empty
some loading States and some empty States so let's go ahead and let's
States so let's go ahead and let's refresh and let's add the empty State
refresh and let's add the empty State first
first so what I'm going to do is I'm just
so what I'm going to do is I'm just going to expand this like this and I'm
going to expand this like this and I'm going to go inside of this div space y4
going to go inside of this div space y4 mt4 like this and just above this div
mt4 like this and just above this div which is rendering our messages what I'm
which is rendering our messages what I'm going to write is a condition which is
going to write is a condition which is going to check if there are no messages
going to check if there are no messages in here so I'm going to write messages
in here so I'm going to write messages that length is equal to 0 and if we are
that length is equal to 0 and if we are not loading so if it's not loading and
not loading so if it's not loading and in that case go ahead and render a div
in that case go ahead and render a div which is going to say empty like this
which is going to say empty like this let's see if that works it works right
let's see if that works it works right here so the messages are empty and we
here so the messages are empty and we are not loading meaning that it's going
are not loading meaning that it's going to display empty but instead of
to display empty but instead of rendering empty what I actually want to
rendering empty what I actually want to render is a component called empty like
render is a component called empty like this so go ahead and save this and of
this so go ahead and save this and of course we get an error because we don't
course we get an error because we don't have that component so let's go ahead
have that component so let's go ahead let's go in our components and create a
let's go in our components and create a new file empty.vsx like this I'm going
new file empty.vsx like this I'm going to go ahead and quickly create an empty
to go ahead and quickly create an empty component but I'm not gonna do export
component but I'm not gonna do export default I'm just going to do export
default I'm just going to do export const empty like this and inside I'm
const empty like this and inside I'm going to create a div saying empty
going to create a div saying empty component like that and then we can go
component like that and then we can go back inside of this page and import that
back inside of this page and import that component from add slash components
component from add slash components empty so just make sure you have
empty so just make sure you have imported it right here and you
imported it right here and you restructure the import because we didn't
restructure the import because we didn't export const and if you save there we go
export const and if you save there we go now it says empty component perfect and
now it says empty component perfect and I just want to move this react import
I just want to move this react import all the way to the top like this there
all the way to the top like this there we go let's go back inside of our
we go let's go back inside of our empty.tsx and let's add an interface for
empty.tsx and let's add an interface for it
it so interface empty props
so interface empty props label is string
label is string like that let's go ahead and instructure
like that let's go ahead and instructure the label and let's give it the props
the label and let's give it the props empty props like that now let's remove
empty props like that now let's remove this and let's give this a class name of
this and let's give this a class name of H dash full e-20 Flex Flex stash call
H dash full e-20 Flex Flex stash call items Dash Center and justify Dash
items Dash Center and justify Dash Center like that
Center like that inside I'm going to go ahead and open
inside I'm going to go ahead and open another div with a class name of
another div with a class name of relative
relative h-72 and w-72 as well and inside I'm
h-72 and w-72 as well and inside I'm going to render an image component from
going to render an image component from next slash image so make sure
next slash image so make sure that you give it an out of empty a fill
that you give it an out of empty a fill property and a source of Slash mt.png
property and a source of Slash mt.png like that and if you refresh of course
like that and if you refresh of course we have a broken image because this
we have a broken image because this image does not exist in our project so
image does not exist in our project so obviously we have to add something to
obviously we have to add something to our public folder right here so if you
our public folder right here so if you want to you can find any uh image you
want to you can find any uh image you like or you can go inside of my
like or you can go inside of my repository right here and go into the
repository right here and go into the public folder and find the image called
public folder and find the image called mt.png right click save the image and
mt.png right click save the image and drag and drop that into the public
drag and drop that into the public folder and make sure it's named
folder and make sure it's named empty.png and now if I refresh right
empty.png and now if I refresh right here there we go you can see that I have
here there we go you can see that I have a nice looking empty State now
a nice looking empty State now one more thing we have to add to this
one more thing we have to add to this empty component is to render the actual
empty component is to render the actual label so go outside of the div rendering
label so go outside of the div rendering the image and add a paragraph label like
the image and add a paragraph label like that and let's just go ahead and add a
that and let's just go ahead and add a class name text Dash muted Dash
class name text Dash muted Dash foreground
foreground text SM and text Dash is center now
text SM and text Dash is center now nothing is rendering that is because in
nothing is rendering that is because in our app folder dashboard routes
our app folder dashboard routes conversation page we did not add a label
conversation page we did not add a label to this component so go ahead and add a
to this component so go ahead and add a label here and we're gonna say
label here and we're gonna say understand sorry no conversation started
understand sorry no conversation started like this there we go now you can see
like this there we go now you can see how nicely this looks perfect now I want
how nicely this looks perfect now I want to create another component and that is
to create another component and that is for the loading state so I'm going to go
for the loading state so I'm going to go ahead and create another conditional
ahead and create another conditional Above This messages saying is loading
Above This messages saying is loading and end I'm going to open parenthesis
and end I'm going to open parenthesis I'm going to open a div with a class
I'm going to open a div with a class name
name b-8 rounded LG W Dash full Flex slash
b-8 rounded LG W Dash full Flex slash sorry Flex item slash Center justify
sorry Flex item slash Center justify Dash Center and DG Dash muted like this
Dash Center and DG Dash muted like this and inside I'm going to render the
and inside I'm going to render the loader component and of course we're
loader component and of course we're going to get an error if we refresh
going to get an error if we refresh uh because loader does not exist oh I'm
uh because loader does not exist oh I'm not getting an error probably because
not getting an error probably because this is not the loading state right now
this is not the loading state right now but let's go ahead and let's create that
but let's go ahead and let's create that component so components
component so components loader.tsx go ahead and write export
loader.tsx go ahead and write export const loader like this
const loader like this and return a div saying loading like
and return a div saying loading like that go back into page and import the
that go back into page and import the loader from add slash components slash
loader from add slash components slash loader so the same way you did with
loader so the same way you did with empty like this and now you should have
empty like this and now you should have no errors at all let's go back inside of
no errors at all let's go back inside of this loader component and let's add some
this loader component and let's add some class names to this div so class name is
class names to this div so class name is going to be H dash full Flex Flex Dash
going to be H dash full Flex Flex Dash call gak Dash y-4 items Dash Center
call gak Dash y-4 items Dash Center justify Dash Center like that and inside
justify Dash Center like that and inside open a div with a class name
w10h10 relative and animate Dash spin like that and inside we're going to use
like that and inside we're going to use an image from next slash image
an image from next slash image give it an out of logo
give it an out of logo give it a property fill and give it a
give it a property fill and give it a property source to be logo dot PNG like
property source to be logo dot PNG like that and below this div which is
that and below this div which is wrapping our image add a paragraph
wrapping our image add a paragraph saying genius is thinking and three dots
saying genius is thinking and three dots and give it a class name of text SM text
and give it a class name of text SM text muted Dash foreground like this perfect
muted Dash foreground like this perfect and now let's go inside of our page.tsx
and now let's go inside of our page.tsx and let's manually trigger the loading
and let's manually trigger the loading so I'm going to change this I'm just
so I'm going to change this I'm just gonna change this is loading to true so
gonna change this is loading to true so you can see how this looks there we go
you can see how this looks there we go you can see how our loader is now
you can see how our loader is now looking so just make sure that you have
looking so just make sure that you have this exact code although if it's not
this exact code although if it's not looking like this for you beautiful and
looking like this for you beautiful and just bring this back there is loading
just bring this back there is loading like that
like that nice and now what we have to do is we
nice and now what we have to do is we have to find a way to render these
have to find a way to render these messages in a nicer way so let's go
messages in a nicer way so let's go ahead and let's change this so I'm gonna
ahead and let's change this so I'm gonna add keep the key here like that but I'm
add keep the key here like that but I'm just going to collapse it because we're
just going to collapse it because we're going to have some more stuff here and
going to have some more stuff here and inside go ahead and write class name
inside go ahead and write class name it's going to be dynamic and we're going
it's going to be dynamic and we're going to use CN from atlibs utils so make sure
to use CN from atlibs utils so make sure you import CN from ad-lib utils like
you import CN from ad-lib utils like this
this open parenthesis inside
open parenthesis inside and our first class the default class is
and our first class the default class is going to be p-8 W Dash full Flex items
going to be p-8 W Dash full Flex items Dash start Gap Dash x-8 and rounded Dash
Dash start Gap Dash x-8 and rounded Dash LG like that and then our Dynamic class
LG like that and then our Dynamic class name is going to be different depending
name is going to be different depending on whether this is our message or the
on whether this is our message or the message from the AI so message that the
message from the AI so message that the role is identical to user in that case
role is identical to user in that case we're going to use BG Dash white border
we're going to use BG Dash white border and Border Dash black
and Border Dash black slash 10 like this else we're going to
slash 10 like this else we're going to use BG Dash muted like that there we go
use BG Dash muted like that there we go and now what I want to do is I want to
and now what I want to do is I want to create two more components user Avatar
create two more components user Avatar and what Avatar components so let's go
and what Avatar components so let's go ahead
ahead and let's go inside of our components
and let's go inside of our components again and create a new file called user
again and create a new file called user Dash
Dash avatar.vsx I'm gonna go ahead and write
avatar.vsx I'm gonna go ahead and write expert cons user Avatar like this
expert cons user Avatar like this and I'm gonna extract the user from use
and I'm gonna extract the user from use user using clerk like this and I'm going
user using clerk like this and I'm going to return and now we have to add the
to return and now we have to add the Avatar component from chat CN so let's
Avatar component from chat CN so let's go to chat CN right here
go to chat CN right here let's go inside of components and let's
let's go inside of components and let's find the Avatar component right here so
find the Avatar component right here so this is the one we want let's go ahead
this is the one we want let's go ahead and copy this I'm gonna go inside of my
and copy this I'm gonna go inside of my terminal
terminal and this is the command we're going to
and this is the command we're going to use npx chat cn-ui at latest add Avatar
use npx chat cn-ui at latest add Avatar like that go ahead and confirm the
like that go ahead and confirm the installation and once it's done run the
installation and once it's done run the project again
project again make sure you refresh your application
make sure you refresh your application and now you can freely add avatar from
and now you can freely add avatar from dot slash UI Avatar or from slash
dot slash UI Avatar or from slash components out there so I like to use it
components out there so I like to use it in this way there we go go ahead and
in this way there we go go ahead and give this a class name of h-8 and w-8 go
give this a class name of h-8 and w-8 go ahead and add another image
ahead and add another image also imported from s slash components or
also imported from s slash components or dot slash UI Avatar like this
dot slash UI Avatar like this and the source is going to be user
and the source is going to be user question mark dot profile image URL like
question mark dot profile image URL like that
that below that use the Avatar fallback so if
below that use the Avatar fallback so if an image well isn't able to load so I'm
an image well isn't able to load so I'm just going to structure this
just going to structure this like this so you can see all the
like this so you can see all the components we need we're going to use
components we need we're going to use the Avatar feed Avatar fallback in case
the Avatar feed Avatar fallback in case the image wasn't able to load so I'm
the image wasn't able to load so I'm going to write user question mark first
going to write user question mark first name question mark Char at zero and I'm
name question mark Char at zero and I'm going to repeat that for the last name
going to repeat that for the last name like this so in case my image can't load
like this so in case my image can't load I'm just going to use my first first
I'm just going to use my first first letter of my first name and first letter
letter of my first name and first letter of my last name because that's what most
of my last name because that's what most commonly that's the most common way of
commonly that's the most common way of fallback perfect and now that we have
fallback perfect and now that we have that let's also create a bot Avatar so
that let's also create a bot Avatar so go ahead and create a new component
go ahead and create a new component called bot-avatar dot DSX export const
called bot-avatar dot DSX export const bot Avatar like this it's going to be
bot Avatar like this it's going to be much simpler so just return avatar from
much simpler so just return avatar from UI Avatar or
UI Avatar or components other like I prefer it like
components other like I prefer it like this let's go ahead and give this a
this let's go ahead and give this a class name of h-8 and W Dash 8 and
class name of h-8 and W Dash 8 and Avatar image
Avatar image from components UI Avatar like that give
from components UI Avatar like that give it a class name of p-1 and the source of
it a class name of p-1 and the source of Slash logo dot PNG so we already have
Slash logo dot PNG so we already have that image because it's in our sidebar
that image because it's in our sidebar and in our loading component perfect so
and in our loading component perfect so we have those two now and we can now
we have those two now and we can now focus on building uh the messages design
focus on building uh the messages design here so what I want to do besides
here so what I want to do besides rendering the message content and this
rendering the message content and this div which we created right here is
div which we created right here is decide whether to render the user Avatar
decide whether to render the user Avatar or bot Avatar so besides along above the
or bot Avatar so besides along above the message content I'm going to write
message content I'm going to write message.roll is user in that case we're
message.roll is user in that case we're going to render user avatar from add
going to render user avatar from add slash components user Avatar so make
slash components user Avatar so make sure you've imported that and otherwise
sure you've imported that and otherwise I'm gonna render the bot Avatar like
I'm gonna render the bot Avatar like this perfect so I'm going to expand this
this perfect so I'm going to expand this you can see it in one line so make sure
you can see it in one line so make sure you have user Avatar and what Avatar
you have user Avatar and what Avatar imported like this
imported like this let's go to the bottom and one more
let's go to the bottom and one more thing we have to do is I want to wrap
thing we have to do is I want to wrap this message content inside a paragraph
this message content inside a paragraph like this and give this paragraph a
like this and give this paragraph a class name of text SM like that and
class name of text SM like that and let's see how our messages look now so
let's see how our messages look now so I'm gonna go ahead and say what is the
I'm gonna go ahead and say what is the radius of the Earth for example and
radius of the Earth for example and there we go genius is thinking and you
there we go genius is thinking and you can see that he could you saw how for a
can see that he could you saw how for a second it used the fallback and then it
second it used the fallback and then it uh loaded my image and here we have the
uh loaded my image and here we have the answer absolutely amazing you have your
answer absolutely amazing you have your first ever working AI model you can ask
first ever working AI model you can ask it whatever you want for example what
it whatever you want for example what are the best Technologies to build a web
are the best Technologies to build a web app in 2020 for example and genius is
app in 2020 for example and genius is now thinking and it's gonna give us an
now thinking and it's gonna give us an answer in a couple of seconds let's see
answer in a couple of seconds let's see what he's going to come up with
there we go look at this say tells us exactly what are the newest libraries
exactly what are the newest libraries and everything great great job you
and everything great great job you successfully finished the conversation
successfully finished the conversation model is available on mobile it's
model is available on mobile it's available on desktop it's fully styled
available on desktop it's fully styled and you're using open AI beautiful
and you're using open AI beautiful amazing amazing job
amazing amazing job the next AI model I want to create is
the next AI model I want to create is code generation because it's very
code generation because it's very similar to this conversation that we
similar to this conversation that we have right now and it also uses open AI
have right now and it also uses open AI so let's go ahead and I'm going to close
so let's go ahead and I'm going to close everything I'm going to go into the app
everything I'm going to go into the app folder dashboard routes and I'm going to
folder dashboard routes and I'm going to copy the conversation and I'm going to
copy the conversation and I'm going to paste it inside routes so now you're
paste it inside routes so now you're going to have conversation and
going to have conversation and conversation copy like this let me just
conversation copy like this let me just expand this there we go and rename the
expand this there we go and rename the conversation copy to code like that so
conversation copy to code like that so now if you click on code generation or
now if you click on code generation or go to slash code you're going to see the
go to slash code you're going to see the exact same thing as conversation so
exact same thing as conversation so let's slowly go ahead and change it so
let's slowly go ahead and change it so that it fits our design for code first I
that it fits our design for code first I want to change the cons conversation
want to change the cons conversation page and the export default to be code
page and the export default to be code page instead of conversation page so I'm
page instead of conversation page so I'm going to select the two and write code
going to select the two and write code page like that perfect so nothing should
page like that perfect so nothing should change right now but we are writing
change right now but we are writing proper code inside most of the stuff can
proper code inside most of the stuff can actually stay this same in here but one
actually stay this same in here but one thing we're going to change of course is
thing we're going to change of course is the API and the design so let's start
the API and the design so let's start with the design first because I think
with the design first because I think it's much simpler to do that okay so
it's much simpler to do that okay so inside of this heading let's change this
inside of this heading let's change this to code generation
to code generation like this make sure you are on slash
like this make sure you are on slash code like this make sure you're not
code like this make sure you're not accidentally editing the conversation so
accidentally editing the conversation so this should stay the same but code
this should stay the same but code generation should now say code
generation should now say code generation on API sorry on slash code
generation on API sorry on slash code like this
like this and the description is going to be
and the description is going to be generate
generate code using descriptive text like that
code using descriptive text like that and the icon is going to be code from
and the icon is going to be code from Lucid react so now let's go ahead and
Lucid react so now let's go ahead and let's just remove the message Square
let's just remove the message Square import because we don't need that now uh
import because we don't need that now uh great so we have that now and now let's
great so we have that now and now let's change the colors so instead of violet
change the colors so instead of violet it's going to be green and instead of
it's going to be green and instead of 500 it's going to be 700 like that
500 it's going to be 700 like that perfect so now it matches what we have
perfect so now it matches what we have on our dashboard right here and I can
on our dashboard right here and I can also click here and it should lead me to
also click here and it should lead me to the exact same route if it's not make
the exact same route if it's not make sure to check the tools constant inside
sure to check the tools constant inside dashboard and make sure that the href is
dashboard and make sure that the href is correct it should be slash code the same
correct it should be slash code the same as in the sidebar beautiful so we now
as in the sidebar beautiful so we now have that let's go ahead and let's
have that let's go ahead and let's change the placeholder of the input
change the placeholder of the input instead of asking us how do I calculate
instead of asking us how do I calculate the radius of a circle let's give this a
the radius of a circle let's give this a more descriptive prompt to what the user
more descriptive prompt to what the user could actually type in here we're going
could actually type in here we're going to go ahead and write right simple
to go ahead and write right simple toggle button using react hooks like
toggle button using react hooks like this so that's something more realistic
this so that's something more realistic to what the user would write in code
to what the user would write in code generation AI model beautiful so now
generation AI model beautiful so now that we have that what I want to do is I
that we have that what I want to do is I want to edit the API so instead of going
want to edit the API so instead of going to slash API slash conversation in the
to slash API slash conversation in the on submit function inside of course the
on submit function inside of course the code page we're going to change it to
code page we're going to change it to slash code like this this of course
slash code like this this of course right now does not exist so let's go
right now does not exist so let's go ahead and let's create that we're going
ahead and let's create that we're going to go inside the app folder inside API
to go inside the app folder inside API we're going to copy the conversation
we're going to copy the conversation paste it rename the new one to code like
paste it rename the new one to code like this and inside route.ds let's go ahead
this and inside route.ds let's go ahead and let's see what we have to change uh
and let's see what we have to change uh to make our code generation works so
to make our code generation works so what I want to do first is I want to add
what I want to do first is I want to add a default message to this model so it
a default message to this model so it knows how to behave so I don't want it
knows how to behave so I don't want it to be a general AI assistant right now
to be a general AI assistant right now it's just an assistant right because it
it's just an assistant right because it has no messages in the beginning so we
has no messages in the beginning so we are going to add a default message
are going to add a default message to tell it how to behave in this model
to tell it how to behave in this model so let's go ahead and write const
so let's go ahead and write const instruction message which is a type of
instruction message which is a type of chat completing chat completion request
chat completing chat completion request message and let's import that from open
message and let's import that from open AI like this
AI like this it's going to be an object which has a
it's going to be an object which has a role of system
role of system like that and content is going to be
like that and content is going to be well you can play around with this you
well you can play around with this you can test what works best but I'm using
can test what works best but I'm using this prompt because it works for me this
this prompt because it works for me this does this is not set in stone you're
does this is not set in stone you're going to see what I'm talking about so
going to see what I'm talking about so I'm gonna tell it what to do so you are
I'm gonna tell it what to do so you are a code generator
a code generator like that you must answer
like that you must answer only in markdown code Snippets
only in markdown code Snippets use code comments for explanations like
use code comments for explanations like that so that is going to be the first
that so that is going to be the first message that this model is going to have
message that this model is going to have so now let's copy this instruction
so now let's copy this instruction message let's go inside the response
message let's go inside the response right here
right here and let's modify these messages to
and let's modify these messages to always take the instruction message
always take the instruction message first and then the rest of the messages
first and then the rest of the messages like that everything else can stay the
like that everything else can stay the same except this error I'm gonna write
same except this error I'm gonna write code error so it's easier for us to find
code error so it's easier for us to find that in the terminal if something goes
that in the terminal if something goes wrong so let's go ahead and let's test
wrong so let's go ahead and let's test this so I'm going to refresh this and
this so I'm going to refresh this and I'm gonna ask it one question first what
I'm gonna ask it one question first what is your purpose for example I think it
is your purpose for example I think it should it should be probably it's
should it should be probably it's probably going to be different for you
probably going to be different for you so we're working with AI here but there
so we're working with AI here but there we go you should say something in this
we go you should say something in this line my purpose as a code generator so
line my purpose as a code generator so that's why uh the reason it's saying
that's why uh the reason it's saying this is because we gave you an
this is because we gave you an instruction message first so it knows
instruction message first so it knows that it is a code generator of course
that it is a code generator of course yours is probably not going to give the
yours is probably not going to give the exact same answer but it should be
exact same answer but it should be something to indicate that it should
something to indicate that it should generate code whereas if you go to
generate code whereas if you go to conversation of course and ask what is
conversation of course and ask what is your purpose I don't think it should
your purpose I don't think it should mention code generation at all see it's
mention code generation at all see it's an AI developed by openai and its
an AI developed by openai and its purpose is to assist and provide helpful
purpose is to assist and provide helpful information but code generation is
information but code generation is obviously he obviously knows that it is
obviously he obviously knows that it is a code generator beautiful so one thing
a code generator beautiful so one thing I want to test now is simple toggle
I want to test now is simple toggle button using react hooks let's see what
button using react hooks let's see what it's going to come up with it is
it's going to come up with it is definitely going to give us some code
definitely going to give us some code but it's not going to be formatted in
but it's not going to be formatted in the way we want to what I want to do is
the way we want to what I want to do is I want to have a nice markdown see this
I want to have a nice markdown see this is very hard to read like almost
is very hard to read like almost impossible so let's go ahead and let's
impossible so let's go ahead and let's go inside the page of code generation
go inside the page of code generation so app dashboard routes code
so app dashboard routes code page.psx right here so as I said
page.psx right here so as I said everything else can stay exactly the
everything else can stay exactly the same but one thing that I want to change
same but one thing that I want to change is that I don't want to just render the
is that I don't want to just render the message content like this instead I want
message content like this instead I want to render it in react markdown so let's
to render it in react markdown so let's go ahead in our terminal and let's
go ahead in our terminal and let's install a package called npm install
install a package called npm install react Dash markdown like that and after
react Dash markdown like that and after that has been installed you can go ahead
that has been installed you can go ahead and npm run Dev your project again and
and npm run Dev your project again and make sure to refresh perfect now let's
make sure to refresh perfect now let's import that so I'm going to import react
import that so I'm going to import react markdown
from react Dash markdown like that perfect and now I'm gonna go and find my
perfect and now I'm gonna go and find my message dot content and I'm going to
message dot content and I'm going to modify it so let's go ahead and let's
modify it so let's go ahead and let's remove this for now and instead I'm
remove this for now and instead I'm going to write react markdown like this
going to write react markdown like this and inside just go ahead and render
and inside just go ahead and render message.content pipe pipe empty array
message.content pipe pipe empty array like this and let's see if that has
like this and let's see if that has improved anything so simple toggle
improved anything so simple toggle button using react hooks let's see if
button using react hooks let's see if that has changed how our code looks now
that has changed how our code looks now there we go okay so we are getting
there we go okay so we are getting somewhere but obviously it's still not
somewhere but obviously it's still not perfect but it's at least structured to
perfect but it's at least structured to some way so let's see how we can improve
some way so let's see how we can improve it I'm gonna go back to react markdown
it I'm gonna go back to react markdown here and let's see if we can give it
here and let's see if we can give it some class names some components
some class names some components anything to make it look a bit better
anything to make it look a bit better and I suggest that you don't refresh
and I suggest that you don't refresh this so you can see the active changes
this so you can see the active changes while you're developing let's go ahead
while you're developing let's go ahead and give it a prop components and inside
and give it a prop components and inside open another object first component I
open another object first component I want to edit is the pre-tag because
want to edit is the pre-tag because that's what it's using to render out
that's what it's using to render out code so we're going to edit that element
code so we're going to edit that element to the way we like it so go ahead and
to the way we like it so go ahead and open an arrow function and immediately
open an arrow function and immediately destruct your node and the rest of the
destruct your node and the rest of the props like this go ahead and open an
props like this go ahead and open an arrow function and render a div inside
arrow function and render a div inside so div like this give it a class name of
so div like this give it a class name of overflow Dash Auto W full margin top and
overflow Dash Auto W full margin top and bottom to two BG Dash Black slash 10 p-2
bottom to two BG Dash Black slash 10 p-2 and rounded Dash LG
and rounded Dash LG and inside render the pre-tag
and inside render the pre-tag and spread the props and it is a
and spread the props and it is a self-closing tag like this there we go
self-closing tag like this there we go now it looks a little bit better let's
now it looks a little bit better let's see if we can improve it even more
see if we can improve it even more I'm gonna go ahead and edit another uh
I'm gonna go ahead and edit another uh element inside called code and I'm going
element inside called code and I'm going to do the same thing I'm going to
to do the same thing I'm going to destruct your node and I'm going to
destruct your node and I'm going to spread the props and I'm going to return
spread the props and I'm going to return the code element
the code element which is a self-closing tag I'm going to
which is a self-closing tag I'm going to give it the class name of bg-black Slash
give it the class name of bg-black Slash 10 rounded LG and padding of one and
10 rounded LG and padding of one and don't forget you have to spread the
don't forget you have to spread the props inside like this so I'm just going
props inside like this so I'm just going to expand this so you can see there we
to expand this so you can see there we go so you can see how now even our
go so you can see how now even our little codes Snippets have a specific
little codes Snippets have a specific color beautiful I'm just going to
color beautiful I'm just going to collapse this so you can see better and
collapse this so you can see better and now what I want to do is I want to add
now what I want to do is I want to add so outside of this components prop to
so outside of this components prop to the react markdown component add a new
the react markdown component add a new Prop class name
Prop class name and in here let's give it a text SM
and in here let's give it a text SM overflow Dash hidden and leading dash 7
overflow Dash hidden and leading dash 7 like this there we go now it looks much
like this there we go now it looks much much better perfect look at this
much better perfect look at this absolutely amazing let's let's ask it
absolutely amazing let's let's ask it something else for example a model using
something else for example a model using react Hooks and Tailwind like this let's
react Hooks and Tailwind like this let's see what it's going to come up with and
see what it's going to come up with and how it's going to look like
how it's going to look like there we go look at this I think this is
there we go look at this I think this is absolutely amazing you can see how we
absolutely amazing you can see how we have an overflow in our code snippet but
have an overflow in our code snippet but we can scroll that without affecting the
we can scroll that without affecting the rest of the website I think this is
rest of the website I think this is really really cool and looks really
really really cool and looks really really nice the AI knows its purpose and
really nice the AI knows its purpose and it can generate nice looking code in
it can generate nice looking code in nice markdown beautiful job you just
nice markdown beautiful job you just finished code generation as well as
finished code generation as well as conversation so now we're gonna get uh
conversation so now we're gonna get uh and do a image generation because that
and do a image generation because that is the last uh model which is going to
is the last uh model which is going to use open AI the rest of our models are
use open AI the rest of our models are going to use replicate AI so that's what
going to use replicate AI so that's what I wanted to go in this direction because
I wanted to go in this direction because it's easier for us to code so next one
it's easier for us to code so next one is going to be image generation that's
is going to be image generation that's going to be a bit different
going to be a bit different let's create our image generation AI
let's create our image generation AI page so what I want to do is I'm going
page so what I want to do is I'm going to expand this I'm going to close
to expand this I'm going to close everything and the same thing I did for
everything and the same thing I did for code generation so I'm going to go and
code generation so I'm going to go and find the conversation I'm going to copy
find the conversation I'm going to copy it and paste it inside routes and I'm
it and paste it inside routes and I'm going to rename this one to image like
going to rename this one to image like that and now if you go and click on
that and now if you go and click on image generation you should see
image generation you should see conversation but not a404 and same thing
conversation but not a404 and same thing if you go from the dashboard like this
if you go from the dashboard like this so now let's go ahead and slowly modify
so now let's go ahead and slowly modify this so it looks like an actual image
this so it looks like an actual image generator so first let's rename the
generator so first let's rename the conversation page constant and the
conversation page constant and the export to image page like this and
export to image page like this and nothing should change yet we are not
nothing should change yet we are not going to work with messages and we're
going to work with messages and we're gonna have to change the default values
gonna have to change the default values but we're going to do that later first I
but we're going to do that later first I just want to change the design so it
just want to change the design so it looks like an image generator so the
looks like an image generator so the title in our heading should be image
title in our heading should be image generation like that beautiful
generation like that beautiful description should be turn your prompt
description should be turn your prompt into an image like that
into an image like that the icon should be image icon from Lucid
the icon should be image icon from Lucid react so make sure you import that and
react so make sure you import that and remove the message Square because we no
remove the message Square because we no longer need that
longer need that the colors should be pink like this
the colors should be pink like this and it should be of 700 value like that
and it should be of 700 value like that so it fits exactly what we used in the
so it fits exactly what we used in the sidebar beautiful so you can see how it
sidebar beautiful so you can see how it looks exactly the same here
looks exactly the same here and now what I want to do is I want to
and now what I want to do is I want to change the constant for my form schema
change the constant for my form schema before I start doing anything else here
before I start doing anything else here so let's go ahead and let's go inside of
so let's go ahead and let's go inside of our constants so inside of this folder
our constants so inside of this folder which we copied we also copy the
which we copied we also copy the constants file so inside what I want to
constants file so inside what I want to do is I want to change the form schema
do is I want to change the form schema to change the message prompt instead of
to change the message prompt instead of prompt is required let's change this to
prompt is required let's change this to image prompt is required and let's also
image prompt is required and let's also add an amount which is going to be Z dot
add an amount which is going to be Z dot string with a minimum value of 1 and
string with a minimum value of 1 and resolution which is also Z dot string
resolution which is also Z dot string and a minimum value of 1 like that and
and a minimum value of 1 like that and now let's create constants for options
now let's create constants for options so this image generation is going to
so this image generation is going to have two options available you'll be
have two options available you'll be able to select the number of images you
able to select the number of images you want to generate as well as the
want to generate as well as the resolution so we have to create that in
resolution so we have to create that in our uh we we just did that in our phone
our uh we we just did that in our phone schema but now I want to create an array
schema but now I want to create an array of options that users will be able to
of options that users will be able to choose from so let's go ahead and let's
choose from so let's go ahead and let's write export const amount options like
write export const amount options like this it's going to be an array of
this it's going to be an array of objects value for the first one is going
objects value for the first one is going to be 1 and label is going to be one
to be 1 and label is going to be one photo like that let's go ahead and let's
photo like that let's go ahead and let's copy that and don't forget to add a
copy that and don't forget to add a comma and the second one is going to be
comma and the second one is going to be 2 and of course photos like that and
2 and of course photos like that and we're going to copy that a couple of
we're going to copy that a couple of more times until we reach five so let me
more times until we reach five so let me just remove the extra comma let's change
just remove the extra comma let's change this to five like that there are of
this to five like that there are of course smarter ways to do this but
course smarter ways to do this but sometimes simple is uh better so I just
sometimes simple is uh better so I just change this to five I don't know why I
change this to five I don't know why I meant on three and here I meant on four
meant on three and here I meant on four and the last one is going to be five
and the last one is going to be five like that so just modify this to five
like that so just modify this to five photos and the same way we did this I
photos and the same way we did this I will want to do our resolution options
will want to do our resolution options so let's go ahead and write expert const
so let's go ahead and write expert const resolution options like that
resolution options like that first object inside is going to have a
first object inside is going to have a value of 256 times 256 and it's going to
value of 256 times 256 and it's going to have the very same label
go ahead and copy this and the second one is going to have a
and the second one is going to have a value not of 256 but of 512.
and the last one is going to have 2020 or so 2024 like this there we go so
2020 or so 2024 like this there we go so we just created in the options that
we just created in the options that users will be able to choose from when
users will be able to choose from when creating their images and now we can go
creating their images and now we can go back inside of our image page right here
back inside of our image page right here and let's slowly start modifying things
and let's slowly start modifying things so first thing I want to remove is this
so first thing I want to remove is this images is the messages we're not going
images is the messages we're not going to have that here and we can also
to have that here and we can also actually remove the chat completion
actually remove the chat completion request message from open AI we are not
request message from open AI we are not going to need that great I'm going to
going to need that great I'm going to modify this on submit right here so I'm
modify this on submit right here so I'm going to replace this I'm just going to
going to replace this I'm just going to leave the response right here and for
leave the response right here and for now let's go ahead and just do this
now let's go ahead and just do this for the set messages I'm also going to
for the set messages I'm also going to remove it like this
remove it like this great so just make sure that your own
great so just make sure that your own submit function is now much simpler and
submit function is now much simpler and of course we're going to change this to
of course we're going to change this to slash image but let's limit it to slash
slash image but let's limit it to slash conversation for now so we don't change
conversation for now so we don't change too many things at once and get confused
too many things at once and get confused so our on submit is now calling the
so our on submit is now calling the response and resetting the form that's
response and resetting the form that's it now we have some errors at the bottom
it now we have some errors at the bottom and that is of course because of uh it's
and that is of course because of uh it's looking for the message state but we
looking for the message state but we just removed it so it doesn't exist
just removed it so it doesn't exist we're going to fix that very simply so
we're going to fix that very simply so we're not going to remove this but what
we're not going to remove this but what I do want to remove is this I'm going to
I do want to remove is this I'm going to remove this entire div iterating over
remove this entire div iterating over our messages so select this remove it
our messages so select this remove it create a new div and just write images
create a new div and just write images will be
will be rendered here like that and of course we
rendered here like that and of course we still have the error because messages is
still have the error because messages is not defined instead of messages we're
not defined instead of messages we're going to use images so let's go ahead
going to use images so let's go ahead and let's create a constant images set
and let's create a constant images set images like this new state
images like this new state and an empty array inside and the type
and an empty array inside and the type of this state is going to be an array of
of this state is going to be an array of strings like this
strings like this so now we have the images to work with
so now we have the images to work with so now let's go back here and let's
so now let's go back here and let's change this to be images.length like
change this to be images.length like that and let's immediately change this
that and let's immediately change this to no images generated like that there
to no images generated like that there we go
we go I also want to modify the loader just a
I also want to modify the loader just a little bit so I'm going to remove this
little bit so I'm going to remove this huge class name we have for the
huge class name we have for the container holding the loader and I'm
container holding the loader and I'm going to replace it with just p-20 like
going to replace it with just p-20 like that so let's check how that looks like
that so let's check how that looks like there we go that looks fine now let's go
there we go that looks fine now let's go ahead and let's change our form schema
ahead and let's change our form schema right here sorry not the form schema but
right here sorry not the form schema but are the default values in our use form
are the default values in our use form hook right here so instead of just
hook right here so instead of just having a prompt it's also going to have
having a prompt it's also going to have amount and this amount is going to be by
amount and this amount is going to be by default just one image and resolution
default just one image and resolution well you can choose what you want but
well you can choose what you want but I'm going to choose 512 like this
I'm going to choose 512 like this beautiful and now that we have that we
beautiful and now that we have that we can go ahead and actually modify our on
can go ahead and actually modify our on submit function here so what I want to
submit function here so what I want to do first is I want to reset all the
do first is I want to reset all the photos every time we click submit so
photos every time we click submit so const set images
const set images and the array like that
and the array like that uh actually not constant just set images
uh actually not constant just set images my apologies great and now what we're
my apologies great and now what we're going to do is we're going to get this
going to do is we're going to get this response but not from slash API
response but not from slash API conversation instead we're going to get
conversation instead we're going to get it from slash API slash image and the
it from slash API slash image and the body we are getting the best inside is
body we are getting the best inside is going to be values so we don't have to
going to be values so we don't have to modify values in any way it's find the
modify values in any way it's find the way it's passed from the on submit prop
way it's passed from the on submit prop right here in our conversation page we
right here in our conversation page we had to modify the values to create a
had to modify the values to create a specific message object which fits the
specific message object which fits the openai schema but this is going to be
openai schema but this is going to be just fine because we're going to modify
just fine because we're going to modify it on the server because the structure
it on the server because the structure is simply that way that we can do that
is simply that way that we can do that great and we're going to prepare the way
great and we're going to prepare the way our response is going to work so I'm
our response is going to work so I'm going to write const urls
going to write const urls response.data.map
you're going to get the individual image which is going to be a type of object
which is going to be a type of object which has URL inside and that is a type
which has URL inside and that is a type of string
of string and all I'm going to do is I'm going to
and all I'm going to do is I'm going to extract image.url from that specific
extract image.url from that specific image we are iterating over so we are
image we are iterating over so we are creating an array going through this
creating an array going through this respond those data and we're just going
respond those data and we're just going to return the URL string that is because
to return the URL string that is because our set images State expects an array of
our set images State expects an array of strings so we extract the URL from each
strings so we extract the URL from each individual image in the array that we
individual image in the array that we are going to get from the axios and we
are going to get from the axios and we set it in that state actually we don't
set it in that state actually we don't yet set it we just created the URLs so
yet set it we just created the URLs so just uh after the form reset before form
just uh after the form reset before form reset let's do a set images URLs like
reset let's do a set images URLs like that great so now that we have that we
that great so now that we have that we can actually go ahead and create our
can actually go ahead and create our image route my apologies we cannot do
image route my apologies we cannot do that yet what we actually have to do is
that yet what we actually have to do is we have to add the options to select our
we have to add the options to select our Fields right here so let's go ahead and
Fields right here so let's go ahead and do that go ahead and find your form
do that go ahead and find your form and let's first change the placeholder
and let's first change the placeholder here so instead of asking how to
here so instead of asking how to calculate the radius of a circle let's
calculate the radius of a circle let's ask a picture
ask a picture of a horse in Swiss Alps like this so
of a horse in Swiss Alps like this so that's a more realistic prompt that the
that's a more realistic prompt that the user would ask great and now let's go
user would ask great and now let's go ahead and let's create another form
ahead and let's create another form field that is going to be besides this
field that is going to be besides this input so form field again which is a
input so form field again which is a self-closing tab
self-closing tab let's go ahead and give it a name of
let's go ahead and give it a name of amount
amount and let's give it a property control
and let's give it a property control to be form dot control so this one is
to be form dot control so this one is going to be a little bit different
going to be a little bit different because this time it's going to be a
because this time it's going to be a select input so that's why I'm adding
select input so that's why I'm adding control separately
control separately now let's add the render field
now let's add the render field go ahead and extract yield in this Arrow
go ahead and extract yield in this Arrow function
function and return form item component which we
and return form item component which we already have
already have let's go ahead and give it a class name
let's go ahead and give it a class name of call Dash span-12
of call Dash span-12 and on LG it's going to be call Dash
and on LG it's going to be call Dash span Dash 2 like that
span Dash 2 like that great inside of that let's go ahead and
great inside of that let's go ahead and add the select component the problem is
add the select component the problem is we don't have it so go in chat c and UI
we don't have it so go in chat c and UI of course and find the select component
of course and find the select component and it's right here there we go and now
and it's right here there we go and now let's find the CLI command so npx chat
let's find the CLI command so npx chat CN Dash UI latest ad select I'm going to
CN Dash UI latest ad select I'm going to copy the npm I'm gonna go inside of my
copy the npm I'm gonna go inside of my terminal like this and I'm gonna pass
terminal like this and I'm gonna pass the command so npx chat cnui at latest
the command so npx chat cnui at latest add select and I'm going to confirm the
add select and I'm going to confirm the installation and after that I'm going to
installation and after that I'm going to go ahead and run my project again
so just write npm run Dev again and refresh your application
refresh your application there we go and now we can safely add
there we go and now we can safely add the select component inside so I'm going
the select component inside so I'm going to add select like this from add slash
to add select like this from add slash components UI select
components UI select so let's see how that looks like so I've
so let's see how that looks like so I've added it right here select from s slash
added it right here select from s slash components UI select so let's move this
components UI select so let's move this well you can keep it here but just make
well you can keep it here but just make sure it's alongside this Imports and
sure it's alongside this Imports and yeah you can remove the user Avatar and
yeah you can remove the user Avatar and the bot Avatar we don't need that and
the bot Avatar we don't need that and I'm pretty sure we are going to need CN
I'm pretty sure we are going to need CN I'm going to leave it just in case great
I'm going to leave it just in case great now let's go ahead and let's continue
now let's go ahead and let's continue developing this select component right
developing this select component right here so let's give it some attributes
here so let's give it some attributes he's going to have a prop disabled to be
he's going to have a prop disabled to be triggered when we are loading like that
triggered when we are loading like that on value change is going to be field dot
on value change is going to be field dot on change
on change value is going to be field
value is going to be field value
value and default value
and default value is going to be field dot value as well
is going to be field dot value as well like that
like that now let's add a deform control form
now let's add a deform control form control like this
control like this he's not going to have any attributes at
he's not going to have any attributes at all now let's add the select trigger
all now let's add the select trigger component from add slash components UI
component from add slash components UI select so make sure you have imported
select so make sure you have imported select trigger and select from
select trigger and select from components UI select
components UI select inside of Select trigger go ahead and
inside of Select trigger go ahead and add select the value another component
add select the value another component you're going to import from add slash
you're going to import from add slash components UI select so make sure you
components UI select so make sure you have that as well great and this is
have that as well great and this is actually going to be a self-closing tag
actually going to be a self-closing tag like this and just give it a default
like this and just give it a default value
value of field dot value like that
of field dot value like that outside of our form control let's go
outside of our form control let's go ahead and let's add select content from
ahead and let's add select content from s slash components UI select and inside
s slash components UI select and inside let's iterate over our amount options so
let's iterate over our amount options so amount options
amount options from constants so I've imported select
from constants so I've imported select content from components UI select as
content from components UI select as well let me just
well let me just structure this like this so you can see
structure this like this so you can see and I have imported amount options from
and I have imported amount options from the same place I'm importing form schema
the same place I'm importing form schema dot slash constants so make sure you
dot slash constants so make sure you import that as well and then go ahead
import that as well and then go ahead and map over those like this pick the
and map over those like this pick the individual option like that and
individual option like that and immediately return select item another
immediately return select item another item you are going to import from
item you are going to import from components UI select beautiful now let's
components UI select beautiful now let's go ahead and let's give it a key value
go ahead and let's give it a key value up option dot value and let's give it a
up option dot value and let's give it a value of option.value as well and inside
value of option.value as well and inside we're going to render option.label like
we're going to render option.label like that there we go you can see how now we
that there we go you can see how now we have a prompt to select how many photos
have a prompt to select how many photos we want to generate beautiful
we want to generate beautiful and let's see how that looks like on
and let's see how that looks like on desktop I think we made a mistake here
desktop I think we made a mistake here and yes so we have to change the grid
and yes so we have to change the grid for our button and for our input so
for our button and for our input so let's go ahead and play a little bit
let's go ahead and play a little bit with that to see what we have to change
with that to see what we have to change exactly so let's find the prompt first
exactly so let's find the prompt first so this is our prompt form field with
so this is our prompt form field with the name prompt currently on large
the name prompt currently on large devices it uses call span 10 and that is
devices it uses call span 10 and that is way too much because we're gonna have
way too much because we're gonna have two selects beside it and we want to be
two selects beside it and we want to be and want them all to be in the same line
and want them all to be in the same line so we have to reduce this from 10 to 6
so we have to reduce this from 10 to 6 on large devices so I think just even
on large devices so I think just even now if I Collapse there we go looks much
now if I Collapse there we go looks much better but still something is a little
better but still something is a little bit weird but let's continue developing
bit weird but let's continue developing and let's add another select option here
and let's add another select option here this time it's going to be for
this time it's going to be for resolution options so you can go ahead
resolution options so you can go ahead and copy this entire form field before
and copy this entire form field before name amount so all the way to the end of
name amount so all the way to the end of the self-closing tag go ahead and paste
the self-closing tag go ahead and paste it like this and save it and just rename
it like this and save it and just rename this to resolution like that
this to resolution like that and let's go ahead and change these
and let's go ahead and change these amount options to resolution options and
amount options to resolution options and make sure you have imported resolution
make sure you have imported resolution options from uh dot slash constants like
options from uh dot slash constants like this so I'm gonna collapse all of those
this so I'm gonna collapse all of those and save and I'm going to refresh here
and save and I'm going to refresh here and there we go now it looks much much
and there we go now it looks much much better on mobile and on desktop you can
better on mobile and on desktop you can select your resolution and you can
select your resolution and you can select the amount of photos you want
select the amount of photos you want beautiful let's see if we have to change
beautiful let's see if we have to change anything in the button or if it looks
anything in the button or if it looks fine so let's see our button is taking
fine so let's see our button is taking an LG call span of two and I think that
an LG call span of two and I think that is fine yes that can stay exactly the
is fine yes that can stay exactly the same and let's just test if this works
same and let's just test if this works so I'm going to comment this out for now
so I'm going to comment this out for now and I'm going to comment actually
and I'm going to comment actually everything besides set images you don't
everything besides set images you don't have to do this but I just want to
have to do this but I just want to console log my values
console log my values to see what we are actually getting so
to see what we are actually getting so we're going to expand this right here
we're going to expand this right here I'm going to open my tab I'm going to
I'm going to open my tab I'm going to select I'm going to write a horse in
select I'm going to write a horse in Swiss Alps I'm gonna select two photos
Swiss Alps I'm gonna select two photos and 512 and there we go we have a prompt
and 512 and there we go we have a prompt we have an amount and resolution
we have an amount and resolution everything seems to be correct let's
everything seems to be correct let's change it there we go so this is what we
change it there we go so this is what we will be sending to the server and openai
will be sending to the server and openai knows how to work with that beautiful so
knows how to work with that beautiful so I'm going to go ahead and I'm going to
I'm going to go ahead and I'm going to undo these changes right here and now
undo these changes right here and now it's time for us to create an API for
it's time for us to create an API for our image generator
our image generator let's go inside of our app folder again
find the API folder and let's just copy the conversation
the conversation and rename it to image like this go
and rename it to image like this go inside that route right here and let's
inside that route right here and let's see what we have to modify so user ID is
see what we have to modify so user ID is fine body is fine but what we are
fine body is fine but what we are destructuring from the body is not
destructuring from the body is not correct instead of messages we are going
correct instead of messages we are going to need a prompt we're going to give an
to need a prompt we're going to give an amount and let's give it a default value
amount and let's give it a default value of one we're also going to need a
of one we're also going to need a resolution and let's give that a default
resolution and let's give that a default value of 512 times 512 like that
value of 512 times 512 like that now instead of checking if we have the
now instead of checking if we have the messages let's check if we have a prompt
messages let's check if we have a prompt like this and say prompt is required
like this and say prompt is required like that and let's copy this two more
like that and let's copy this two more times
times one for amount and say amount is
one for amount and say amount is required and one for resolution and say
required and one for resolution and say resolution is required and now instead
resolution is required and now instead of using chat create chat completion
of using chat create chat completion what we are going to do is we're going
what we are going to do is we're going to use openai dot create image
to use openai dot create image like this this one does not accept model
like this this one does not accept model or messages instead it exempts a prompt
or messages instead it exempts a prompt you can write it either like this or use
you can write it either like this or use a shorthand like this
a shorthand like this a number which we have to parse so parse
a number which we have to parse so parse integer amount with a Radix of 10 like
integer amount with a Radix of 10 like this and size is a resolution like this
this and size is a resolution like this there we go and the response is now
there we go and the response is now different so we have the modified so
different so we have the modified so instead of using
instead of using response.data.choices0.message go ahead
response.data.choices0.message go ahead and return the entire data so response
and return the entire data so response dot data dot data and change the
dot data dot data and change the conversation error to image error like
conversation error to image error like this beautiful now let's go back inside
this beautiful now let's go back inside page.tsx and let's see if we can find a
page.tsx and let's see if we can find a way to Simply render our images already
way to Simply render our images already so I'm going to go ahead
so I'm going to go ahead and let's give this div a class name of
and let's give this div a class name of grid grid again Dash calls dash one
grid grid again Dash calls dash one that's going to be on mobile on medium
that's going to be on mobile on medium we're going to use grid Dash called
we're going to use grid Dash called stash 2. on large we're going to use
stash 2. on large we're going to use grid Dash calls Dash 3 on extra large
grid Dash calls Dash 3 on extra large you are going to use grid Dash calls-4
you are going to use grid Dash calls-4 and give it a gap 4 and margin top 8
and give it a gap 4 and margin top 8 like that
like that now let's go ahead and let's write
now let's go ahead and let's write images.net
images.net source
source and immediately return a card which we
and immediately return a card which we already added in chat CN so make sure
already added in chat CN so make sure you import card from components UI card
you import card from components UI card like this
head and give it some properties so it's going to have a key which is source and
going to have a key which is source and it's going to have a class name which is
it's going to have a class name which is going to be rounded LG and overflow Dash
going to be rounded LG and overflow Dash hidden
hidden inside card create a div with a class
inside card create a div with a class name of relative and aspect Dash Square
name of relative and aspect Dash Square inside of that create an image from next
inside of that create an image from next slash image
slash image so make sure you have imported
so make sure you have imported image from next slash image like I did
image from next slash image like I did right here and I'm just going to move it
right here and I'm just going to move it to the top here so image from next slash
to the top here so image from next slash image let's go all the way down back to
image let's go all the way down back to where we added an image it is a
where we added an image it is a self-closing tag let's go ahead and give
self-closing tag let's go ahead and give it an ALT property of image a Field
it an ALT property of image a Field property and source which is going to be
property and source which is going to be Source like this
Source like this beautiful and inside the card let's also
beautiful and inside the card let's also add card footer something you will also
add card footer something you will also going to import from add slash
going to import from add slash components UI card inside of this card
components UI card inside of this card folder go ahead and give it a class name
folder go ahead and give it a class name of p-2
of p-2 and inside add a button
and inside add a button which we already have imported so just
which we already have imported so just make sure you have it imported but you
make sure you have it imported but you should have it because we already use a
should have it because we already use a button in this page
button in this page like this and give this button a variant
like this and give this button a variant of secondary and the class name of w
of secondary and the class name of w Dash full like this and inside I'm going
Dash full like this and inside I'm going to render download icon from lucidreact
to render download icon from lucidreact so make sure you have imported download
so make sure you have imported download and image icon from lucidreact like this
and image icon from lucidreact like this let's go ahead and let's give it a class
let's go ahead and let's give it a class name of h-4 W-4 and margin right 2 like
name of h-4 W-4 and margin right 2 like this and let's write a text to download
this and let's write a text to download like this and I'm going to collapse
like this and I'm going to collapse these attributes in this button because
these attributes in this button because I want to add another one
I want to add another one like this and let's add on click
like this and let's add on click to Be an Arrow function window dot open
to Be an Arrow function window dot open source like that let's see if this is
source like that let's see if this is enough for us to render our images
enough for us to render our images I'm gonna go and expand this
I'm going to refresh the entire page I'm going to write a picture of a horse in
going to write a picture of a horse in Swiss Alps I'm gonna say to select four
Swiss Alps I'm gonna say to select four photos in the lowest resolution and
photos in the lowest resolution and let's see if that's gonna throw some
let's see if that's gonna throw some errors or if we did everything correctly
errors or if we did everything correctly after a couple of seconds I'm pretty
after a couple of seconds I'm pretty confident yes it actually works but
confident yes it actually works but what's going on why are we having this
what's going on why are we having this error well what's going on is that you
error well what's going on is that you cannot just load any image you want from
cannot just load any image you want from uh in xjs using the next image what we
uh in xjs using the next image what we have to do is we have to add this host
have to do is we have to add this host name so this exact host name inside of
name so this exact host name inside of our configuration so go ahead and copy
our configuration so go ahead and copy this hostname right here so you're gonna
this hostname right here so you're gonna get this error in the lead Source prop
get this error in the lead Source prop for this specific image on the next
for this specific image on the next slash image which is the component we're
slash image which is the component we're using and it says exactly what is the
using and it says exactly what is the hostname that we have to add inside of
hostname that we have to add inside of our next config and it also gives you
our next config and it also gives you instructions on how to do that so let's
instructions on how to do that so let's go ahead and let's copy this hostname
go ahead and let's copy this hostname it's a very long host name this
it's a very long host name this and let's find our
and let's find our config so I'm going to close everything
config so I'm going to close everything and find
and find next.config.js like this open this
next.config.js like this open this object and write images
object and write images domains an array and paste it inside
domains an array and paste it inside like this
like this and what I recommend actually doing is
and what I recommend actually doing is shutting down and restarting your
shutting down and restarting your application
application so NDM run that again
so NDM run that again I'm going to zoom out a bit I'm going to
I'm going to zoom out a bit I'm going to refresh
refresh and once this page loads we're gonna try
and once this page loads we're gonna try our prompt again
our prompt again let's try one more time a picture of a
let's try one more time a picture of a horse in Swiss Alps for photos lowest
horse in Swiss Alps for photos lowest resolution genius is thinking and let's
resolution genius is thinking and let's see if this is going to be a success or
see if this is going to be a success or not
not in a couple of seconds and there we go
in a couple of seconds and there we go look at this absolutely amazing we have
look at this absolutely amazing we have four images of a horse in Swiss Ops and
four images of a horse in Swiss Ops and we can also open this image individually
we can also open this image individually and download it beautiful you officially
and download it beautiful you officially know how to create your own chat GPD
know how to create your own chat GPD your own code generator and your own
your own code generator and your own image generator you're doing an amazing
image generator you're doing an amazing job so far we only have a couple of
job so far we only have a couple of models left to do so video generation
models left to do so video generation and music generation is going to be done
and music generation is going to be done using replicate Ai and after we finish
using replicate Ai and after we finish that we're going to implement stripe
that we're going to implement stripe beautiful
beautiful let's continue and let's create a music
let's continue and let's create a music generation API so we're going to go
generation API so we're going to go ahead and we're going to do what we
ahead and we're going to do what we already did a few times and that is
already did a few times and that is we're going to copy the conversation
we're going to copy the conversation right here in routes and paste it and
right here in routes and paste it and we're going to rename it to music like
we're going to rename it to music like this now if you click on music you
this now if you click on music you should see the conversation the same
should see the conversation the same thing as we did a couple of times and
thing as we did a couple of times and same thing if you go from the dashboard
same thing if you go from the dashboard so now let's go ahead inside Music
so now let's go ahead inside Music Inside page.tsx right here and let's
Inside page.tsx right here and let's slowly modify this so it fits exactly
slowly modify this so it fits exactly what we want our music page to look like
what we want our music page to look like so first things first let's modify our
so first things first let's modify our heading instead of conversation it's
heading instead of conversation it's going to be music generation
like this in the description is going to be turn
in the description is going to be turn your prompt into music like that and
your prompt into music like that and we're going to change the icon to be
we're going to change the icon to be music
music from Lucid react so make sure you import
from Lucid react so make sure you import that and remove the message Square
that and remove the message Square because we do not need that
because we do not need that number eight and the colors are not
number eight and the colors are not going to be Violet they're going to be
going to be Violet they're going to be Emerald like this
Emerald like this and 500 is correct now let's just
and 500 is correct now let's just quickly change the placeholder in our
quickly change the placeholder in our prompt form field so instead of this
prompt form field so instead of this question I'm going to write piano solo
question I'm going to write piano solo like this
like this great and what I want to already do is I
great and what I want to already do is I just want to replace this entire div
just want to replace this entire div rendering the messages so go ahead and
rendering the messages so go ahead and replace this entire div create a new one
replace this entire div create a new one and just write music will be generated
and just write music will be generated here like that and let's change this
here like that and let's change this empty label to no music
empty label to no music generated
generated like that and now what I quickly want to
like that and now what I quickly want to change here so I'm going to expand this
change here so I'm going to expand this so you can see more of my code
so you can see more of my code I want to change this messages State
I want to change this messages State it's not going to use this type so you
it's not going to use this type so you can remove this already
can remove this already and let's change the constant messages
and let's change the constant messages and set messages to be music
and set messages to be music and set music like this it's not going
and set music like this it's not going to be an array instead it's going to be
to be an array instead it's going to be just a type of string like this while we
just a type of string like this while we are here let's also remove user Avatar
are here let's also remove user Avatar both Avatar and CN from our Imports
both Avatar and CN from our Imports because we're not going to use them and
because we're not going to use them and let's rename the page from conversation
let's rename the page from conversation page to music page so make sure to
page to music page so make sure to rename the export default and the
rename the export default and the constant right here and now let's change
constant right here and now let's change our on submit so it matches our uh set
our on submit so it matches our uh set music state so we so we're not going to
music state so we so we're not going to need this at all we can remove that
need this at all we can remove that let's just go ahead and write set music
let's just go ahead and write set music on the phone every time uh we click
on the phone every time uh we click submit the response is going to be a bit
submit the response is going to be a bit different
different so you can change it like this you can
so you can change it like this you can remove this set messages for now and
remove this set messages for now and change this to instead of Slash API
change this to instead of Slash API slash conversation to slash API slash
slash conversation to slash API slash music
music music like that and just pass in the
music like that and just pass in the values and then you're gonna write set
values and then you're gonna write set music
music response.data.audio like this and reset
response.data.audio like this and reset the form
the form great and let's just see all the other
great and let's just see all the other errors we have so in here we are using
errors we have so in here we are using we are checking for messages.length so
we are checking for messages.length so let's go ahead and change that instead
let's go ahead and change that instead of checking messages length we're just
of checking messages length we're just going to change if there is no music
going to change if there is no music like this
like this there we go
there we go and now we are ready to actually create
and now we are ready to actually create the API route that's because the
the API route that's because the constants the form schema file can stay
constants the form schema file can stay the same so prompt is required if you
the same so prompt is required if you want to you can change this to music is
want to you can change this to music is required but we are actually not even
required but we are actually not even showing this prompts
showing this prompts great so our form schema is correct and
great so our form schema is correct and it can stay the same
it can stay the same and what we have to do now is we have to
and what we have to do now is we have to go ahead and copy the API for
go ahead and copy the API for conversation paste it and rename it to
conversation paste it and rename it to music
like this route the TS here and a lot of stuff is going to be changed here
stuff is going to be changed here actually because we are no longer using
actually because we are no longer using open AI for this we're going to be using
open AI for this we're going to be using replicate for this so let's go ahead and
replicate for this so let's go ahead and go to replicate.com or just Google
go to replicate.com or just Google replicate ai go ahead and find the sign
replicate ai go ahead and find the sign in button or get started and create an
in button or get started and create an account so you can go inside of your
account so you can go inside of your dashboard
and this is how my dashboard looks like because I'm already using replicate and
because I'm already using replicate and you can see I've run a lot of models
you can see I've run a lot of models here already but replicate as well as
here already but replicate as well as openai have a free tier if this is your
openai have a free tier if this is your first time using it open AI has a bit
first time using it open AI has a bit more explicit way of telling you how
more explicit way of telling you how much of a free theater you have but I'm
much of a free theater you have but I'm not sure about replicate but just be
not sure about replicate but just be careful and don't spam too much and yes
careful and don't spam too much and yes you don't need to add your credit card
you don't need to add your credit card you can start using it for free so in
you can start using it for free so in order to find your API key what you have
order to find your API key what you have to do is click on your username right
to do is click on your username right here and click on API tokens and then
here and click on API tokens and then you can go ahead and copy this and let's
you can go ahead and copy this and let's add it to our environment variable
add it to our environment variable so go back inside your code I'm going to
so go back inside your code I'm going to close everything go inside dot
close everything go inside dot environment right here and let's go
environment right here and let's go ahead and let's add replicate underscore
ahead and let's add replicate underscore API underscore token like this and just
API underscore token like this and just paste that in here beautiful and now
paste that in here beautiful and now that we have this
that we have this uh I just want to show you how to add a
uh I just want to show you how to add a limit to here as well so if you end up
limit to here as well so if you end up needing more credits and add your credit
needing more credits and add your credit card you can go into billing right here
card you can go into billing right here and you can also add a spend the limit
and you can also add a spend the limit so if you're ready to only spend ten
so if you're ready to only spend ten dollars change this to 10 and click
dollars change this to 10 and click update monthly spend limit and then you
update monthly spend limit and then you will not be charged more than that so
will not be charged more than that so you can see that in my rigorous testing
you can see that in my rigorous testing over the past few weeks of building this
over the past few weeks of building this application I barely used up seven
application I barely used up seven dollars so seven dollars in replicate
dollars so seven dollars in replicate and seven dollars on open AI so 14 in
and seven dollars on open AI so 14 in total in heavy testing of this project
total in heavy testing of this project so I'm pretty sure that you're going to
so I'm pretty sure that you're going to be able to build this entire thing on a
be able to build this entire thing on a free tier but just in case you can see
free tier but just in case you can see it's not really that expensive great so
it's not really that expensive great so now that we have that let's go back
now that we have that let's go back inside of our application and let's go
inside of our application and let's go back inside of our app folder API music
back inside of our app folder API music route.ts right here
route.ts right here and what we have to do is we have to
and what we have to do is we have to install a package for replicate so go
install a package for replicate so go inside of your terminal right here and
inside of your terminal right here and write npm install replicate like this
write npm install replicate like this wait a couple of seconds and run your
wait a couple of seconds and run your application again and restart I mean
application again and restart I mean refresh your web application great so
refresh your web application great so you can remove everything regarding open
you can remove everything regarding open AI we are not going to need it instead
AI we are not going to need it instead import replicate from replicate like
import replicate from replicate like this you can go ahead and remove this
this you can go ahead and remove this configuration and open AI constant and
configuration and open AI constant and instead write const replicate to be new
instead write const replicate to be new replicate like this alph is going to be
replicate like this alph is going to be process.environment and you're going to
process.environment and you're going to use the key from your environment
use the key from your environment variable so copy it from here and paste
variable so copy it from here and paste it here like this
it here like this you're going to have an error here
you're going to have an error here because there is a chance that it is
because there is a chance that it is undefined so you can fix that by either
undefined so you can fix that by either adding pipe pipe empty string or you can
adding pipe pipe empty string or you can put an exclamation point at the end like
put an exclamation point at the end like this
this great now let's go ahead and let's
great now let's go ahead and let's modify this API Handler so it generates
modify this API Handler so it generates music
music so what we have to change in here is
so what we have to change in here is modify the message from the
modify the message from the destructuring of the body to prompts
destructuring of the body to prompts like this then we can remove this check
like this then we can remove this check for configuration API key that is for
for configuration API key that is for openai like this and instead of checking
openai like this and instead of checking if there are messages we're going to
if there are messages we're going to check if there is a prompt and write
check if there is a prompt and write prompt is required like this and now our
prompt is required like this and now our response is going to be a little bit
response is going to be a little bit different so we're not going to use open
different so we're not going to use open AI we're going to use replicate but in
AI we're going to use replicate but in order to find the correct model it's
order to find the correct model it's really hard to write because it's a very
really hard to write because it's a very long model so let's go ahead and let's
long model so let's go ahead and let's go into replicate and let me show you
go into replicate and let me show you how to use this
how to use this so going to replicate and find the
so going to replicate and find the explore button right here and here you
explore button right here and here you can see a bunch of models that they have
can see a bunch of models that they have so feel free to play around with any of
so feel free to play around with any of these as you want you see they have a
these as you want you see they have a music generation bark a bunch of stuff
music generation bark a bunch of stuff right so I'm going to show you which one
right so I'm going to show you which one I am using to create music and then
I am using to create music and then later once you finish the tutorial you
later once you finish the tutorial you can play around with any of those but
can play around with any of those but just be careful if you are on a free
just be careful if you are on a free tier because you're going to use them up
tier because you're going to use them up so go ahead and find the audio
so go ahead and find the audio generation models in the collections
generation models in the collections right here and I'm going to use refusion
right here and I'm going to use refusion right here
right here and here you can see and you can test
and here you can see and you can test out try and generate one of your own
out try and generate one of your own change the test here but don't change
change the test here but don't change too much don't play around too much
too much don't play around too much because I don't want you to lose your
because I don't want you to lose your free tier and basically once you click
free tier and basically once you click on the API here you can see how you have
on the API here you can see how you have to uh how you can actually use it so we
to uh how you can actually use it so we already did this and what we have to do
already did this and what we have to do now is we have to copy this so this is
now is we have to copy this so this is the you can see the exact code that we
the you can see the exact code that we need to call to actually generate music
need to call to actually generate music so I'm going to copy this output which
so I'm going to copy this output which is a weight replicate.run and you can
is a weight replicate.run and you can see how it uses this very long text I'm
see how it uses this very long text I'm actually not sure if we need this this
actually not sure if we need this this looks like some kind of hash
looks like some kind of hash um but I I haven't tested it without it
um but I I haven't tested it without it so let's go just go ahead and copy this
so let's go just go ahead and copy this right here
right here and let's go ahead and replace this
and let's go ahead and replace this response with that like this so I'm
response with that like this so I'm going to expand it as much as I can so
going to expand it as much as I can so you can see and I'm going to change the
you can see and I'm going to change the output to response like that and we're
output to response like that and we're going to change this prompt a which is
going to change this prompt a which is hard coded to Funky synth solo to be our
hard coded to Funky synth solo to be our prompt which we're receiving from the
prompt which we're receiving from the body like this and then let's go ahead
body like this and then let's go ahead and just pass in the entire response
and just pass in the entire response back and let's change this to music
back and let's change this to music error like that and now let's go back
error like that and now let's go back inside of our page
inside of our page so inside the dashboard routes music
so inside the dashboard routes music page.thesx right here let's go all the
page.thesx right here let's go all the way down where we write music will be
way down where we write music will be generated here and let's change this to
generated here and let's change this to be an actual audio file so I'm gonna go
be an actual audio file so I'm gonna go ahead and I'm gonna remove this div I'm
ahead and I'm gonna remove this div I'm going to write a conditional so only if
going to write a conditional so only if there is music in our state in that case
there is music in our state in that case we're going to render an audio element
we're going to render an audio element from native HTML we're going to enable
from native HTML we're going to enable the controls we're going to give you the
the controls we're going to give you the class name of w Dash full and margin top
class name of w Dash full and margin top 8 like this and inside we're gonna give
8 like this and inside we're gonna give a source which is a self-closing tag
a source which is a self-closing tag with a source of music like this
with a source of music like this so let's go ahead Let's test if this is
so let's go ahead Let's test if this is working I'm going to write piano solo
working I'm going to write piano solo like this and I'm going to click
like this and I'm going to click generate and in a couple of seconds
generate and in a couple of seconds we're gonna see if this is working or
we're gonna see if this is working or not but don't be scared if this is
not but don't be scared if this is taking a long long time so the way I
taking a long long time so the way I replicate AI works is it has a cold
replicate AI works is it has a cold start so if this is your first time
start so if this is your first time running it you might wait up to a minute
running it you might wait up to a minute or more for this to be generated but
or more for this to be generated but next instances are going to be much
next instances are going to be much faster because it's not doing a cold
faster because it's not doing a cold start so just be patient and the way you
start so just be patient and the way you can check if everything is correct you
can check if everything is correct you can go ahead
can go ahead in your dashboard right here
in your dashboard right here and you can see that I have refusions
and you can see that I have refusions starting 28 seconds ago so if you see
starting 28 seconds ago so if you see that here that means everything is good
that here that means everything is good your API is working and just be patient
your API is working and just be patient and wait till it says succeeded right
and wait till it says succeeded right here so I'm gonna pause the video and
here so I'm gonna pause the video and I'm gonna enable it once it's finished
I'm gonna enable it once it's finished there we go you can go ahead and play it
there we go you can go ahead and play it I'm not gonna play just in case someone
I'm not gonna play just in case someone decides to copyright AI music in the
decides to copyright AI music in the future but I want to show you how long
future but I want to show you how long it took me to do this so let's see I'm
it took me to do this so let's see I'm going to refresh here it took me 28
going to refresh here it took me 28 seconds to actually run it but the cold
seconds to actually run it but the cold start was almost 12 minutes so don't be
start was almost 12 minutes so don't be scared if yours is still running it's
scared if yours is still running it's completely normal but the second one you
completely normal but the second one you try is going to be much shorter than
try is going to be much shorter than that and if you actually take a look
that and if you actually take a look let's take a look at the I don't know
let's take a look at the I don't know stable diffusion for example every API
stable diffusion for example every API actually has
actually has a web Hook when it's completed so if you
a web Hook when it's completed so if you are a bit more advanced and know how to
are a bit more advanced and know how to work with web hooks you can go ahead and
work with web hooks you can go ahead and add a web hook to your API that way you
add a web hook to your API that way you don't have to hold your
don't have to hold your uh API routes into loading for such a
uh API routes into loading for such a long time almost 12 minutes you can use
long time almost 12 minutes you can use a web hook to trigger the event as
a web hook to trigger the event as completed and then you can show a
completed and then you can show a notification for your user that's a bit
notification for your user that's a bit more advanced and I'm gonna save that
more advanced and I'm gonna save that for some other tutorial but there are
for some other tutorial but there are options you can speed up this if you
options you can speed up this if you want to great so now you know how to
want to great so now you know how to generate music you can change the volume
generate music you can change the volume you can play it you can download it
you can play it you can download it amazing you're doing so great and it
amazing you're doing so great and it also is responsive on mobile as
also is responsive on mobile as everything so far let's check it if we
everything so far let's check it if we go from the dashboard and click on music
go from the dashboard and click on music it works as well amazing so all that's
it works as well amazing so all that's left is video generation and that's what
left is video generation and that's what we are going to do next
we are going to do next let's create our last AI model video
let's create our last AI model video generation so we're gonna do the same
generation so we're gonna do the same thing with it a couple of times but this
thing with it a couple of times but this time we're going to copy the music app
time we're going to copy the music app so let's go into routes inside of your
so let's go into routes inside of your dashboard right here go ahead and copy
dashboard right here go ahead and copy the music folder and paste it inside of
the music folder and paste it inside of the routes and rename a music copy to
the routes and rename a music copy to video like that the reason we are
video like that the reason we are copying music is because it's going to
copying music is because it's going to be more similar than other tools to the
be more similar than other tools to the one we want right now which is video and
one we want right now which is video and now if I try and click on the video I
now if I try and click on the video I get music generation instead of a 404
get music generation instead of a 404 and let's just quickly check if it's the
and let's just quickly check if it's the same from the dashboard it is great and
same from the dashboard it is great and now what we have to do is we have to
now what we have to do is we have to obviously modify this
obviously modify this a video page to look like video page and
a video page to look like video page and not music generation so make sure you
not music generation so make sure you are on localhost 3000 slash video make
are on localhost 3000 slash video make sure you're not accidentally editing the
sure you're not accidentally editing the music folder go inside video folder
music folder go inside video folder page.tsx
page.tsx and let's already remove this import we
and let's already remove this import we don't need so chat completion request
don't need so chat completion request message from open AI we don't need that
message from open AI we don't need that here great now let's go ahead and let's
here great now let's go ahead and let's go and change this music generation
go and change this music generation title into video generation and let's
title into video generation and let's change the prompt uh the description to
change the prompt uh the description to turn your prompt into music into video
turn your prompt into music into video like this
like this the icon is going to be file audio sorry
the icon is going to be file audio sorry the icon is going to be video icon like
the icon is going to be video icon like this from Lucid react
this from Lucid react so make sure you import that and remove
so make sure you import that and remove music like this
music like this and now let's go ahead and change the
and now let's go ahead and change the colors so it's going to be orange like
colors so it's going to be orange like this and the value is not going to be
this and the value is not going to be 500 but it's going to be 700 like this
500 but it's going to be 700 like this so it looks the same as your sidebar and
so it looks the same as your sidebar and as this tools component right here great
as this tools component right here great now let's go ahead and let's change the
now let's go ahead and let's change the placeholder for the input instead of
placeholder for the input instead of saying uh piano solo we're going to
saying uh piano solo we're going to write a more realistic prompt something
write a more realistic prompt something like clown fish swimming around a coral
like clown fish swimming around a coral reef like that there we go and let's go
reef like that there we go and let's go ahead
ahead and modify we're not going to store any
and modify we're not going to store any music here instead we're gonna store
music here instead we're gonna store video so let's change let's first change
video so let's change let's first change the music page to video page like that
the music page to video page like that and then let's change the music state to
and then let's change the music state to video and set video like that now let's
video and set video like that now let's modify our on submit function so it's
modify our on submit function so it's going to be set video like this and this
going to be set video like this and this is going to be set video as well and
is going to be set video as well and let's also modify the API request so
let's also modify the API request so it's going to go to slash video and not
it's going to go to slash video and not slash music and the response data is
slash music and the response data is going to be a little bit different so we
going to be a little bit different so we are actually going to go ahead and pick
are actually going to go ahead and pick the first from the array because that's
the first from the array because that's what is going to be returned from the
what is going to be returned from the API so make sure you modify it from data
API so make sure you modify it from data dot audio to data first in the array
dot audio to data first in the array right here great and now let's go all
right here great and now let's go all the way down here so we can actually fix
the way down here so we can actually fix these errors so instead of checking for
these errors so instead of checking for music we're going to check for video and
music we're going to check for video and we're gonna write no video generated
we're gonna write no video generated like that and the same thing for the yes
like that and the same thing for the yes we're gonna add video and we're actually
we're gonna add video and we're actually not going to render an audio file we're
not going to render an audio file we're going to render a video file
going to render a video file like this and we're going to give it a
like this and we're going to give it a class name of w Dash full aspect
class name of w Dash full aspect Dash video margin top 8 rounded LG
Dash video margin top 8 rounded LG border and BG Dash black like this and I
border and BG Dash black like this and I also want to give it a controls prop so
also want to give it a controls prop so we can control the video and inside add
we can control the video and inside add a source element with Source video like
a source element with Source video like that so very similar to music great and
that so very similar to music great and now let's go ahead and let's actually
now let's go ahead and let's actually create this slash API video because the
create this slash API video because the prompt can stay the same so if you check
prompt can stay the same so if you check the constants right here you can see we
the constants right here you can see we have a form schema and let's just change
have a form schema and let's just change the message to video prompt is required
the message to video prompt is required but again you actually don't need this
but again you actually don't need this at all because you're not displaying it
at all because you're not displaying it anywhere great and now let's go ahead
anywhere great and now let's go ahead and close everything and let's go inside
and close everything and let's go inside of our API and let's copy the music
of our API and let's copy the music folder again
folder again let's paste it inside of the API and
let's paste it inside of the API and let's rename it to video and in route.ts
let's rename it to video and in route.ts let's go ahead and let's see what we
let's go ahead and let's see what we have to change here so first things
have to change here so first things first we have to go inside uh replicate
first we have to go inside uh replicate again and we have to find the AI model
again and we have to find the AI model we want to use so in my case you can
we want to use so in my case you can play around you can choose whatever you
play around you can choose whatever you want really there are many models here
want really there are many models here the one I'm going to use is going to be
the one I'm going to use is going to be zeroscope right here but if you go into
zeroscope right here but if you go into collections you can go ahead and find uh
collections you can go ahead and find uh this videos collection and you can see
this videos collection and you can see that they have a bunch of video models
that they have a bunch of video models that you can use and you can feel free
that you can use and you can feel free to play around with them but the reason
to play around with them but the reason I chose this one
I chose this one called the zero scope so go into
called the zero scope so go into Explorer and it should be the very first
Explorer and it should be the very first right here or you can search zeroscope
right here or you can search zeroscope like this and find it the reason I chose
like this and find it the reason I chose this one is because it has the lowest uh
this one is because it has the lowest uh a time to generate everything else is
a time to generate everything else is like a thousand seconds this one seems
like a thousand seconds this one seems to be the fastest so that's why I chose
to be the fastest so that's why I chose this one great so if you want to you can
this one great so if you want to you can play around and test it but be careful
play around and test it but be careful if you have a free tier you don't want
if you have a free tier you don't want to block yourself from using the
to block yourself from using the tutorial and have to add a billing so
tutorial and have to add a billing so let's just go into API right here
let's just go into API right here and let's go ahead and let's copy this
and let's go ahead and let's copy this output right here so we know what to put
output right here so we know what to put in our API so I'm going to copy this
in our API so I'm going to copy this output from here
output from here I'm going to expand this and I'm going
I'm going to expand this and I'm going to replace this response with that but
to replace this response with that but I'm going to change the constant to be
I'm going to change the constant to be response like that and you can see how
response like that and you can see how I'm using xeroscope right here so this
I'm using xeroscope right here so this exact problem that I copied from here
exact problem that I copied from here great and let's change this prompt to
great and let's change this prompt to actually use our prompt so you can
actually use our prompt so you can either use prompt like this or you can
either use prompt like this or you can use a shorthand because it's named
use a shorthand because it's named exactly the same and we're extracting
exactly the same and we're extracting prompt from the body so we don't need to
prompt from the body so we don't need to change absolutely anything everything is
change absolutely anything everything is fine except we have to change the music
fine except we have to change the music error to video error like that
error to video error like that and sending just response is fine great
and sending just response is fine great and I think we are ready to immediately
and I think we are ready to immediately test this so let's go inside of our
test this so let's go inside of our genius right here
genius right here I'm gonna go ahead and write clown fish
I'm gonna go ahead and write clown fish swimming around a
swimming around a a coral reef like that and I'm Gonna
a coral reef like that and I'm Gonna Leave it again I assume it's going to
Leave it again I assume it's going to take a long time to generate because
take a long time to generate because this is another called the start so be
this is another called the start so be patient my music took 12 minutes so I
patient my music took 12 minutes so I assume this is going to take something
assume this is going to take something like that so just be patient and I'm
like that so just be patient and I'm gonna unpause the video once it is ready
gonna unpause the video once it is ready and there we go it has generated for me
and there we go it has generated for me and this is how it looks really really
and this is how it looks really really cool it's so cool to me that an AI
cool it's so cool to me that an AI generates this realistic looking videos
generates this realistic looking videos and you can even test the prompts more
and you can even test the prompts more for example you can see in this demo
for example you can see in this demo right here that they give it a very
right here that they give it a very specific and very
specific and very um detailed prompt so you can play
um detailed prompt so you can play around with that to get a better result
around with that to get a better result and let me show you exactly how long it
and let me show you exactly how long it took me to generate this so I'm going to
took me to generate this so I'm going to zoom out a bit so it took me 42 seconds
zoom out a bit so it took me 42 seconds to generate it
to generate it um so yeah it was a bit shorter than
um so yeah it was a bit shorter than this one
this one this one says 28 seconds but you know
this one says 28 seconds but you know that the cold start was 12 minutes this
that the cold start was 12 minutes this one was actually much faster for me but
one was actually much faster for me but if yours is still running as long as you
if yours is still running as long as you can see it on the dashboard zeroscope
can see it on the dashboard zeroscope that means everything is fine you
that means everything is fine you successfully finished every single AI
successfully finished every single AI tool great great job uh what we're gonna
tool great great job uh what we're gonna do now is we are going to implement
do now is we are going to implement subscription and API limits to how much
subscription and API limits to how much free users can use our application and
free users can use our application and then we're going to add crisp for
then we're going to add crisp for customer support and then we are going
customer support and then we are going to implement the landing page
to implement the landing page so now that we have all of our AI tools
so now that we have all of our AI tools working it's time to create a
working it's time to create a functionality that is going to limit
functionality that is going to limit free users to only be able to use them
free users to only be able to use them five times in order to do that we're
five times in order to do that we're going to use Prisma so let's go ahead
going to use Prisma so let's go ahead and let's set up Prisma first I'm gonna
and let's set up Prisma first I'm gonna go inside of my terminal right here
go inside of my terminal right here I'm gonna shut down everything and I'm
I'm gonna shut down everything and I'm gonna write npm install Dash capital D
gonna write npm install Dash capital D Prisma like this I'm gonna wait a couple
Prisma like this I'm gonna wait a couple of seconds for this to install and then
of seconds for this to install and then we're gonna run Prisma in it so it's
we're gonna run Prisma in it so it's going to create a couple of files in our
going to create a couple of files in our project
project so let's go ahead and let's run npx
so let's go ahead and let's run npx Prisma in it like this and there we go
Prisma in it like this and there we go we have our prism setup let's take a
we have our prism setup let's take a look at everything that has been created
look at everything that has been created inside so we have a new folder called
inside so we have a new folder called Prisma and inside we have schema.prisma
Prisma and inside we have schema.prisma right now it's set to postgrad SQL we're
right now it's set to postgrad SQL we're going to change that to mySQL and we
going to change that to mySQL and we also have some additions to our DOT
also have some additions to our DOT environment file you can see that this
environment file you can see that this was inserted by Prisma in it and we have
was inserted by Prisma in it and we have a database URL which is currently a
a database URL which is currently a postgresql database0 which of course is
postgresql database0 which of course is not working it's just a mock URL so
not working it's just a mock URL so we're going to change both of those in
we're going to change both of those in order to do that we have to create our
order to do that we have to create our planet scale account
planet scale account so let's go ahead and go to
so let's go ahead and go to planetscale.com or Google Planet scale
planetscale.com or Google Planet scale and find sign in or get started button
and find sign in or get started button so I'm going to go ahead and log in and
so I'm going to go ahead and log in and show you what it looks like
show you what it looks like great so once you're here if you want to
great so once you're here if you want to you can go ahead and click click on all
you can go ahead and click click on all of these different options or you can
of these different options or you can simply go ahead and click on this create
simply go ahead and click on this create option right here so just click create
option right here so just click create and let's go ahead and let's give this
and let's go ahead and let's give this database name AI SAS like this
database name AI SAS like this and you can go ahead and select a free
and you can go ahead and select a free option right here
option right here and then just go ahead and click create
and then just go ahead and click create database and just confirm that your
database and just confirm that your total monthly cost is free I just want
total monthly cost is free I just want to ensure that this looks like it to you
to ensure that this looks like it to you so just select the free option right
so just select the free option right here so it's you don't have to pay
here so it's you don't have to pay anything for Planet scale for your uh
anything for Planet scale for your uh one database that you have great and
one database that you have great and this can take uh some time so I'm gonna
this can take uh some time so I'm gonna pause the video and I'm gonna show you
pause the video and I'm gonna show you what it looks like once it's initialized
what it looks like once it's initialized so again just be patient and you're
so again just be patient and you're actually going to see a little pop-up
actually going to see a little pop-up here saying that you are ready to
here saying that you are ready to connect so just be patient and wait for
connect so just be patient and wait for this to finish
this to finish and you can see how I have this prompt
and you can see how I have this prompt ready to connect to your database and I
ready to connect to your database and I have an option to click get connection
have an option to click get connection strings so click on either of those I'm
strings so click on either of those I'm going to use this really to connect to
going to use this really to connect to your database and in here you can see
your database and in here you can see that we have to click create a password
that we have to click create a password like this and there we go once this has
like this and there we go once this has created you can choose how you want to
created you can choose how you want to connect go ahead and select Prisma
connect go ahead and select Prisma because that's what we're using so first
because that's what we're using so first thing you have to do is copy this
thing you have to do is copy this database URL and let's paste that in our
database URL and let's paste that in our environment file right here so I'm going
environment file right here so I'm going to replace this entire thing that has
to replace this entire thing that has generated by by Prisma and paste this
generated by by Prisma and paste this new string right here using Planet scale
new string right here using Planet scale right here so P scale and you can see
right here so P scale and you can see the name of my database right here great
the name of my database right here great and what we have to do next is modify
and what we have to do next is modify schema.prisma so click on this tabs
schema.prisma so click on this tabs schema.prisma copy the entire thing and
schema.prisma copy the entire thing and let's go back inside of our code go
let's go back inside of our code go ahead in schema.prisma which is in your
ahead in schema.prisma which is in your Prisma folder and you can just paste it
Prisma folder and you can just paste it here and you can see right now it uses
here and you can see right now it uses the MySQL provider and reads the
the MySQL provider and reads the environment while database underscore
environment while database underscore URL which we've added right here
URL which we've added right here alongside everything else we have great
alongside everything else we have great so that is actually it for Planet scale
so that is actually it for Planet scale you can safely close that now
you can safely close that now uh that is ready and let's go back and
uh that is ready and let's go back and work on our application so one util I
work on our application so one util I want to add before we continue uh is
want to add before we continue uh is our Prisma DB client so let's go inside
our Prisma DB client so let's go inside of our terminal
of our terminal and let's run npm install at Prisma
and let's run npm install at Prisma slash client like this wait a couple of
slash client like this wait a couple of seconds for this to install and then
seconds for this to install and then we're gonna create a util which is going
we're gonna create a util which is going to be able to access the database using
to be able to access the database using Prisma and this package so there we go
Prisma and this package so there we go it's installed and now let's go inside
it's installed and now let's go inside lib and create a new file called Prisma
lib and create a new file called Prisma db.ts like that go ahead and import
db.ts like that go ahead and import Prisma client from ads Prisma slash
Prisma client from ads Prisma slash client and declare global war Prisma to
client and declare global war Prisma to be Prisma client
be Prisma client or undefined
or undefined like this
like this and then just write const Prisma DB is
and then just write const Prisma DB is equal to
equal to globaldis.prisma or
globaldis.prisma or new Prisma client like that
new Prisma client like that and then we're going to write a
and then we're going to write a condition so if process.environment dot
condition so if process.environment dot node environment is not identical to
node environment is not identical to production meaning its development in
production meaning its development in that case we're gonna assign Global this
that case we're gonna assign Global this dot Prisma
dot Prisma to Prisma DB like that and just export
to Prisma DB like that and just export default Prisma DB like this so what does
default Prisma DB like this so what does this code do and why do we need this
this code do and why do we need this declare Global well you can try and
declare Global well you can try and remove it and then you see you have a
remove it and then you see you have a curly line in Globe of this so that's
curly line in Globe of this so that's why we need this we add Prisma variable
why we need this we add Prisma variable to our Global window great and why are
to our Global window great and why are we doing this uh conditional why are we
we doing this uh conditional why are we checking for Global this and why don't
checking for Global this and why don't we just do new Prisma client that looks
we just do new Prisma client that looks much simpler well that's because the way
much simpler well that's because the way next 13 does reloading uh it basically
next 13 does reloading uh it basically there is a chance that you have a lot of
there is a chance that you have a lot of Prisma clients initialized every time
Prisma clients initialized every time you hot reload every time you change
you hot reload every time you change something in your code so this way we
something in your code so this way we assign that in not in production so in
assign that in not in production so in development we assign this to Global
development we assign this to Global this that way it's not affected by hot
this that way it's not affected by hot reload and you don't get that warning in
reload and you don't get that warning in your console that there are multiple
your console that there are multiple Prisma client instances active great and
Prisma client instances active great and now that we have that we can actually go
now that we have that we can actually go ahead back in our skin Prisma
ahead back in our skin Prisma and let's create the model for our user
and let's create the model for our user API limit so one thing I just want to
API limit so one thing I just want to tell you right ahead if you are seeing
tell you right ahead if you are seeing this Prisma a bit different so if you're
this Prisma a bit different so if you're not seeing blue colors for the generator
not seeing blue colors for the generator client and clearly separate the strings
client and clearly separate the strings so if everything is in the same color
so if everything is in the same color for you make sure that you're using the
for you make sure that you're using the Prisma extension so just type in Prisma
Prisma extension so just type in Prisma it's the first one so make sure you
it's the first one so make sure you install that and use that because it
install that and use that because it also has some autocomplete features
also has some autocomplete features great now let's write our model so model
great now let's write our model so model user API limit like that let's give it
user API limit like that let's give it an ID which is a type of string
an ID which is a type of string decorator ID and a default value is
decorator ID and a default value is going to be cuid like this
going to be cuid like this user ID is going to be a string and you
user ID is going to be a string and you need
need pound is going to be an integer
pound is going to be an integer and it's going to have a default value
and it's going to have a default value of 0.
of 0. created at is going to be a date time
created at is going to be a date time with the default value of now and
with the default value of now and updated ad is also going to be a date
updated ad is also going to be a date time
time with a decorator updated at like this
with a decorator updated at like this perfect now that we have that let's go
perfect now that we have that let's go ahead and let's try and push that to our
ahead and let's try and push that to our database so I'm going to write npx
database so I'm going to write npx Prisma DB push like this and let's see
Prisma DB push like this and let's see if we this is going to work or if we are
if we this is going to work or if we are going to get any errors so you can see
going to get any errors so you can see that we are using Planet scale and this
that we are using Planet scale and this is the name of my database and mine was
is the name of my database and mine was successful so now it's successfully uh
successful so now it's successfully uh in the database and every time you
in the database and every time you modify your schema Prisma you have to
modify your schema Prisma you have to push it and you also have to run npx
push it and you also have to run npx Prisma generate like this so npx Prisma
Prisma generate like this so npx Prisma generate is going to add this model to
generate is going to add this model to your node modules so then you have the
your node modules so then you have the types and you're not going to get any
types and you're not going to get any errors while developing great
errors while developing great now let's go ahead and let's go inside
now let's go ahead and let's go inside of actually before I run the app I want
of actually before I run the app I want to show you how you can take a look at
to show you how you can take a look at your data so I'm going to run npx Prisma
your data so I'm going to run npx Prisma Studio like this
Studio like this and I'm gonna add it right here
and I'm gonna add it right here okay I'm just gonna copy it like this so
okay I'm just gonna copy it like this so I'm gonna paste it here there we go and
I'm gonna paste it here there we go and now you can see all of your data inside
now you can see all of your data inside so you can see this model that we just
so you can see this model that we just created user API limits and once I click
created user API limits and once I click here we have no uh API limits inside so
here we have no uh API limits inside so now we're slowly going to create some
now we're slowly going to create some utils and we are going to create it
utils and we are going to create it first for the conversation model so
first for the conversation model so we're going to start by protecting the
we're going to start by protecting the conversation model and every time we add
conversation model and every time we add a new prompt in here in conversation uh
a new prompt in here in conversation uh we're gonna create a new account for
we're gonna create a new account for user API limit and that is the way we
user API limit and that is the way we are going to protect the maximum count
are going to protect the maximum count the maximum number of times free tier
the maximum number of times free tier users can use this conversation model so
users can use this conversation model so let's go ahead and do that so you can
let's go ahead and do that so you can keep this Prisma Studio running in
keep this Prisma Studio running in another terminal if you want to I'm
another terminal if you want to I'm going to shut it down and I'm going to
going to shut it down and I'm going to run the application instead
run the application instead so I'm going to refresh this I'm going
so I'm going to refresh this I'm going to zoom out just a bit and I'm going to
to zoom out just a bit and I'm going to wait for it to load
wait for it to load and what we're going to do now is you're
and what we're going to do now is you're actually going to go ahead in our
actually going to go ahead in our constants file which we don't have yet
constants file which we don't have yet so let's get at the root of our
so let's get at the root of our application and create a new file called
application and create a new file called constance.ds like this and go ahead and
constance.ds like this and go ahead and write export const Max underscore free
write export const Max underscore free underscore counts to be five you can of
underscore counts to be five you can of course change this to whatever you want
course change this to whatever you want so for this tutorial I'm gonna allow
so for this tutorial I'm gonna allow free theater users to use the app five
free theater users to use the app five times you can increase this to 100 if
times you can increase this to 100 if you want to and now let's go ahead
you want to and now let's go ahead inside of our lib folder
inside of our lib folder and I'm going to create a new file
and I'm going to create a new file called
called api-limit.ts like this and let's go
api-limit.ts like this and let's go ahead and let's import out from clerk
ahead and let's import out from clerk next.js like this let's import Prisma DB
next.js like this let's import Prisma DB from dot slash Prisma DB because it's in
from dot slash Prisma DB because it's in the same folder or you can use slash
the same folder or you can use slash Libs lib like this
Libs lib like this and let's also import Max underscore
and let's also import Max underscore free Counts from add slash constants
free Counts from add slash constants great so now let's write a util that is
great so now let's write a util that is going to increase our API limit count
going to increase our API limit count every time we ping one of the apis so
every time we ping one of the apis so export const increase
export const increase API limit is going to be in a
API limit is going to be in a synchronous Arrow function
synchronous Arrow function we're going to extract the user ID using
we're going to extract the user ID using auth
auth like this
like this if there is no user ID we're just going
if there is no user ID we're just going to return and break this function now if
to return and break this function now if there is what we're going to do is write
there is what we're going to do is write const user API limit
const user API limit like this to be a weight Charisma DB dot
like this to be a weight Charisma DB dot user API limit if you did not get this
user API limit if you did not get this autocorrect or if you're getting an
autocorrect or if you're getting an underline in here make sure that you run
underline in here make sure that you run npx Prisma generate and refresh your
npx Prisma generate and refresh your application and reload your entire vs
application and reload your entire vs code so you need to run npx Prisma
code so you need to run npx Prisma generate and npx Prisma DB push and this
generate and npx Prisma DB push and this user API limit is matching what we have
user API limit is matching what we have in our schema so make sure you didn't
in our schema so make sure you didn't misspell this accidentally user API
misspell this accidentally user API limit and then it should work in here as
limit and then it should work in here as well so first thing that we're going to
well so first thing that we're going to do is we're going to check whether there
do is we're going to check whether there is an model there is a document in the
is an model there is a document in the table for this exact user for its API
table for this exact user for its API limit because right now when we register
limit because right now when we register this model doesn't exist in my Prisma
this model doesn't exist in my Prisma studio so first thing I'm going to do is
studio so first thing I'm going to do is check if it already exists so I'm going
check if it already exists so I'm going to write find unique
to write find unique I'm going to open an object and like
I'm going to open an object and like where user ID is equal to user ID or you
where user ID is equal to user ID or you can use the shorthand so we're going to
can use the shorthand so we're going to fetch that by looking at the user ID in
fetch that by looking at the user ID in that model and we get the user ID from
that model and we get the user ID from the app like that so if there is user
the app like that so if there is user API limit so if it already exists in
API limit so if it already exists in that case we are going to update its
that case we are going to update its count so I'll wait
count so I'll wait Prisma db.user API limit dot update
Prisma db.user API limit dot update where
where user ID is equal to user ID and data
user ID is equal to user ID and data is going to be count user
is going to be count user API limit dot count plus one like this
API limit dot count plus one like this great else we're going to create a new
great else we're going to create a new user API limit so we're going to write a
user API limit so we're going to write a weight Prisma DB dot user API limit dot
weight Prisma DB dot user API limit dot create
create data
data user ID is going to be user ID and count
user ID is going to be user ID and count is going to be one
is going to be one like that beautiful and now that we have
like that beautiful and now that we have that we can go ahead and create another
that we can go ahead and create another YouTube which is going to check whether
YouTube which is going to check whether the current user has reached the limit
the current user has reached the limit of their free usage so export cons check
of their free usage so export cons check API limit
API limit is going to be in a synchronous Arrow
is going to be in a synchronous Arrow function
we're going to extract the user ID again so out like this
so out like this if there is no user ID
if there is no user ID we are immediately going to return false
we are immediately going to return false so we are not going to allow the user to
so we are not going to allow the user to go any further and then let's go ahead
go any further and then let's go ahead and fetch the user API limit so const
and fetch the user API limit so const user API limit await
user API limit await Prisma DB dot user API limit dot find
Prisma DB dot user API limit dot find unique
unique where
where user ID is equal to user ID
user ID is equal to user ID like this if there is no user API limit
like this if there is no user API limit or if there is user API limit and the
or if there is user API limit and the current account is less than Max 3
current account is less than Max 3 counts so if the user has not used up
counts so if the user has not used up all of their accounts or if they never
all of their accounts or if they never even created their first generation
even created their first generation meaning that they don't have this user
meaning that they don't have this user API limit in that case we're going to
API limit in that case we're going to return true meaning they can still use
return true meaning they can still use our app but if user has passed the free
our app but if user has passed the free count in that case we're going to return
count in that case we're going to return false meaning that we have to block the
false meaning that we have to block the user from using our API great and now
user from using our API great and now that we have these two we are ready to
that we have these two we are ready to add them to our routes and actually
add them to our routes and actually protect them so let's go ahead and do
protect them so let's go ahead and do that next
that next so let's go inside of our conversation
so let's go inside of our conversation for example so I'm gonna go into app API
for example so I'm gonna go into app API inside conversation route CS right here
inside conversation route CS right here and I'm going to go ahead and I'm going
and I'm going to go ahead and I'm going to import increment API limit and check
to import increment API limit and check API limit from add slash lib API Dash
API limit from add slash lib API Dash limit like this and after I check for
limit like this and after I check for this messages right here what I'm going
this messages right here what I'm going to do is I'm going to check whether we
to do is I'm going to check whether we are on a free trial so it cost free
are on a free trial so it cost free trial is equal to 08 check API limit
trial is equal to 08 check API limit like this great and now if we have
like this great and now if we have passed the free trial so question mark
passed the free trial so question mark free trial in that case we're going to
free trial in that case we're going to return new next response free trial has
return new next response free trial has expired like this and let's give it a
expired like this and let's give it a status of 403
status of 403 so the status of 403 is really important
so the status of 403 is really important because the status this is the status
because the status this is the status that we are going to recognize on the
that we are going to recognize on the front end and know okay we have to
front end and know okay we have to trigger a pro subscription model so make
trigger a pro subscription model so make sure you return a status of 403 in this
sure you return a status of 403 in this case if there is no free trial available
case if there is no free trial available great and in case this passes we're
great and in case this passes we're going to normally generate the response
going to normally generate the response and then we're gonna run a weight
and then we're gonna run a weight increase API limit like this great so
increase API limit like this great so let's go ahead and test this now but the
let's go ahead and test this now but the best way to test this is to keep your
best way to test this is to keep your Prisma Studio running in the same place
Prisma Studio running in the same place so I'm going to go ahead and click plus
so I'm going to go ahead and click plus right here so I have two Terminals and
right here so I have two Terminals and I'm going to run npx Prisma Studio like
I'm going to run npx Prisma Studio like this and now it's running right here
this and now it's running right here great so I have both of my terminals
great so I have both of my terminals running now and let's check this so make
running now and let's check this so make sure that you are
sure that you are in your conversation right here make
in your conversation right here make sure that you have nothing inside of
sure that you have nothing inside of your user API limit so select user API
your user API limit so select user API limit from here great and let's check
limit from here great and let's check now so I'm going to write I don't know
now so I'm going to write I don't know hello how are you like this
hello how are you like this let's wait for the response from chat
let's wait for the response from chat GPT great so it has responded and let's
GPT great so it has responded and let's see if I refresh right now I think I
see if I refresh right now I think I should have great there we go you can
should have great there we go you can see that I have my user API limit and
see that I have my user API limit and it's linked to my clerk user ID and the
it's linked to my clerk user ID and the count is one so let's try another one
count is one so let's try another one this is a test
this is a test let's see if that is going to increase
let's see if that is going to increase our limit let's go ahead and refresh
our limit let's go ahead and refresh again
again there we go count is now two so I'm
there we go count is now two so I'm gonna just zoom in so you can see count
gonna just zoom in so you can see count is two and I'm gonna go ahead and just
is two and I'm gonna go ahead and just try a couple of more times until we
try a couple of more times until we reach uh the count of five and see what
reach uh the count of five and see what happens then
happens then let's see so I just pasted a couple of
let's see so I just pasted a couple of messages I'm gonna refresh there it goes
messages I'm gonna refresh there it goes now it says that count is five and if
now it says that count is five and if I'm correct we should now get an error
I'm correct we should now get an error saying that free trial has expired so
saying that free trial has expired so I'm gonna go ahead
I'm gonna go ahead in my network right here and I'm gonna
in my network right here and I'm gonna write expired and click generate and
write expired and click generate and there we go you can see this time it
there we go you can see this time it didn't work and we got a 403 that free
didn't work and we got a 403 that free trial has expired great great job you
trial has expired great great job you officially implemented API limits for
officially implemented API limits for your users what we have to do next is we
your users what we have to do next is we have to connect them with stripe to
have to connect them with stripe to actually check uh whether the user is in
actually check uh whether the user is in Pro or not but we're gonna do that
Pro or not but we're gonna do that slowly what I want to do now is I want
slowly what I want to do now is I want to add this code for uh checking free
to add this code for uh checking free trials into all of our routes so let's
trials into all of our routes so let's go ahead and let's copy this
go ahead and let's copy this and let's go inside of code next right
and let's go inside of code next right here so I'm going to add that here
here so I'm going to add that here inside of code like that I'm gonna go
inside of code like that I'm gonna go back inside of conversation and I'm
back inside of conversation and I'm gonna check for free trial and the if
gonna check for free trial and the if clause for the free trial and I'm gonna
clause for the free trial and I'm gonna paste that after this messages right
paste that after this messages right here and then all I'm gonna do is just
here and then all I'm gonna do is just await increase API limit after I give
await increase API limit after I give the respond so make sure you're doing
the respond so make sure you're doing this in code route great so now that we
this in code route great so now that we have that copy this again and let's go
have that copy this again and let's go into the next one so we did code and
into the next one so we did code and conversation now let's do image right
conversation now let's do image right here so I'm going to add it right here
here so I'm going to add it right here let's go ahead and let's copy this check
let's go ahead and let's copy this check for the free trial like that
for the free trial like that so after we check for resolution let's
so after we check for resolution let's do it right here and after we do the
do it right here and after we do the response our weight increase API limit
response our weight increase API limit like this great so copy this again let's
like this great so copy this again let's go to the next one let's go to the music
go to the next one let's go to the music right here
right here let's paste this like that
let's paste this like that let's copy this uh code for checking the
let's copy this uh code for checking the free trial and after the prompt go ahead
free trial and after the prompt go ahead and paste it here and after the response
and paste it here and after the response I'll wait increase API limit like that
I'll wait increase API limit like that perfect go ahead and copy this one more
perfect go ahead and copy this one more time and let's put that into the video
time and let's put that into the video as well so after the prompt check whoops
as well so after the prompt check whoops my apologies
my apologies so first we have to paste this Imports
so first we have to paste this Imports and then let's go ahead and copy this
and then let's go ahead and copy this free trial check
free trial check and after the prompt let's give it right
and after the prompt let's give it right here there we go and of course let's not
here there we go and of course let's not forget to increase the API limit so I'll
forget to increase the API limit so I'll wait increase API limit like that
wait increase API limit like that perfect so now every single one of our
perfect so now every single one of our uh AIS is protected so if I try image
uh AIS is protected so if I try image generation for example it will
generation for example it will immediately fail you can see that it's
immediately fail you can see that it's not generating any anything and the same
not generating any anything and the same thing is true for video yes it's failing
thing is true for video yes it's failing too and piano as well and code
too and piano as well and code generation as well so all of them works
generation as well so all of them works and if you go in Prisma studio and
and if you go in Prisma studio and modify this account to I don't know
modify this account to I don't know three and click save changes
three and click save changes and then go ahead and try conversation
and then go ahead and try conversation it should work normally because our Max
it should work normally because our Max count is five and you can of course
count is five and you can of course change that in the constants file so you
change that in the constants file so you can change Max free counts to 10 if you
can change Max free counts to 10 if you want to great great job uh what we're
want to great great job uh what we're going to do next is we're gonna go to
going to do next is we're gonna go to the front end and add the counter here
the front end and add the counter here into the sidebar and then we're gonna go
into the sidebar and then we're gonna go ahead and handle the 403 error in each
ahead and handle the 403 error in each of our components here so we can display
of our components here so we can display a nice model
a nice model let's build the front-end interface
let's build the front-end interface which is going to show the amount of
which is going to show the amount of three generations we have in this
three generations we have in this sidebar right here so let me just remind
sidebar right here so let me just remind you what I have opened so in my
you what I have opened so in my terminals right here in the first one I
terminals right here in the first one I have the app running and in the second
have the app running and in the second one I run npx Prisma studio so make sure
one I run npx Prisma studio so make sure you run this Command right here and make
you run this Command right here and make sure you visit Prisma Studio on
sure you visit Prisma Studio on localhost 55555 so I have that opened
localhost 55555 so I have that opened right here in my second Tab and as you
right here in my second Tab and as you can see right now I'm on count four so
can see right now I'm on count four so it doesn't matter what count you are on
it doesn't matter what count you are on but just go ahead and reset this to zero
but just go ahead and reset this to zero and click save one change so you can
and click save one change so you can develop the same way I am so just
develop the same way I am so just refresh again make sure this is zero and
refresh again make sure this is zero and refresh here as well great so what we
refresh here as well great so what we are going to do now is we're going to
are going to do now is we're going to add another action inside of our API
add another action inside of our API limit lib so going to the lib folder and
limit lib so going to the lib folder and go inside API Dash limit right here I'm
go inside API Dash limit right here I'm gonna expand this and alongside our
gonna expand this and alongside our check API limit and increase API limits
check API limit and increase API limits we're gonna add another one and this is
we're gonna add another one and this is going to be called get API limit count
going to be called get API limit count so export const get API limit count like
so export const get API limit count like this is going to be in the synchronous
this is going to be in the synchronous Arrow function which is also going to
Arrow function which is also going to use user ID from out
use user ID from out whoops
whoops we already have it so no need to import
we already have it so no need to import anything we already have this out from
anything we already have this out from Clark next JS great if we don't have a
Clark next JS great if we don't have a user ID in that case you can just return
user ID in that case you can just return zero
zero uh and now we're gonna go ahead and try
uh and now we're gonna go ahead and try and fetch the user API limit model so
and fetch the user API limit model so const user API limit is equal to await
const user API limit is equal to await Prisma DB dot user API limit dot find
Prisma DB dot user API limit dot find unique like this where user ID like this
unique like this where user ID like this great and if there is no user API
great and if there is no user API limited that means the user has never
limited that means the user has never run a generation before meaning that we
run a generation before meaning that we can also return zero because they have
can also return zero because they have no they haven't used any of their free
no they haven't used any of their free counts otherwise you are going to return
counts otherwise you are going to return user API limit dot count like this great
user API limit dot count like this great and now what we have to do is we have to
and now what we have to do is we have to run this action inside a server
run this action inside a server component so we can pass it in our
component so we can pass it in our sidebar component which is a client
sidebar component which is a client component so let's go ahead let's go
component so let's go ahead let's go inside of our app folder inside
inside of our app folder inside dashboard route group and go ahead and
dashboard route group and go ahead and select the layout inside the dashboard
select the layout inside the dashboard folder right here so make sure you are
folder right here so make sure you are in dashboard layout and not in any other
in dashboard layout and not in any other layout because we have two layouts so
layout because we have two layouts so make sure you're not in this one go
make sure you're not in this one go ahead in the dashboard folder and select
ahead in the dashboard folder and select that layout right here now let's go
that layout right here now let's go ahead and let's add this so const API
ahead and let's add this so const API limit count is equal to a weight
limit count is equal to a weight get API limits count like this and make
get API limits count like this and make sure you import get API limit count from
sure you import get API limit count from add slash lib API limit and we have an
add slash lib API limit and we have an error because we are trying to use a
error because we are trying to use a weight inside of an arrow function which
weight inside of an arrow function which is not a synchronous so just make sure
is not a synchronous so just make sure you mark this as an asynchronous layout
you mark this as an asynchronous layout like this and now we're going to use
like this and now we're going to use this API limit count and we're going to
this API limit count and we're going to pass it into the sidebar as a prop so go
pass it into the sidebar as a prop so go ahead and write API limit count
ahead and write API limit count with a Capital C like this and just
with a Capital C like this and just paste that here and Save
paste that here and Save we have a type error here because our
we have a type error here because our sidebar component does not accept this
sidebar component does not accept this prop so go ahead inside of your
prop so go ahead inside of your components folder inside sidebar right
components folder inside sidebar right here and let's go ahead and let's modify
here and let's go ahead and let's modify our interface actually create our
our interface actually create our interface so you can accept that uh here
interface so you can accept that uh here so let's go ahead and write the
so let's go ahead and write the interface sidebar props like that and
interface sidebar props like that and just write API limit count to be a
just write API limit count to be a number like this and then go ahead and
number like this and then go ahead and extract API limit count from our props
extract API limit count from our props and just let's give it a type of sidebar
and just let's give it a type of sidebar props like that and you can give it a
props like that and you can give it a default value of zero so it's easier to
default value of zero so it's easier to work with great now that we have that
work with great now that we have that what I'm going to do is I'm going to go
what I'm going to do is I'm going to go all the way to the bottom and I'm going
all the way to the bottom and I'm going to find this last div here and before
to find this last div here and before this all ends I'm going to add a new
this all ends I'm going to add a new component called free counter like this
component called free counter like this so it's a component that we don't have
so it's a component that we don't have yet it's going to be a self-closing
yet it's going to be a self-closing component and we're going to create it
component and we're going to create it in a second but first let's go ahead and
in a second but first let's go ahead and pass API limit count to it right here so
pass API limit count to it right here so what we are doing is we are fetching the
what we are doing is we are fetching the API limit count in a server component
API limit count in a server component because our server components have
because our server components have access to Prisma right here and then we
access to Prisma right here and then we are using that to pass it as a prop to
are using that to pass it as a prop to sidebar which is a client component so
sidebar which is a client component so that's why we need to do that that's why
that's why we need to do that that's why we could not fetch it inside of here and
we could not fetch it inside of here and then we are using it from here to pass
then we are using it from here to pass to pass it to this new component called
to pass it to this new component called free counter so let's go ahead and let's
free counter so let's go ahead and let's create that component now so inside of
create that component now so inside of your components folder create a new file
your components folder create a new file called free Dash
called free Dash counter.dsx like this let's go ahead and
counter.dsx like this let's go ahead and write export const free counter like
write export const free counter like this
this and return a div saying free counter
and return a div saying free counter like that now you can go back inside of
like that now you can go back inside of your software component and import the
your software component and import the free counter from dot slash free counter
free counter from dot slash free counter like this or you can modify it to be
like this or you can modify it to be from components like this so I'm just
from components like this so I'm just going to move this right here and I'm
going to move this right here and I'm also going to move my icons up here with
also going to move my icons up here with the Global Imports there we go so now
the Global Imports there we go so now you should not have an error beside this
you should not have an error beside this type error right here and if you expand
type error right here and if you expand your sidebar you should see the text
your sidebar you should see the text free counter in the lower bottom corner
free counter in the lower bottom corner great
great now I'm actually gonna try and keep my
now I'm actually gonna try and keep my sidebar expanded like this so make sure
sidebar expanded like this so make sure you're on desktop view when you're
you're on desktop view when you're working with this later on we're also
working with this later on we're also gonna have to add that to our mobile
gonna have to add that to our mobile sidebar but for now we're gonna wrap up
sidebar but for now we're gonna wrap up the desktop so make sure you are seeing
the desktop so make sure you are seeing this on desktop view great now let's go
this on desktop view great now let's go back inside of our free calendar and
back inside of our free calendar and let's create an interface for this so
let's create an interface for this so interface free counter props is gonna
interface free counter props is gonna take API limit count which is a type of
take API limit count which is a type of number as well like that let's go ahead
number as well like that let's go ahead and let's extract AKA limit count like
and let's extract AKA limit count like that and let's give it a type of free
that and let's give it a type of free counter props and give it a default
counter props and give it a default value of zero like that now let's go
value of zero like that now let's go ahead and do a simple trick which is
ahead and do a simple trick which is going to prevent this from causing any
going to prevent this from causing any hydration errors so const mounted
hydration errors so const mounted set mounted is going to be use state
set mounted is going to be use state from react and default is going to be
from react and default is going to be false so we automatically need to mark
false so we automatically need to mark this as a client component like this but
this as a client component like this but it's also not going to throw any errors
it's also not going to throw any errors if you don't write use client the reason
if you don't write use client the reason for that is because we are only using
for that is because we are only using this free counter component inside
this free counter component inside another client component so when you add
another client component so when you add a component to a client component and
a component to a client component and don't explicitly mark it here it's also
don't explicitly mark it here it's also going to be a client component but if I
going to be a client component but if I were to put this inside a server
were to put this inside a server component without this sign it will be a
component without this sign it will be a server component and this is going to
server component and this is going to throw an error so that's why it's still
throw an error so that's why it's still safe to mark this as use client great
safe to mark this as use client great now let's go ahead and write the use
now let's go ahead and write the use effect here also from react
effect here also from react and we're just going to set mounted to
and we're just going to set mounted to True like that and if we are not mounted
True like that and if we are not mounted in that case just return now so this way
in that case just return now so this way this is not going to be rendered on the
this is not going to be rendered on the server meaning that it's not going to
server meaning that it's not going to cause any hydration errors great now
cause any hydration errors great now let's go ahead and let's actually style
let's go ahead and let's actually style this so I'm going to give this div a
this so I'm going to give this div a class name of PX3 like this and inside
class name of PX3 like this and inside I'm going to add a card element from dot
I'm going to add a card element from dot slash UI card or you can move that to
slash UI card or you can move that to slash components like I'm going to do
slash components like I'm going to do there we go so now we have the card
there we go so now we have the card ready here let's go ahead and give this
ready here let's go ahead and give this card the class name of
card the class name of bg-110 and Border Dash zero
bg-110 and Border Dash zero great and inside I'm gonna create a card
great and inside I'm gonna create a card content component so I also imported
content component so I also imported that from slash components UI card let's
that from slash components UI card let's give this a class name of py-6 like this
give this a class name of py-6 like this and now you can see how I have a small
and now you can see how I have a small rounded element right here in the lower
rounded element right here in the lower corner great now inside I'm going to
corner great now inside I'm going to create a div with a class name of text
create a div with a class name of text Dash Center text SM text white margin
Dash Center text SM text white margin bottom four and space Dash Y dash 2 like
bottom four and space Dash Y dash 2 like that and inside of that div I'm going to
that and inside of that div I'm going to go ahead and open a paragraph where I'm
go ahead and open a paragraph where I'm going to go ahead and write the current
going to go ahead and write the current API limit count like this which you can
API limit count like this which you can see is zero right here the reason it's
see is zero right here the reason it's zero is because that is in my database
zero is because that is in my database right here it's zero so you can see how
right here it's zero so you can see how it changes once we increase it I'm going
it changes once we increase it I'm going to write API limit count I'm gonna add a
to write API limit count I'm gonna add a slash and now I'm gonna render how many
slash and now I'm gonna render how many accounts are available so for that we're
accounts are available so for that we're going to use our constant Max underscore
going to use our constant Max underscore free counts so make sure you import that
free counts so make sure you import that from add slash constants like this so
from add slash constants like this so now it's going to write 0 out of five
now it's going to write 0 out of five right here in your corner and just add a
right here in your corner and just add a text three generations like this so now
text three generations like this so now it says 0 out of five three generations
it says 0 out of five three generations great and what we have to do now is we
great and what we have to do now is we have to add another component from chat
have to add another component from chat CNN UI so let's go ahead let's visit the
CNN UI so let's go ahead let's visit the documentation right here and go into
documentation right here and go into components and find the progress
components and find the progress component right here as you can see
component right here as you can see let's see how we can install that so
let's see how we can install that so using this npx chat cnui at latest add
using this npx chat cnui at latest add progress I'm gonna copy this as npm I'm
progress I'm gonna copy this as npm I'm gonna go ahead in my terminal right here
gonna go ahead in my terminal right here I'm going to shut down the app for now
I'm going to shut down the app for now and I'm gonna go ahead and run this
and I'm gonna go ahead and run this Command right here so I'm just going to
Command right here so I'm just going to expand so you can see npx chat cn-ui at
expand so you can see npx chat cn-ui at latest add progress right here and
latest add progress right here and confirm the installation after that has
confirm the installation after that has been finished go ahead and run the app
been finished go ahead and run the app again so I'm gonna close this I'm gonna
again so I'm gonna close this I'm gonna expand my screen a bit and I'm going to
expand my screen a bit and I'm going to refresh my application here
refresh my application here great now that we have that just below
great now that we have that just below this paragraph right here go ahead and
this paragraph right here go ahead and add progress from dot slash UI progress
add progress from dot slash UI progress so don't accidentally import it from
so don't accidentally import it from Radix you need to import it from dot
Radix you need to import it from dot slash UI progress or you already know
slash UI progress or you already know what I'm going to do I'm going to rename
what I'm going to do I'm going to rename these two components because I like to
these two components because I like to be consistent great now that we have the
be consistent great now that we have the progress let's go ahead and let's give
progress let's go ahead and let's give it some values so it's gonna have
it some values so it's gonna have a class name of h-3 so I want it to be a
a class name of h-3 so I want it to be a bit thinner and I'm going to give it a
bit thinner and I'm going to give it a value of API limit count
value of API limit count divided by Max three counts times 100
divided by Max three counts times 100 like this beautiful and one more thing
like this beautiful and one more thing I'm going to do outside of this div
I'm going to do outside of this div encapsulating our paragraph and our
encapsulating our paragraph and our progress but still inside of card
progress but still inside of card content is I'm going to add a button
content is I'm going to add a button component from dot slash UI button and
component from dot slash UI button and you already know I'm going to move this
you already know I'm going to move this to components like that there we go so
to components like that there we go so now we have the button right here and
now we have the button right here and let's go ahead and write upgrade right
let's go ahead and write upgrade right here and let's give it an icon of Zap
here and let's give it an icon of Zap from Lucid react so make sure you import
from Lucid react so make sure you import zap from lucidreact and I'm going to
zap from lucidreact and I'm going to move this to the top right here great
move this to the top right here great let's give this zap a class name of W-4
let's give this zap a class name of W-4 h-4 margin left Dash 2 and fill Dash
h-4 margin left Dash 2 and fill Dash white like that beautiful and now what
white like that beautiful and now what I'm going to do is I'm going to give
I'm going to do is I'm going to give this a class name of w Dash full and one
this a class name of w Dash full and one thing I want to do is I want to make
thing I want to do is I want to make this upgrade button look a bit special I
this upgrade button look a bit special I want to give this a gradient I want to
want to give this a gradient I want to make this look more
make this look more I want to make this look different than
I want to make this look different than all the others buttons right because
all the others buttons right because this is our upgrade button so what I
this is our upgrade button so what I could technically do is just modify the
could technically do is just modify the background in the class name but since I
background in the class name but since I want to reuse this button in our model
want to reuse this button in our model as well I think it's cool that we
as well I think it's cool that we utilize the fact that this button
utilize the fact that this button component is actually inside of our
component is actually inside of our components folder and we can freely add
components folder and we can freely add our own variant to it so let's see how
our own variant to it so let's see how we can do that I'm going to close
we can do that I'm going to close everything and I'm going to go inside of
everything and I'm going to go inside of my components folder inside UI and I'm
my components folder inside UI and I'm going to find this button.dsx so we
going to find this button.dsx so we already took a look at this when I added
already took a look at this when I added it in the beginning of the video but
it in the beginning of the video but what we're going to do now is we're
what we're going to do now is we're going to add another variant right here
going to add another variant right here so the same way as default destructive
so the same way as default destructive outline secondary ghost and Link exist
outline secondary ghost and Link exist we're going to go ahead and after the
we're going to go ahead and after the link or whatever is your last one go
link or whatever is your last one go ahead and add premium or whatever you
ahead and add premium or whatever you want you can name this absolutely
want you can name this absolutely anything
anything and let's go ahead and give it a value
and let's go ahead and give it a value of BG Dash gradient Dash 2 right like
of BG Dash gradient Dash 2 right like this let's give it a from Dash Indigo
this let's give it a from Dash Indigo 500 via Dash purple Dash 500 to dash
500 via Dash purple Dash 500 to dash pink Dash 500 tax dash light and Border
pink Dash 500 tax dash light and Border Dash zero like this so I'm gonna expand
Dash zero like this so I'm gonna expand this so you can see how it looks in one
this so you can see how it looks in one line uh even more okay I can't expand it
line uh even more okay I can't expand it that much but I can do this so VG
that much but I can do this so VG gradient to write from Indigo 500 via
gradient to write from Indigo 500 via purple 500 to Pink 500 text white and
purple 500 to Pink 500 text white and Border zero like this and now let's go
Border zero like this and now let's go ahead back inside of our free counter
ahead back inside of our free counter component right here expand this so you
component right here expand this so you can see the sidebar on desktop and go
can see the sidebar on desktop and go ahead and give this button a variant of
ahead and give this button a variant of Premium you can see how it also Auto
Premium you can see how it also Auto completes and once I save there we go
completes and once I save there we go you can see how premium this button now
you can see how premium this button now looks and now let's actually go ahead
looks and now let's actually go ahead and check if this accounter is working
and check if this accounter is working so I'm gonna go ahead and refresh
so I'm gonna go ahead and refresh everything and I'm gonna go ahead and
everything and I'm gonna go ahead and well I will repeat one of these
well I will repeat one of these questions it doesn't really matter and
questions it doesn't really matter and let's see if this is going to increase
let's see if this is going to increase right here so genius is thinking and
right here so genius is thinking and there we go it says that I've used up
there we go it says that I've used up one out of five of my three generations
one out of five of my three generations and my counter right here is starting to
and my counter right here is starting to fill but why is this working how did it
fill but why is this working how did it automatically refill well let me explain
automatically refill well let me explain that to you so what are we doing where
that to you so what are we doing where are we fetching this information we are
are we fetching this information we are fetching that inside a server component
fetching that inside a server component called layout.tsx right here so we are
called layout.tsx right here so we are calling awaiting API limit count that
calling awaiting API limit count that the only thing that that is doing is
the only thing that that is doing is calling Prisma so how did it know to
calling Prisma so how did it know to refresh once I did this generation what
refresh once I did this generation what made it uh update the values right well
made it uh update the values right well let me explain what let's go inside of
let me explain what let's go inside of the app folder dashboard routes
the app folder dashboard routes conversation
conversation page.tsx right here and let's take a
page.tsx right here and let's take a look at what we do once we submit so you
look at what we do once we submit so you can see that in the try block we
can see that in the try block we actually call the API request and then
actually call the API request and then we just assign the data so nothing in
we just assign the data so nothing in here actually refetches the server
here actually refetches the server component but in our finally block this
component but in our finally block this is what I told you I was going explain
is what I told you I was going explain later this is
later this is router.refresh so router.refresh is used
router.refresh so router.refresh is used to rehydrate all server components
to rehydrate all server components fetching the newest data so once you do
fetching the newest data so once you do router.refresh it doesn't really matter
router.refresh it doesn't really matter where you are all server components are
where you are all server components are going to get refreshed with new data
going to get refreshed with new data from the database so that's why I think
from the database so that's why I think it's really cool to work with server and
it's really cool to work with server and client components in extra thin perfect
client components in extra thin perfect so that's why it works so if you don't
so that's why it works so if you don't have this in your final block you're
have this in your final block you're probably not getting any updates so make
probably not getting any updates so make sure you have this in every single on
sure you have this in every single on submit in our uh in all of our apps
submit in our uh in all of our apps right here but since we copied and
right here but since we copied and pasted the code I have it everywhere
pasted the code I have it everywhere great amazing job we of course could
great amazing job we of course could change this color a little bit I think
change this color a little bit I think it looks kind of weird so let me see if
it looks kind of weird so let me see if we can do that quickly
we can do that quickly so what we can actually do is we can
so what we can actually do is we can change both this progress color and the
change both this progress color and the color of our primary buttons in a color
color of our primary buttons in a color that you saw in the intro video which is
that you saw in the intro video which is a light purple color so in order to do
a light purple color so in order to do that let's go ahead and let's close
that let's go ahead and let's close everything and let's go inside of our
everything and let's go inside of our app folder and find
app folder and find globals.css right here now inside the
globals.css right here now inside the layer base root right here go ahead and
layer base root right here go ahead and find the dash dash primary so this is an
find the dash dash primary so this is an hsl value right here and I'm going to
hsl value right here and I'm going to modify it to the color that I like so
modify it to the color that I like so I'm going to remove all this in primary
I'm going to remove all this in primary and I'm going to write 2 4 8 90 and 66
and I'm going to write 2 4 8 90 and 66 percent like this and I'm going to save
percent like this and I'm going to save and look at this now you can see that my
and look at this now you can see that my button is light purple and you can see
button is light purple and you can see that my progress bar is light purple as
that my progress bar is light purple as well perfect so that's exactly what I
well perfect so that's exactly what I wanted beautiful job you just finished
wanted beautiful job you just finished the counter and now what we're going to
the counter and now what we're going to do is we're going to add a pro model
do is we're going to add a pro model which opens and then finally connects to
which opens and then finally connects to stripe
stripe now let's create our premium model which
now let's create our premium model which is going to open when we click on
is going to open when we click on upgrade or when we fill up our
upgrade or when we fill up our generations and then get a 403 error
generations and then get a 403 error when we try a generation similarity to
when we try a generation similarity to do that first we have to install a
do that first we have to install a package called to stand so let's go
package called to stand so let's go ahead and let's go inside of our
ahead and let's go inside of our terminal right here
terminal right here and go ahead and run npm install to
and go ahead and run npm install to stand like this wait a couple of seconds
stand like this wait a couple of seconds for it to install and run the app again
for it to install and run the app again and refresh if you have shut it down and
and refresh if you have shut it down and now let's go ahead and create a hooks
now let's go ahead and create a hooks folder in the root of our application
folder in the root of our application like this and inside create a new file
like this and inside create a new file called use Dash Pro Dash model dot ESX
called use Dash Pro Dash model dot ESX like this go ahead and import create
like this go ahead and import create from not from domain but from to stand
from not from domain but from to stand and just let's go ahead and write an
and just let's go ahead and write an interface for our model so interface use
interface for our model so interface use pro model store like this it's gonna
pro model store like this it's gonna have is open which is a Boolean on open
have is open which is a Boolean on open which is a void
which is a void and on close which is a void as well and
and on close which is a void as well and now let's go ahead and write export
now let's go ahead and write export const use pro model to be create
const use pro model to be create go ahead and open pointy brackets use
go ahead and open pointy brackets use pro model store go ahead and open
pro model store go ahead and open parenthesis open parenthesis again write
parenthesis open parenthesis again write this set prop write an arrow function
this set prop write an arrow function which is going to immediately return an
which is going to immediately return an object like this it is open default
object like this it is open default value to false on open
value to false on open is going to be an arrow function which
is going to be an arrow function which is going to call the set prop which we
is going to call the set prop which we extracted right here and it's going to
extracted right here and it's going to set an object is open to be true like
set an object is open to be true like that go ahead and copy and paste that
that go ahead and copy and paste that rename this to on close and this one is
rename this to on close and this one is going to set is open to false like this
going to set is open to false like this so this gives us Global State controls
so this gives us Global State controls for opening and closing the model from
for opening and closing the model from wherever we want now let's go ahead and
wherever we want now let's go ahead and let's create a provider for our model
let's create a provider for our model because it's going to have to be
because it's going to have to be rendered uh carefully so we don't cause
rendered uh carefully so we don't cause any hydration errors so in components
any hydration errors so in components right here create a new file called
right here create a new file called Model Dash
Model Dash provider.tsx like this and inside go
provider.tsx like this and inside go ahead and Mark this as use client that's
ahead and Mark this as use client that's important and Export const model
important and Export const model provider like this
provider like this go ahead and add is mounted set is
go ahead and add is mounted set is mounted
mounted from US state which is from react give
from US state which is from react give it the default value of false go ahead
it the default value of false go ahead and add use effect like this
and set is mounted to True inside and if it's not mounted in that case return
it's not mounted in that case return null like this otherwise return a
null like this otherwise return a fragment and let's go ahead and add pro
fragment and let's go ahead and add pro model inside which of course does not
model inside which of course does not exist yet so let's go ahead and let's
exist yet so let's go ahead and let's quickly create our pro model so inside
quickly create our pro model so inside of components create a new file called
of components create a new file called Pro Dash model dot vsx export const pro
Pro Dash model dot vsx export const pro model like this and I'm just going to
model like this and I'm just going to return hey div saying pro model like
return hey div saying pro model like this for now and go ahead and Mark this
this for now and go ahead and Mark this as use client just to be safe and now go
as use client just to be safe and now go back inside the model provider and
back inside the model provider and import the pro model from dot slash pro
import the pro model from dot slash pro model or slash components pro model like
model or slash components pro model like this
this now we have to add this model provider
now we have to add this model provider to our layout application so let's go
to our layout application so let's go ahead and let's go inside of a layout of
ahead and let's go inside of a layout of our app so not inside dashboard but
our app so not inside dashboard but inside of our app right here so this
inside of our app right here so this main layout root layout file and inside
main layout root layout file and inside of the body let's go ahead and collapse
of the body let's go ahead and collapse this
this and just above the children let's add
and just above the children let's add model Provider from dot slash components
model Provider from dot slash components model provider like this there we go so
model provider like this there we go so now we have the model provider here and
now we have the model provider here and you can see the text pro model right
you can see the text pro model right here we are of course going to modify
here we are of course going to modify this to actually work as a model so in
this to actually work as a model so in order to do that we can we're gonna have
order to do that we can we're gonna have to go and add another chat CN component
to go and add another chat CN component and that component is going to be called
and that component is going to be called dialog right here so you can see how
dialog right here so you can see how this is going to look like great so this
this is going to look like great so this is the command we are going to need MPX
is the command we are going to need MPX chat cnui at latest add dialog I'm going
chat cnui at latest add dialog I'm going to copy this as npm go inside of my
to copy this as npm go inside of my terminal and I'm gonna run npx chat cnui
terminal and I'm gonna run npx chat cnui at latest
at latest add dialogue like this so just press
add dialogue like this so just press enter and confirm this installation and
enter and confirm this installation and then you can go ahead and run your
then you can go ahead and run your application again
application again great so I'm gonna expand this and I'm
great so I'm gonna expand this and I'm gonna refresh this
gonna refresh this okay and now let's go ahead and let's
okay and now let's go ahead and let's replace this div with dialog component
replace this div with dialog component from dot slash UI dialog so make sure
from dot slash UI dialog so make sure you don't accidentally import this from
you don't accidentally import this from Radix like this and you already know I'm
Radix like this and you already know I'm gonna rename this to slash components
gonna rename this to slash components there we go and now let's give it the
there we go and now let's give it the default value of open like this and now
default value of open like this and now let's add dialog content from add slash
let's add dialog content from add slash components dialog so again make sure you
components dialog so again make sure you have no Radix Imports inside I'm already
have no Radix Imports inside I'm already going to collapse this so they all
going to collapse this so they all Import in that manner and inside of
Import in that manner and inside of dialog content add a dialog header also
dialog content add a dialog header also from UI dialog like this and inside add
from UI dialog like this and inside add a dialog title from components UI dialog
a dialog title from components UI dialog again and give this a class name of flex
again and give this a class name of flex justify Dash center items Dash Center
justify Dash center items Dash Center Flex Dash call Gap Dash y-4 and padding
Flex Dash call Gap Dash y-4 and padding bottom to like this
bottom to like this and let's just write upgrade to genius
and let's just write upgrade to genius like this and there we go now you should
like this and there we go now you should see a model right here but you can see
see a model right here but you can see that our sidebar is actually uh higher
that our sidebar is actually uh higher of a higher Z index than our model so
of a higher Z index than our model so let's quickly fix that by going back
let's quickly fix that by going back inside of our sidebar component right
inside of our sidebar component right here and let's see what's going on here
here and let's see what's going on here uh or maybe it's not the sidebar I think
uh or maybe it's not the sidebar I think it actually might be our layout file so
it actually might be our layout file so go ahead inside of dashboard inside
go ahead inside of dashboard inside layout right here and there we go so we
layout right here and there we go so we put the Z index but I think we don't
put the Z index but I think we don't actually need it so yes you can see how
actually need it so yes you can see how now the model is above our layout right
now the model is above our layout right here great so I'm going to use that and
here great so I'm going to use that and now go safely back inside of the pro
now go safely back inside of the pro model right here
model right here and before we do anything let's actually
and before we do anything let's actually connect this to our two-stand store
connect this to our two-stand store which we created so go ahead and let's
which we created so go ahead and let's add the pro model controls here so const
add the pro model controls here so const pro model is equal use pro model from
pro model is equal use pro model from add slash hooks use pro model and you're
add slash hooks use pro model and you're going to change this hard-coded open to
going to change this hard-coded open to be pro model that is open like this and
be pro model that is open like this and you're gonna change on open change to be
you're gonna change on open change to be promodel dot on close like this great so
promodel dot on close like this great so now you can go ahead and go inside of
now you can go ahead and go inside of your use pro model for example and
your use pro model for example and change the default value of is open to
change the default value of is open to true and that is going to open your
true and that is going to open your model so just do that for now so your
model so just do that for now so your model is visible so you can see what
model is visible so you can see what you're developing if you change it to
you're developing if you change it to false it's going to go away so just
false it's going to go away so just bring it back it sure you can even
bring it back it sure you can even refresh if it's not working great so now
refresh if it's not working great so now that you have that and we have these
that you have that and we have these controls here let's go ahead and let's
controls here let's go ahead and let's add another Library sorry another
add another Library sorry another component from chat CN called batch so
component from chat CN called batch so I'm going to go ahead add inside batch
I'm going to go ahead add inside batch right here
right here and I'm going to add npx chat cnui at
and I'm going to add npx chat cnui at latest add batch so I'm going to expand
latest add batch so I'm going to expand this a bit more so terminal is better of
this a bit more so terminal is better of better visibility
better visibility and there we go so ntx chat scene UI at
and there we go so ntx chat scene UI at latest add batch like this and just
latest add batch like this and just confirm the installation and run your
confirm the installation and run your app again great so I'm gonna expand this
app again great so I'm gonna expand this I'm gonna refresh this
I'm gonna refresh this make sure the app is running uh
make sure the app is running uh correctly there we go so now alongside
correctly there we go so now alongside this upgrade to genius just below that
this upgrade to genius just below that add a batch component from dot slash UI
add a batch component from dot slash UI batch and I'm gonna rename that to slash
batch and I'm gonna rename that to slash components badge like this and inside of
components badge like this and inside of that Badge go ahead and write Pro like
that Badge go ahead and write Pro like this and now let's go ahead and give the
this and now let's go ahead and give the class name of uppercase Dash text Dash
class name of uppercase Dash text Dash whoops uppercase like this text SM
whoops uppercase like this text SM and padding y one like this great and
and padding y one like this great and now what I want to do is I want to
now what I want to do is I want to create a div right here encapsulating
create a div right here encapsulating both of these items here
and I want to give this a class name blacks items Dash Center like this I'll
blacks items Dash Center like this I'll make sure it's class name like this so
make sure it's class name like this so Flex items Dash Center Gap Dash X-2 font
Flex items Dash Center Gap Dash X-2 font dashboard py dash one like this there we
dashboard py dash one like this there we go and I want this badge to be of a
go and I want this badge to be of a gradient similar to what we have inside
gradient similar to what we have inside of this upgrade button so I want it to
of this upgrade button so I want it to look similar so let's go ahead and do
look similar so let's go ahead and do that so just refresh your page if you
that so just refresh your page if you close the model and make sure that your
close the model and make sure that your default value here is true we are of
default value here is true we are of course going to change this to false
course going to change this to false later but just for development part it's
later but just for development part it's easier to do it like this so what we're
easier to do it like this so what we're going to do now is we're gonna go inside
going to do now is we're gonna go inside of our components UI and find the batch
of our components UI and find the batch component right here and the same thing
component right here and the same thing we did with the button we're gonna add
we did with the button we're gonna add another variant Hill uh here called
another variant Hill uh here called premium like this it's going to be BG
premium like this it's going to be BG Dash gradient Dash 2 Dash R from Dash
Dash gradient Dash 2 Dash R from Dash Indigo Dash 500 via Dash purple Dash 500
Indigo Dash 500 via Dash purple Dash 500 102 Dash pink Dash 500 and tax dot
102 Dash pink Dash 500 and tax dot primary Dash foreground like this
primary Dash foreground like this uh and also border Dash zero and now
uh and also border Dash zero and now let's go back inside of our pro model
let's go back inside of our pro model here and let's give this badge a variant
here and let's give this badge a variant of Premium like this there we go now it
of Premium like this there we go now it looks much much nicer so basically in
looks much much nicer so basically in the badge we added the same value we
the badge we added the same value we have in our button component right so
have in our button component right so this is the premium variant that we
this is the premium variant that we added right here and then we used it in
added right here and then we used it in the pro model variant premium like this
the pro model variant premium like this great great job now let's go back and
great great job now let's go back and let's focus on the pro model here so
let's focus on the pro model here so let's add some content inside
let's add some content inside so just outside of dialogue content
so just outside of dialogue content right of dialog title right here
right of dialog title right here let's go ahead and add dialog
let's go ahead and add dialog description right here and yes I
description right here and yes I accidentally imported it from Radix
accidentally imported it from Radix dialog so make sure you don't do that
dialog so make sure you don't do that you have to import it from components UI
you have to import it from components UI dialog like that so dialog description
dialog like that so dialog description component here inside uh give you the
component here inside uh give you the class name of text Dash Center
class name of text Dash Center pt-2 space Dash y-2 text Dash
pt-2 space Dash y-2 text Dash sync-900 and phone Dash medium like this
sync-900 and phone Dash medium like this and inside we're going to iterate over
and inside we're going to iterate over our
our over our tools so we're going to get the
over our tools so we're going to get the tools from the dashboard so go ahead and
tools from the dashboard so go ahead and find the dashboard page so routes
find the dashboard page so routes dashboard page.tsx and you can either
dashboard page.tsx and you can either add this to Global constants or copy it
add this to Global constants or copy it you know you can find a smarter way if
you know you can find a smarter way if you want to but I'm just going to go
you want to but I'm just going to go ahead and copy this tools constant for
ahead and copy this tools constant for now so make sure you are in dashboard
now so make sure you are in dashboard routes dashboard page find the constant
routes dashboard page find the constant tools
tools copy this and you can just paste it
copy this and you can just paste it inside of the pro model
inside of the pro model just like this right and I'm also going
just like this right and I'm also going to copy all of the icons from this page
to copy all of the icons from this page right here so I'm going to copy this
right here so I'm going to copy this imports from lucidreact and I'm gonna go
imports from lucidreact and I'm gonna go ahead and paste them here and the only
ahead and paste them here and the only one we don't need is Arrow right like
one we don't need is Arrow right like this
this and we're actually not gonna need the
and we're actually not gonna need the href at all in any of this
href at all in any of this because we're not gonna redirect from
because we're not gonna redirect from anywhere we're just gonna display all of
anywhere we're just gonna display all of the tools available in Pro of our
the tools available in Pro of our application great so inside the dialog
application great so inside the dialog description now go ahead and write
description now go ahead and write tools.map individual tool like that and
tools.map individual tool like that and let's go ahead and add a card from that
let's go ahead and add a card from that dot slash UI card or rename it to slash
dot slash UI card or rename it to slash components like this
components like this great let's go ahead and give it some
great let's go ahead and give it some properties so key is going to be tool
properties so key is going to be tool dot href like this uh sorry not href
dot href like this uh sorry not href it's gonna be uh dot what is the is it
it's gonna be uh dot what is the is it label yes like this
label yes like this uh and let's add a class name here p
uh and let's add a class name here p dash three border Dash Black slash F5
dash three border Dash Black slash F5 Flats items Dash Center and justify Dash
Flats items Dash Center and justify Dash between like this
between like this great inside of that create a new div
great inside of that create a new div with the class name of flex items Dash
with the class name of flex items Dash Center and GAP Dash
Center and GAP Dash x-4 make sure you don't misspell class
x-4 make sure you don't misspell class name like I did
name like I did great inside of that create a new div
great inside of that create a new div with a class name which is going to be
with a class name which is going to be dynamic so CN make sure you import that
dynamic so CN make sure you import that from s slash lib utils so as I did right
from s slash lib utils so as I did right here we have the CN here open
here we have the CN here open parenthesis let's write a default class
parenthesis let's write a default class of w 6 and H uh my apologies now uh the
of w 6 and H uh my apologies now uh the first Dynamic class is p-2 W Dash fit
first Dynamic class is p-2 W Dash fit and rounded MD and the dynamic class is
and rounded MD and the dynamic class is tool dot PG color like that
tool dot PG color like that and then inside we're going to go ahead
and then inside we're going to go ahead and render tool dot icon which is a
and render tool dot icon which is a self-closing tag and give you the class
self-closing tag and give you the class name which is also Dynamic so
cnw-6h-6 and dynamic is going to be tool dot color like this there we go so now
dot color like this there we go so now we have all the icons of our tools here
we have all the icons of our tools here great and outside this div encapsulating
great and outside this div encapsulating our icon create a new div and render
our icon create a new div and render tool.label inside
tool.label inside let's just go ahead and give this a
let's just go ahead and give this a class name
class name bold and text SM like this great and
bold and text SM like this great and outside of this div right here but still
outside of this div right here but still inside of the card we're gonna add an
inside of the card we're gonna add an icon check from Lucid react
icon check from Lucid react so the check should now appear at the
so the check should now appear at the end so make sure you've imported check
end so make sure you've imported check from lucidreact alongside this Imports
from lucidreact alongside this Imports which we copied from the dashboard and
which we copied from the dashboard and let's give this a class name of text
let's give this a class name of text primary and
primary and W5 and h-5 like this there we go great
W5 and h-5 like this there we go great now that we have that let's go ahead and
now that we have that let's go ahead and add dialogue footer from add slash
add dialogue footer from add slash components UI dialog so make sure you
components UI dialog so make sure you have imported that right here
have imported that right here uh and let's go ahead and add a button
uh and let's go ahead and add a button from dot slash UI button or you can
from dot slash UI button or you can rename it to component Cy button like
rename it to component Cy button like this and inside we're gonna write
this and inside we're gonna write upgrade like this and we're going to add
upgrade like this and we're going to add a zap icon from Lucid react so the same
a zap icon from Lucid react so the same thing with it in our sidebar like this
thing with it in our sidebar like this give it a class name of W-4 h-4 margin
give it a class name of W-4 h-4 margin left 2 and fill Dash white like this and
left 2 and fill Dash white like this and now let's go ahead and give some props
now let's go ahead and give some props here so size is going to be large
here so size is going to be large variant is going to be premium and class
variant is going to be premium and class name is going to be W Dash full like
name is going to be W Dash full like this great and what we are going to do
this great and what we are going to do now actually uh well we're gonna go
now actually uh well we're gonna go ahead
ahead and we are going to change the way we
and we are going to change the way we open the pro model so now we can close
open the pro model so now we can close everything and go inside our use pro
everything and go inside our use pro model store and change the value of ease
model store and change the value of ease open to false like this and let's find
open to false like this and let's find proper ways to open this model so the
proper ways to open this model so the first thing I want to do is I want to
first thing I want to do is I want to open it when I click upgrade in the
open it when I click upgrade in the sidebar so for that let's go inside of
sidebar so for that let's go inside of our components not inside the UI so I'm
our components not inside the UI so I'm going to close everything so it's easier
going to close everything so it's easier and I'm going to try and expand this so
and I'm going to try and expand this so just be patient for a second all right
just be patient for a second all right so inside of components inside of free
so inside of components inside of free counter right here we have this button
counter right here we have this button which says upgrade so what we are going
which says upgrade so what we are going to do is we are going to add a constant
to do is we are going to add a constant pro model to be use pro model
pro model to be use pro model just above our mounted U State here and
just above our mounted U State here and make sure you import the use pro model
make sure you import the use pro model from add slash hooks use pro model like
from add slash hooks use pro model like this
this great and now that you have that pro
great and now that you have that pro model you're going to add an on click
model you're going to add an on click here to this button to say pro model dot
here to this button to say pro model dot on open like this and now when I click
on open like this and now when I click on the upgrade you can see that it shows
on the upgrade you can see that it shows this upgrade to genius right here great
this upgrade to genius right here great and now what we have to do is we have to
and now what we have to do is we have to add the pro model to open every time we
add the pro model to open every time we capture a 403 error so let's go ahead
capture a 403 error so let's go ahead and do that now so there are certainly
and do that now so there are certainly different ways you can do this you can
different ways you can do this you can find uh one middleware which is going to
find uh one middleware which is going to look for four or three errors but let's
look for four or three errors but let's do it the simplest way for now I'm gonna
do it the simplest way for now I'm gonna go inside of my dashboard I'm gonna find
go inside of my dashboard I'm gonna find the conversation app first I'm gonna go
the conversation app first I'm gonna go inside of page.tsx and there we go we
inside of page.tsx and there we go we wrote it to do here open pro model so
wrote it to do here open pro model so we're going to search through all of our
we're going to search through all of our to-do's and we're going to add open pro
to-do's and we're going to add open pro model wherever we need to do that so
model wherever we need to do that so what I want to do now is in this catch
what I want to do now is in this catch form we have to check if the error is a
form we have to check if the error is a 403 three so I'm going to remove this
403 three so I'm going to remove this and I'm going to remove this as well and
and I'm going to remove this as well and I'm going to write if error question
I'm going to write if error question mark response question mark status is
mark response question mark status is identical to 403 in that case we're
identical to 403 in that case we're going to open the pro model so first we
going to open the pro model so first we have to add the pro model so just above
have to add the pro model so just above the router const pro model is equal use
the router const pro model is equal use pro model from ad slash hooks use pro
pro model from ad slash hooks use pro model like this
model like this and now in here in this F block just go
and now in here in this F block just go ahead and run promodel dot on open like
ahead and run promodel dot on open like this great and make sure you add
this great and make sure you add question marks here because errors can
question marks here because errors can be uh in we don't have a guarantee that
be uh in we don't have a guarantee that it's always going to be this 403 error
it's always going to be this 403 error which we are expecting it can be any
which we are expecting it can be any error and it could be uh it could have a
error and it could be uh it could have a different structure so that's why I'm
different structure so that's why I'm putting question marks because this is
putting question marks because this is one of the options that I know might
one of the options that I know might happen and if that option happens we
happen and if that option happens we have to open the pro model so let me
have to open the pro model so let me just explain when this happens so if you
just explain when this happens so if you go inside of your conversational route
go inside of your conversational route you can see that if you don't have a
you can see that if you don't have a free trial in that case we throw a next
free trial in that case we throw a next response error with a 403 status so
response error with a 403 status so that's why it's very important that you
that's why it's very important that you put a 403 here please make sure that
put a 403 here please make sure that wherever you do uh in the in this if
wherever you do uh in the in this if block if there is no free trial throw a
block if there is no free trial throw a 403 error that is very very important so
403 error that is very very important so now let's go ahead and let's try and
now let's go ahead and let's try and fill this up so I'm just gonna ask you
fill this up so I'm just gonna ask you the couple of questions so it fills up
the couple of questions so it fills up this three generations right here on the
this three generations right here on the bottom until we get
bottom until we get until we get to uh five out of five
until we get to uh five out of five or you can simply go to Prisma and
or you can simply go to Prisma and increase it here as well if you want to
increase it here as well if you want to this seems to be taking uh each time so
this seems to be taking uh each time so I'm gonna go ahead and do that so in
I'm gonna go ahead and do that so in here I'm going to increase it to five
here I'm going to increase it to five out of five and click save and now each
out of five and click save and now each of my requests should throw an error so
of my requests should throw an error so you can see I have a 505 here I'm going
you can see I have a 505 here I'm going to go ahead and write test inside and
to go ahead and write test inside and there we go so we caught the 403 error
there we go so we caught the 403 error and we opened a model so if this is not
and we opened a model so if this is not working for you let's go ahead and check
working for you let's go ahead and check everything you need to do first of all
everything you need to do first of all make sure that you are in the dashboard
make sure that you are in the dashboard routes conversation page.tsx make sure
routes conversation page.tsx make sure that you are in the on submit function
that you are in the on submit function make sure that you catch the error and
make sure that you catch the error and that you check for error.response DOT
that you check for error.response DOT status 403 next make sure that in the
status 403 next make sure that in the equivalent API sorry this is for code so
equivalent API sorry this is for code so the equivalent route conversation
the equivalent route conversation route.ds make sure that you're actually
route.ds make sure that you're actually throwing a 403 status if there is no
throwing a 403 status if there is no free trial there we go so you can see
free trial there we go so you can see how amazing this looks perfect and now
how amazing this looks perfect and now we have to do that for all others as
we have to do that for all others as well so the simple way we can do that is
well so the simple way we can do that is if you copied and pasted the code we did
if you copied and pasted the code we did I'm just going to search for to do like
I'm just going to search for to do like this and you can see that I have all the
this and you can see that I have all the places where I need to add a pro model
places where I need to add a pro model but in case you didn't add the comment
but in case you didn't add the comment don't worry I'm going to show you
don't worry I'm going to show you exactly where this is so let's see click
exactly where this is so let's see click on this one and I'm gonna show you
on this one and I'm gonna show you exactly what that is so go inside of
exactly what that is so go inside of your dashboard routes code
your dashboard routes code page.tsx right here and I'm also going
page.tsx right here and I'm also going to open the conversation just so I can
to open the conversation just so I can copy and paste stuff so inside of the
copy and paste stuff so inside of the cache function I'm just going to copy
cache function I'm just going to copy this if Clause right here and I'm going
this if Clause right here and I'm going to replace this console log and this
to replace this console log and this right here and of course we have to add
right here and of course we have to add the pro model so let's go to the top of
the pro model so let's go to the top of the code page right here at const pro
the code page right here at const pro model to be use pro model from hooks use
model to be use pro model from hooks use pro model like this let's go ahead
pro model like this let's go ahead and let's check code generation now so
and let's check code generation now so if I try something inside there we go I
if I try something inside there we go I have a model here as well perfect now
have a model here as well perfect now let's go ahead and I'm already gonna
let's go ahead and I'm already gonna copy this
copy this okay let's go ahead and go to the next
okay let's go ahead and go to the next one so this is
one so this is routes uh which one is it
routes uh which one is it uh where are my image okay so this is
uh where are my image okay so this is routes image page.tsx go inside of here
routes image page.tsx go inside of here replace this
replace this there we go let's add the pro model so
there we go let's add the pro model so const
const like this
like this there we go let's test out the image
there we go let's test out the image generation
generation works as well great now uh let's do
works as well great now uh let's do either video or music generation so
either video or music generation so let's see but we are here's some music
let's see but we are here's some music let's do music first so same thing here
let's do music first so same thing here uh I'm just gonna copy and paste it from
uh I'm just gonna copy and paste it from here
here so remove the comment and the console
so remove the comment and the console log in the catch block and add the pro
log in the catch block and add the pro model to the top so conspro model is use
model to the top so conspro model is use pro model like this
pro model like this there we go I'm already gonna copy it
there we go I'm already gonna copy it and let's just test if music is
and let's just test if music is protected as well
protected as well so I'm gonna write anything here there
so I'm gonna write anything here there we go the pro model has opened and now
we go the pro model has opened and now let's go ahead and finish the last one
let's go ahead and finish the last one which is video route so go inside of
which is video route so go inside of your uh
your uh video folder page.dsx right here
video folder page.dsx right here and just go ahead and paste this here
and just go ahead and paste this here and add a pro model one last time
there we go perfect and now if we test the video
perfect and now if we test the video there we go works as well one thing that
there we go works as well one thing that I think is not working is the mobile
I think is not working is the mobile sidebar so if I test it right here there
sidebar so if I test it right here there we go here it says 0 out of five
we go here it says 0 out of five regenerations but in desktop it says 5
regenerations but in desktop it says 5 out of five so why is that happening
out of five so why is that happening well that's because we did not pass the
well that's because we did not pass the API account from our dashboard to our
API account from our dashboard to our mobile sidebar so let's go ahead and
mobile sidebar so let's go ahead and let's see how we can fix that
let's see how we can fix that so what we have to do is we have to go
so what we have to do is we have to go inside of our components inside navbar
inside of our components inside navbar right here and this is a server
right here and this is a server component meaning that we have we can
component meaning that we have we can fetch stuff from here and don't have to
fetch stuff from here and don't have to prop drill through dashboard the layout
prop drill through dashboard the layout like we did with the sidebar so inside
like we did with the sidebar so inside your navbar component where you hold the
your navbar component where you hold the mobile sidebar and the user button so
mobile sidebar and the user button so it's located here in components nav bar
it's located here in components nav bar right here you can go ahead and write
right here you can go ahead and write const API limit count to be await get
const API limit count to be await get API limit count from s slash lib API
API limit count from s slash lib API limit of course we have an error that we
limit of course we have an error that we are using await in a arrow function
are using await in a arrow function which is not a synchronous so just Mark
which is not a synchronous so just Mark the snapbar as asynchronous like this
the snapbar as asynchronous like this now when we have this API limit count
now when we have this API limit count you can go ahead and pass it to mobile
you can go ahead and pass it to mobile sidebar as API limit count like this now
sidebar as API limit count like this now go ahead and inside of your mobile
go ahead and inside of your mobile sidebar so mobile sidebar inside the
sidebar so mobile sidebar inside the components folder right here let's go
components folder right here let's go ahead and create an interface so
ahead and create an interface so interface mobile sidebar props it's
interface mobile sidebar props it's gonna API limit count which is a type of
gonna API limit count which is a type of number let's go ahead
number let's go ahead and let's extract the API limit count
and let's extract the API limit count and let's give it a prop type of mobile
and let's give it a prop type of mobile sidebar props like this and now that we
sidebar props like this and now that we have the API limit count we can just
have the API limit count we can just pass that to this sidebar inside of
pass that to this sidebar inside of sheet content right here there we go and
sheet content right here there we go and now our mobile sidebar works perfectly
now our mobile sidebar works perfectly as well great great job what we are
as well great great job what we are going to do next is actual stripe
going to do next is actual stripe connection and the subscription creation
connection and the subscription creation so in order to integrate stripe first
so in order to integrate stripe first thing we have to do is create a stripe
thing we have to do is create a stripe account so go to stripe.com or Google
account so go to stripe.com or Google stripe and go ahead and find a way to
stripe and go ahead and find a way to log in or create an account so I already
log in or create an account so I already have that so I'm going to go ahead and
have that so I'm going to go ahead and just enter my dashboard once you're
just enter my dashboard once you're inside you're going to see a screen
inside you're going to see a screen similar to this so what we want to do is
similar to this so what we want to do is you want to find this uh top right
you want to find this uh top right corner and you want to click create a
corner and you want to click create a new account right here or maybe this was
new account right here or maybe this was what you initially did so if you already
what you initially did so if you already did that fine but since I already have
did that fine but since I already have this account my screen is a bit
this account my screen is a bit different so I'm going to name this AI
different so I'm going to name this AI SAS tutorial like this and I'm going to
SAS tutorial like this and I'm going to click create an account right here
click create an account right here so now what we have to do is we have to
so now what we have to do is we have to copy our API keys so go ahead and click
copy our API keys so go ahead and click for API keys for developers or if you
for API keys for developers or if you don't have this screen so let me just
don't have this screen so let me just zoom in so if you don't have this screen
zoom in so if you don't have this screen API keys for developers you can just
API keys for developers you can just click for developers here and basically
click for developers here and basically you can find it somewhere so there we go
you can find it somewhere so there we go you have the publishable key and you
you have the publishable key and you have the secret key right here so you
have the secret key right here so you need to use this secret key so just
need to use this secret key so just click on this I and there we go click to
click on this I and there we go click to copy like this and once you copied it so
copy like this and once you copied it so make sure it's the secret key right here
make sure it's the secret key right here copy that and then go inside of your dot
copy that and then go inside of your dot environment file
environment file like this and you can paste it anywhere
like this and you can paste it anywhere so at the bottom I'm going to write
so at the bottom I'm going to write stripe underscore API underscore key
stripe underscore API underscore key like this there we go great so now that
like this there we go great so now that we have that uh leave this open because
we have that uh leave this open because we are gonna need to create some web
we are gonna need to create some web hooks later so don't close it just yet
hooks later so don't close it just yet but we are not gonna do anything more
but we are not gonna do anything more for now great what I want to do now is I
for now great what I want to do now is I want to install a package for Stripes so
want to install a package for Stripes so go inside of your terminal
go inside of your terminal and run
and run npm install stripe like this there we go
npm install stripe like this there we go and run the application again
and run the application again now I'm gonna go ahead and I'm gonna
now I'm gonna go ahead and I'm gonna create a live library for stripe so go
create a live library for stripe so go inside your lib folder and create a new
inside your lib folder and create a new file called a stripe.ts go ahead and
file called a stripe.ts go ahead and import Stripe from a stripe like this
import Stripe from a stripe like this and Export con stripe to be new striped
and Export con stripe to be new striped and instead inside you're going to use
and instead inside you're going to use the process.environment of course you're
the process.environment of course you're going to use the key that you pasted
going to use the key that you pasted here so stripe underscore API key and
here so stripe underscore API key and just paste it here like this and this
just paste it here like this and this gives an error so just go ahead and open
gives an error so just go ahead and open an object here and to fix this error you
an object here and to fix this error you can either use Pi pipe string or you can
can either use Pi pipe string or you can use exclamation point like this
use exclamation point like this great so inside I'm going to use the API
great so inside I'm going to use the API version of
version of 2022 11 15 like this and typescript
2022 11 15 like this and typescript is going to be true like this
is going to be true like this perfect and now what I want to do is I
perfect and now what I want to do is I want to create a route for my stripe but
want to create a route for my stripe but before I do that I actually have to go
before I do that I actually have to go in my schema Prisma and create a new
in my schema Prisma and create a new model for user subscription so let's do
model for user subscription so let's do that first let's go inside the Prisma
that first let's go inside the Prisma schema.prisma and the same way we did
schema.prisma and the same way we did with model user API limit we're going to
with model user API limit we're going to create a model user subscription like
create a model user subscription like this we're going to have an ID of string
this we're going to have an ID of string which is going to be an ID and a default
which is going to be an ID and a default value is going to be CU ID like this
value is going to be CU ID like this we're going to have the user ID which is
we're going to have the user ID which is going to come from clerk which is string
going to come from clerk which is string and unique
and unique we're gonna have a stripe customer ID
we're gonna have a stripe customer ID like this which is going to be an
like this which is going to be an optional string is going to be unique
optional string is going to be unique and we're going to map it to this name
and we're going to map it to this name stripe underscore customer underscore ID
stripe underscore customer underscore ID so this is a way that we can access this
so this is a way that we can access this both through this Pascal case actually
both through this Pascal case actually I'm not sure sorry I said Pascal case
I'm not sure sorry I said Pascal case but I'm not sure what's the proper name
but I'm not sure what's the proper name of this one so we can either access it
of this one so we can either access it using these underscores which is what
using these underscores which is what stripe API uses or using this camel case
stripe API uses or using this camel case that we are used to in JavaScript right
that we are used to in JavaScript right here so that's why we are doing this map
here so that's why we are doing this map right here great and now we're going to
right here great and now we're going to repeat this for stripe subscription ID
repeat this for stripe subscription ID which is also a string unique map
which is also a string unique map name stripe underscore subscription
name stripe underscore subscription underscore ID
underscore ID and we have stripe price ID which is
and we have stripe price ID which is also an optional string it's not unique
also an optional string it's not unique so this one is just map name stripe
so this one is just map name stripe underscore price underscore ID and
underscore price underscore ID and stripe
stripe current period and
current period and which is an optional date time and map
which is an optional date time and map that to name
that to name stripe underscore current underscore
stripe underscore current underscore period underscore and like this perfect
period underscore and like this perfect so let me just search for a stripe to
so let me just search for a stripe to see if we misspelled anything okay so
see if we misspelled anything okay so stripe customer ID seems correct stripe
stripe customer ID seems correct stripe subscription ID seems correct strike
subscription ID seems correct strike price ID seems correct and the map
price ID seems correct and the map should be the same thing we have here
should be the same thing we have here but separated with underscores great so
but separated with underscores great so make sure you didn't do any misspells
make sure you didn't do any misspells here subscription subscription customer
here subscription subscription customer customer price price everything seems
customer price price everything seems fine current period And I think this is
fine current period And I think this is fine great and what do we have to do
fine great and what do we have to do every time we modify our schema Prisma
every time we modify our schema Prisma well we have to first shut down the
well we have to first shut down the application run npx Prisma generate
application run npx Prisma generate so we add that to our node modules and
so we add that to our node modules and then npx Prisma DB push so we push that
then npx Prisma DB push so we push that to Planet scale and once you do npx
to Planet scale and once you do npx Prisma DB push you can go ahead and run
Prisma DB push you can go ahead and run your application again if you want to
your application again if you want to you can reset the Prisma studio just in
you can reset the Prisma studio just in case
case so I'm doing this in my other terminal
so I'm doing this in my other terminal so I'm I'm running the app here but I
so I'm I'm running the app here but I run Prisma studio in my other terminal
run Prisma studio in my other terminal and now if you go here and if you close
and now if you go here and if you close this user API limit you can see that we
this user API limit you can see that we have user subscription as a model now as
have user subscription as a model now as well so you can prepare that here right
well so you can prepare that here right so just go ahead and select user
so just go ahead and select user subscription and there should be no
subscription and there should be no results inside uh great now that we have
results inside uh great now that we have that let's go ahead and let's create a
that let's go ahead and let's create a route which is actually going to create
route which is actually going to create our subscriptions
our subscriptions great let's go inside of app folder
great let's go inside of app folder inside of API right here and go ahead
inside of API right here and go ahead and create a new folder called stripe
and create a new folder called stripe and inside of that create a new file
and inside of that create a new file route.ds like this let's go ahead and
route.ds like this let's go ahead and let's import out and current user from
let's import out and current user from Clerk
Clerk nexjs
nexjs let's go ahead and import
next response from next server let's import Prisma DB from lib Prisma DB
import Prisma DB from lib Prisma DB let's import Stripe from lib stripe like
let's import Stripe from lib stripe like this and let's import uh well one util
this and let's import uh well one util that we have to create so what we are
that we have to create so what we are going to do is before remove this import
going to do is before remove this import for now and go back inside of your lib
for now and go back inside of your lib inside of eudels right here and go ahead
inside of eudels right here and go ahead and just write export function absolute
and just write export function absolute URL that is going to be string like this
URL that is going to be string like this and just return
back decks like this go ahead and open the special object and write
the special object and write process.environment dot next underscore
process.environment dot next underscore public underscore app underscore URL and
public underscore app underscore URL and then append the path from the prop right
then append the path from the prop right here so why do we need this what is this
here so why do we need this what is this exactly well first thing let's add this
exactly well first thing let's add this to our environment variable so we can
to our environment variable so we can discuss it further I'm going to go
discuss it further I'm going to go inside of my DOT environment I'm going
inside of my DOT environment I'm going to add this and it's going to be HTTP
to add this and it's going to be HTTP localhost 3000
localhost 3000 like this so make sure that you don't
like this so make sure that you don't add a black backslash at the end and
add a black backslash at the end and make sure that this is the actual route
make sure that this is the actual route that you are running your application on
that you are running your application on so for me it's localhost 3000 it for you
so for me it's localhost 3000 it for you is something different then make sure
is something different then make sure that you use that great so why am I
that you use that great so why am I doing this well that's because what you
doing this well that's because what you will see that when we build this uh
will see that when we build this uh stripe route right here it's gonna need
stripe route right here it's gonna need to take a return URL and the return URL
to take a return URL and the return URL cannot be just slash settings or slash
cannot be just slash settings or slash dashboard it needs to be an absolute URL
dashboard it needs to be an absolute URL because stripe has no idea what
because stripe has no idea what application it's using or where it's
application it's using or where it's hosted so that's why we need to give it
hosted so that's why we need to give it an explicit absolute URL so it knows how
an explicit absolute URL so it knows how to go back to our website so obviously
to go back to our website so obviously in production we're gonna have to change
in production we're gonna have to change this to our actual URL and now we can
this to our actual URL and now we can import that absolute URL from lib utils
import that absolute URL from lib utils like this great and now let's create the
like this great and now let's create the settings URL so const settings URL is
settings URL so const settings URL is going to be absolute URL like this and
going to be absolute URL like this and it's going to go to slash settings like
it's going to go to slash settings like this
this with two T's so what this is going to
with two T's so what this is going to generate is is going to call localhost
generate is is going to call localhost 3000 slash settings so slash settings so
3000 slash settings so slash settings so just make sure that you don't put the
just make sure that you don't put the slash here because then it's going to be
slash here because then it's going to be slash slash settings that's not
slash slash settings that's not something we want so make sure it
something we want so make sure it doesn't have a trailing slash at the end
doesn't have a trailing slash at the end great and now that we have that let's go
great and now that we have that let's go ahead and write export asynchronous
ahead and write export asynchronous function get like this let's open a try
function get like this let's open a try method inside
method inside and while we are already here let's do
and while we are already here let's do the catch first so catch error console
the catch first so catch error console log
oops so go ahead and log stripe error like
so go ahead and log stripe error like this and the error like that and return
this and the error like that and return new next response internal error with a
new next response internal error with a status of 500 like this great and now
status of 500 like this great and now let's go ahead and let's uh first
let's go ahead and let's uh first extract the user ID from out which we
extract the user ID from out which we imported at the top
imported at the top uh and let's get the user from await
uh and let's get the user from await current user which we also imported from
current user which we also imported from clerk if there is no user or sorry if
clerk if there is no user or sorry if there is no user ID
there is no user ID or if there is no user
or if there is no user a return new next response
unauthorized with a status of 401 like this great now
with a status of 401 like this great now let's go ahead and try and find current
let's go ahead and try and find current user subscription const user
user subscription const user subscription
subscription is equal to await Prisma DB dot user
is equal to await Prisma DB dot user subscription so again if you're getting
subscription so again if you're getting a curling red line here or your Prisma
a curling red line here or your Prisma did not autocomplete the user
did not autocomplete the user subscription make sure that you have the
subscription make sure that you have the user subscription in your schema Prisma
user subscription in your schema Prisma make sure you didn't misspell it make
make sure you didn't misspell it make sure you did npx Prisma DB push and npx
sure you did npx Prisma DB push and npx Prisma generate and if that is still not
Prisma generate and if that is still not working you can just reload your entire
working you can just reload your entire vs code and then try again great so
vs code and then try again great so await Prisma db.usersubscription dot
await Prisma db.usersubscription dot find unique like this where user ID like
find unique like this where user ID like this so we're gonna find a subscription
this so we're gonna find a subscription based on the currently logged in user ID
based on the currently logged in user ID uh if there is a user subscription
uh if there is a user subscription already and if there is user
already and if there is user subscription
subscription dot stripe customer ID in that case once
dot stripe customer ID in that case once user uh points to this API route we
user uh points to this API route we don't want to create a checkout page
don't want to create a checkout page instead we want to redirect the user to
instead we want to redirect the user to the billing page so that they can cancel
the billing page so that they can cancel their active subscription in order to do
their active subscription in order to do that we're going to write const stripe
that we're going to write const stripe session is equal to await stripe dot
session is equal to await stripe dot billing
billing portal.sessions dot create like this and
portal.sessions dot create like this and inside of this object let's give it a
inside of this object let's give it a customer a user subscription dot stripe
customer a user subscription dot stripe customer ID and return URL is going to
customer ID and return URL is going to be settings URL which we defined right
be settings URL which we defined right here that's the absolute URL thing great
here that's the absolute URL thing great so once the user finishes doing whatever
so once the user finishes doing whatever they want on the billing portal they're
they want on the billing portal they're going to be returned to localhost 3000
going to be returned to localhost 3000 slash settings which for now is a404 in
slash settings which for now is a404 in our project but don't worry we're gonna
our project but don't worry we're gonna fix that later great so we have our
fix that later great so we have our stripe session and what we have to do
stripe session and what we have to do still inside of this if block is
still inside of this if block is actually returned that back so return
actually returned that back so return new next response like this
new next response like this json.stringify like that URL
json.stringify like that URL stripe session dot URL like this perfect
stripe session dot URL like this perfect and now that we have that let's see what
and now that we have that let's see what happens if we don't have a stripe
happens if we don't have a stripe subscription so if we don't have a
subscription so if we don't have a stripe subscription we want to create
stripe subscription we want to create another form of stripe session so go
another form of stripe session so go ahead and write con stripe session again
ahead and write con stripe session again but this time we're going to use a
but this time we're going to use a weightstripe.checkout.sessions DOT
weightstripe.checkout.sessions DOT create so we're not going to create a
create so we're not going to create a billing portal but a checkout session
billing portal but a checkout session because it's user's first time
because it's user's first time subscribing to our application we're
subscribing to our application we're going to give it a success URL to be
going to give it a success URL to be settings URL but it's also going to be
settings URL but it's also going to be the cancel URL so we don't really care
the cancel URL so we don't really care for our application it can be the same
for our application it can be the same payment method types are going to be an
payment method types are going to be an array and I'm only going to accept
array and I'm only going to accept credit card
credit card mode is going to be subscription like
mode is going to be subscription like this billing address in collection is
this billing address in collection is going to be Auto
customer email is going to be user.email addresses so this is from clerk so this
addresses so this is from clerk so this user object comes from clerk right here
user object comes from clerk right here so uh clerk has an array of email
so uh clerk has an array of email addresses and Greek is just going to
addresses and Greek is just going to pick the first one like this dot email
pick the first one like this dot email address like that
address like that and line underscore items is going to be
and line underscore items is going to be an array inside with just one object so
an array inside with just one object so this is going to be our product and it's
this is going to be our product and it's going to have price underscore data
going to have price underscore data which is an object currency is going to
which is an object currency is going to be US Dollars product underscore data is
be US Dollars product underscore data is going to be another object with the name
going to be another object with the name of Genius Pro and description is going
of Genius Pro and description is going to be unlimited AI Generations like that
to be unlimited AI Generations like that perfect so we finished up uh price data
perfect so we finished up uh price data uh actually we haven't so we finished
uh actually we haven't so we finished that product data now we have to add the
that product data now we have to add the unit underscore amount which is going to
unit underscore amount which is going to be 2 000. so this is equivalent to 20
be 2 000. so this is equivalent to 20 dollars and we're gonna add the
dollars and we're gonna add the recurring option because this is a
recurring option because this is a subscription to be on a monthly interval
subscription to be on a monthly interval like this great and lastly let's just
like this great and lastly let's just give it a quantity of one so quantity is
give it a quantity of one so quantity is part of the main align items object not
part of the main align items object not the price data object you can see price
the price data object you can see price data is a separate object for itself so
data is a separate object for itself so make sure you put the quantity outside
make sure you put the quantity outside of the price data object great and one
of the price data object great and one more thing that we have to pass outside
more thing that we have to pass outside of line items so you can close line
of line items so you can close line items I mean you don't have to close
items I mean you don't have to close them but just outside of the array make
them but just outside of the array make sure that you add metadata this is
sure that you add metadata this is actually very important user ID the
actually very important user ID the reason metadata user ID is important is
reason metadata user ID is important is because this is not gonna create
because this is not gonna create anything yet this is only gonna open the
anything yet this is only gonna open the checkout page and only after users
checkout page and only after users successfully purchases our monthly
successfully purchases our monthly subscription are we gonna create a web
subscription are we gonna create a web hook which is going to catch that and
hook which is going to catch that and then it's going to read the metadata
then it's going to read the metadata find the user ID and then say oh okay so
find the user ID and then say oh okay so this checkout which was just completed
this checkout which was just completed successfully belongs to this user ID so
successfully belongs to this user ID so it's very important that you pass that
it's very important that you pass that otherwise users will be able to check
otherwise users will be able to check out and subscribe to your application
out and subscribe to your application but you won't know who actually
but you won't know who actually subscribed and who to give subscription
subscribed and who to give subscription to so that's why this metadata is very
to so that's why this metadata is very important uh great so now we have that
important uh great so now we have that and we can now simply do a return new
and we can now simply do a return new next response
next response json.stringify like this URL
json.stringify like this URL stripe session dot URL like that perfect
stripe session dot URL like that perfect so you just finished the stripe checkout
so you just finished the stripe checkout page great and what I want to do now is
page great and what I want to do now is I want to create a web hook for our
I want to create a web hook for our stripe so I'm gonna close everything
stripe so I'm gonna close everything here and we're gonna go back inside of
here and we're gonna go back inside of the app folder inside of API and create
the app folder inside of API and create a new folder called webhook like this
a new folder called webhook like this and inside create a new file
and inside create a new file route.ds like that perfect so let's go
route.ds like that perfect so let's go ahead and let's import Stripe from
ahead and let's import Stripe from stripe let's go ahead and import headers
stripe let's go ahead and import headers from next slash headers like that let's
from next slash headers like that let's import next response from next slash
import next response from next slash server let's import Prisma DB from
server let's import Prisma DB from Prisma DB and let's import the stripe in
Prisma DB and let's import the stripe in util that we created from s slash lib
util that we created from s slash lib stripe now let's export a synchronous
stripe now let's export a synchronous function post which is going to take the
function post which is going to take the request which is a type of request
request which is a type of request let's go ahead and let's get the body in
let's go ahead and let's get the body in a form of a weight request dot text
a form of a weight request dot text like this
like this and let's get the signature so const
and let's get the signature so const signature is equal to headers
signature is equal to headers dot get stripe Dash signature as a
dot get stripe Dash signature as a string
string now let's create a let for event
now let's create a let for event which is a type of stripe dot event like
which is a type of stripe dot event like this
this and now we're going to open a try and
and now we're going to open a try and catch block right here
catch block right here uh
uh okay and let's go ahead and let's write
okay and let's go ahead and let's write event is equal to
event is equal to stripe.webhooks dot construct events
stripe.webhooks dot construct events we're gonna pass in the body we're gonna
we're gonna pass in the body we're gonna pass in the signature and we're gonna
pass in the signature and we're gonna pass in the process.environment and you
pass in the process.environment and you already know which one this stripe uh
already know which one this stripe uh API key actually no my apologies
API key actually no my apologies actually this is uh this is going to be
actually this is uh this is going to be stripe underscore web hook underscore
stripe underscore web hook underscore secret which we are going to create in a
secret which we are going to create in a second so we don't have this yet but
second so we don't have this yet but don't worry we're gonna create it my
don't worry we're gonna create it my apologies I I thought it was the other
apologies I I thought it was the other one uh great and let's just add a catch
one uh great and let's just add a catch here for an error of any
here for an error of any and return
and return new next response
new next response webhook
webhook error
error error.message and a status of 400 like
error.message and a status of 400 like this great and now that we have that
this great and now that we have that let's create the logic which is going to
let's create the logic which is going to capture the current so we are only going
capture the current so we are only going to look for two events the checkout
to look for two events the checkout session completed and invoice payment
session completed and invoice payment succeeded so two events because in our
succeeded so two events because in our stripe route we only do two things we
stripe route we only do two things we are either doing the billing portal or
are either doing the billing portal or we are doing the checkout session so
we are doing the checkout session so those are two separate events one is
those are two separate events one is going to either cancel or upgrade the
going to either cancel or upgrade the subscription and the other one is going
subscription and the other one is going to create it for the very first time so
to create it for the very first time so those are the two events that we are
those are the two events that we are going to look for inside of our web hook
going to look for inside of our web hook so let's go ahead and let's write const
so let's go ahead and let's write const session is equal to
session is equal to event.data.object as
event.data.object as stripe.checkout.session like this great
stripe.checkout.session like this great now let's check for the first event so
now let's check for the first event so if session so if events DOT type
if session so if events DOT type is equal sorry identical to
is equal sorry identical to checkout.session dot completed so make
checkout.session dot completed so make sure you don't misspell any of this
sure you don't misspell any of this in that case let's go ahead and retrieve
in that case let's go ahead and retrieve the subscription using stripe silicon
the subscription using stripe silicon subscription
subscription is equal to await stripe dot
is equal to await stripe dot subscriptions
subscriptions dot retrieve
dot retrieve and just pass in session dot
and just pass in session dot subscription as a string like this
subscription as a string like this if there is no session question mark dot
if there is no session question mark dot metadata question mark dot user ID so
metadata question mark dot user ID so that's what I was talking about we have
that's what I was talking about we have to pass that user ID in the metadata but
to pass that user ID in the metadata but if it's not here we don't know who this
if it's not here we don't know who this subscription belongs to in that case we
subscription belongs to in that case we have to throw an error return new next
have to throw an error return new next response user ID
response user ID is required like that and let's just
is required like that and let's just pass in a proper status of 400 as well
pass in a proper status of 400 as well great if there is we can go ahead and
great if there is we can go ahead and actually create a Prisma subscription so
actually create a Prisma subscription so away Prisma DB dot user subscription dot
away Prisma DB dot user subscription dot create like this and the data we are
create like this and the data we are going to pass inside is going to be user
going to pass inside is going to be user ID which is going to be session question
ID which is going to be session question mark metadata question mark user ID so
mark metadata question mark user ID so the same one we had right here so that's
the same one we had right here so that's how we are going to match uh the
how we are going to match uh the currently logged in user using web code
currently logged in user using web code because in this web hook we cannot use
because in this web hook we cannot use clerk because this webhook is going to
clerk because this webhook is going to be running independently from our
be running independently from our application right and we're also going
application right and we're also going to have to add this webhook to public
to have to add this webhook to public routes as well uh great because it's
routes as well uh great because it's going to be accessed by stripe in a
going to be accessed by stripe in a different way great so that's how we get
different way great so that's how we get the current user ID without actually
the current user ID without actually being logged in and now we have the
being logged in and now we have the stripe subscription ID which is
stripe subscription ID which is subscription ID we have the stripe
subscription ID we have the stripe customer ID which is a subscription
customer ID which is a subscription Dot customer as string
Dot customer as string we have the stripe price ID which is
we have the stripe price ID which is subscription DOT items.data first in
subscription DOT items.data first in Array because we only have one item
Array because we only have one item Anyway dot price dot ID like that and
Anyway dot price dot ID like that and stripe current period and is going to be
stripe current period and is going to be new date which is going to take in
new date which is going to take in subscription
the current underscore period underscore end times 1000 like this perfect so we
end times 1000 like this perfect so we created a user account in case this
created a user account in case this event is run right here great so let's
event is run right here great so let's go outside of that if function and let's
go outside of that if function and let's check for the second one and that is if
check for the second one and that is if user just upgraded their subscription
user just upgraded their subscription and they already had one before maybe it
and they already had one before maybe it has expired or something so if
has expired or something so if events.tight is identical to
events.tight is identical to invoice.tayment underscore succeeded
invoice.tayment underscore succeeded whoops
like this in that case Hans subscription is equal
in that case Hans subscription is equal to a weight stripe dot subscriptions
to a weight stripe dot subscriptions dot retrieve like this
dot retrieve like this session dot subscription as string again
session dot subscription as string again and we're simply going to update the
and we're simply going to update the existing user subscription so await
existing user subscription so await Prisma
Prisma DB dot users subscription dot update
DB dot users subscription dot update where
where stripe subscription ID is equal to
stripe subscription ID is equal to subscription dot ID like this and data
subscription dot ID like this and data is going to be stripe price ID because
is going to be stripe price ID because we have a new price ID now because we
we have a new price ID now because we have an entirely new subscription so
have an entirely new subscription so subscription
subscription Dot items.data
burstinaray.price.id and we are going to update the current period and because
update the current period and because user just renewed their subscription so
user just renewed their subscription so a new date and inside stripe sorry
a new date and inside stripe sorry subscription
subscription dot current underscore period end times
dot current underscore period end times 1000 like this perfect and now that we
1000 like this perfect and now that we have that all we have to do is just
have that all we have to do is just return new next response no and the
return new next response no and the status of 200 so this is actually quite
status of 200 so this is actually quite important make sure that you return this
important make sure that you return this it doesn't matter that we are not
it doesn't matter that we are not sending anything but it can mess with
sending anything but it can mess with the web hooks functionality if you don't
the web hooks functionality if you don't do it properly great so what we have to
do it properly great so what we have to do now is we have to actually
do now is we have to actually uh create this environment variable but
uh create this environment variable but there is a certain way we have to do it
there is a certain way we have to do it in local development what we have to do
in local development what we have to do is we have to go back inside of stripe
is we have to go back inside of stripe and you have to click on developers
and you have to click on developers right here in the corner so make sure
right here in the corner so make sure you click on this developers button go
you click on this developers button go inside of your web hooks here and when
inside of your web hooks here and when you are in production you're going to
you are in production you're going to click add on endpoint but we are local
click add on endpoint but we are local so we're going to click test in a local
so we're going to click test in a local environment so first thing you have to
environment so first thing you have to do is download the CLI so you can click
do is download the CLI so you can click on download the CLI right here and you
on download the CLI right here and you can see some options on how to do that
can see some options on how to do that so I'm on the Macbook so I can just use
so I'm on the Macbook so I can just use Brew if you run a Windows you can go
Brew if you run a Windows you can go ahead and download from GitHub and run
ahead and download from GitHub and run stripe.exe and a bunch of other options
stripe.exe and a bunch of other options from Linux Mac OS and a bunch of other
from Linux Mac OS and a bunch of other tools you might use so make sure you
tools you might use so make sure you have the stripe CLI setup and now you
have the stripe CLI setup and now you have to do the stripe login so I'm going
have to do the stripe login so I'm going to copy this to the clipboard I'm going
to copy this to the clipboard I'm going to go ahead in my terminal and I'm going
to go ahead in my terminal and I'm going to open my third terminal actually
to open my third terminal actually because one runs my project one runs my
because one runs my project one runs my Prisma so I'm gonna add a new one and
Prisma so I'm gonna add a new one and this one is going to do stripe login
this one is going to do stripe login there we go so my pairing code is this
there we go so my pairing code is this one and I have to click on this link
one and I have to click on this link right here and open it and there we go
right here and open it and there we go it's opened in my dashboard now here and
it's opened in my dashboard now here and you can see that I have the very same
you can see that I have the very same pairing code that is in my terminal so
pairing code that is in my terminal so that way I know okay this is certainly
that way I know okay this is certainly mine and I can allow access to it there
mine and I can allow access to it there we go now I have my access granted and
we go now I have my access granted and take a look at the uh take a look at my
take a look at the uh take a look at my terminal you can see that the stripe CLI
terminal you can see that the stripe CLI is configured right here
is configured right here uh yeah okay so everything is correct
uh yeah okay so everything is correct that's what I wanted to point out uh
that's what I wanted to point out uh great now let's go back inside of the
great now let's go back inside of the dashboard AI right here and what we have
dashboard AI right here and what we have to do is we have to simulate listening
to do is we have to simulate listening to our web hook so copy the second one
to our web hook so copy the second one and you should see the completed green
and you should see the completed green tag right here so go back inside of your
tag right here so go back inside of your terminal now
terminal now copy this and you have to modify it a
copy this and you have to modify it a little bit so it's not localhost4242
little bit so it's not localhost4242 instead is 3000 slash API slash web hook
instead is 3000 slash API slash web hook so the route which we just created log
so the route which we just created log host 3000 slash API slash fabcook I just
host 3000 slash API slash fabcook I just want to zoom out so you can see it in
want to zoom out so you can see it in one line stripe listen dash dash
one line stripe listen dash dash forward-2 localhost 3000 slash API slash
forward-2 localhost 3000 slash API slash web hook press enter like this there we
web hook press enter like this there we go you can see that it now says
go you can see that it now says completed here as well and now we
completed here as well and now we finally got our web hook signing secret
finally got our web hook signing secret so you can go ahead and copy this so
so you can go ahead and copy this so starting with a
starting with a whsec so go ahead and copy this entire
whsec so go ahead and copy this entire thing after the last number make sure
thing after the last number make sure you don't accidentally copy some spaces
you don't accidentally copy some spaces so be very precise when copying this and
so be very precise when copying this and then you can create this stripe
then you can create this stripe underscore webhook Secret in your
underscore webhook Secret in your environment file so go ahead and add
environment file so go ahead and add stripe underscore webhook underscore
stripe underscore webhook underscore secret like this and just paste that in
secret like this and just paste that in here just make sure there are no
here just make sure there are no trailing spaces on either end great so
trailing spaces on either end great so stripe web hook secret and just double
stripe web hook secret and just double check in the web hook that you're
check in the web hook that you're actually using that one there we go and
actually using that one there we go and make sure to keep this running in your
make sure to keep this running in your terminal every time you are developing
terminal every time you are developing otherwise your stripe web Hook is not
otherwise your stripe web Hook is not going to work so for now make sure that
going to work so for now make sure that your app is running make sure that your
your app is running make sure that your Prisma studio is running and make sure
Prisma studio is running and make sure that you have the stripe listened
that you have the stripe listened forward to localhost 3000 slash API
forward to localhost 3000 slash API slash web hook running as well perfect
slash web hook running as well perfect so I'm gonna close this now and what
so I'm gonna close this now and what we're gonna do now
we're gonna do now is we're going to actually make it so
is we're going to actually make it so that when we click on this upgrade
that when we click on this upgrade button it actually calls this route
button it actually calls this route stripe which is going to either open the
stripe which is going to either open the billing portal or open the checkout
billing portal or open the checkout session so let's go ahead and let's
session so let's go ahead and let's close everything and let's see how we
close everything and let's see how we can do that now so let's head inside of
can do that now so let's head inside of our components inside of our pro model
our components inside of our pro model right here I'm just going to expand this
right here I'm just going to expand this and what we're going to add is we're
and what we're going to add is we're going to add const on subscribe
going to add const on subscribe to Be an Arrow function and it's going
to Be an Arrow function and it's going to be asynchronous
to be asynchronous like this go ahead and open the try and
like this go ahead and open the try and catch block
so you can just log the error here and let's just write stripe client error
let's just write stripe client error like this
like this and let's go ahead and just do const
and let's go ahead and just do const response is equal to axios so make sure
response is equal to axios so make sure you import axios I'm going to move it to
you import axios I'm going to move it to the top of my imports all the way up but
the top of my imports all the way up but always make sure your Imports are below
always make sure your Imports are below use clients so that's also important
use clients so that's also important great so we have the axis now so axios
great so we have the axis now so axios is going to be dot get slash API slash
is going to be dot get slash API slash stripe because that is the route we
stripe because that is the route we created in our app folder API we have
created in our app folder API we have the stripe folder route DS and you can
the stripe folder route DS and you can see that it is a get method so that's
see that it is a get method so that's why we do axios.get slash API slash
why we do axios.get slash API slash stripe and what are we gonna get in this
stripe and what are we gonna get in this response well you can take a look at
response well you can take a look at that right here so we are going to get
that right here so we are going to get an URL inside of an object for both
an URL inside of an object for both cases you can see URL at the bottom and
cases you can see URL at the bottom and URL in this case too perfect so let's go
URL in this case too perfect so let's go ahead and run
ahead and run window.location.href is going to be
window.location.href is going to be equal to
equal to response.data.url so I just realized
response.data.url so I just realized that my vs code automatically added a
that my vs code automatically added a weight response and I didn't mention
weight response and I didn't mention anything about it so that's because I
anything about it so that's because I honestly didn't even notice this so here
honestly didn't even notice this so here is a screenshot of an alternative way
is a screenshot of an alternative way you can do this you can put a weight in
you can do this you can put a weight in front of axios.get and that is a
front of axios.get and that is a preferred way of doing this like this
preferred way of doing this like this but before we do that let's also add a
but before we do that let's also add a loading state so loading set loading use
loading state so loading set loading use state from react give it the default
state from react give it the default value of false and I'm just going to
value of false and I'm just going to move this along uh with the other Global
move this along uh with the other Global Imports like that
Imports like that and in the finally
and in the finally I'm going to add set loading to false
I'm going to add set loading to false and in the try I'm going to add set
and in the try I'm going to add set loading to True like that there we go
loading to True like that there we go and now let's just add this on subscribe
and now let's just add this on subscribe to be an on click of this button
to be an on click of this button like that now let's go ahead and I'm
like that now let's go ahead and I'm going to try and click upgrade but I'm
going to try and click upgrade but I'm just going to refresh first just in case
just going to refresh first just in case so again make sure you have your Prisma
so again make sure you have your Prisma Studio running so you can look if there
Studio running so you can look if there are any active subscriptions here so
are any active subscriptions here so here are my use here I'm looking for
here are my use here I'm looking for user subscriptions in the Prisma Studio
user subscriptions in the Prisma Studio nothing is here make sure that you have
nothing is here make sure that you have uh your and make sure that you have your
uh your and make sure that you have your web hook running so I'm just going to
web hook running so I'm just going to open my terminals quickly
open my terminals quickly so make sure you have this terminal
so make sure you have this terminal running right here uh make sure you
running right here uh make sure you added this stripe API webhook and now
added this stripe API webhook and now let's go ahead and let's see if this is
let's go ahead and let's see if this is going to work so I'm going to click
going to work so I'm going to click upgrade right here and we forgot to
upgrade right here and we forgot to append the loading states to it but
append the loading states to it but there we go you can see that it uses my
there we go you can see that it uses my email that I logged in with you can see
email that I logged in with you can see that it puts 20 dollars per month
that it puts 20 dollars per month unlimited AI Generations now let's use
unlimited AI Generations now let's use the test credit card from stripe and I'm
the test credit card from stripe and I'm just going to expand this so you can
just going to expand this so you can also keep my uh so you can see my
also keep my uh so you can see my terminal so open your web hook terminal
terminal so open your web hook terminal here so you can see the actions in real
here so you can see the actions in real time here I'm going to add a fake stripe
time here I'm going to add a fake stripe credit card like this I'm gonna add some
credit card like this I'm gonna add some more fake information I'm going to use
more fake information I'm going to use my name and I'm going to click subscribe
my name and I'm going to click subscribe now let's see what happens let's see if
now let's see what happens let's see if we did everything correctly or if we did
we did everything correctly or if we did a mistake and we did a mistake we are
a mistake and we did a mistake we are getting a 401 error here and let's take
getting a 401 error here and let's take a look at why that happened so now if
a look at why that happened so now if you refresh your Prisma Studio I'm
you refresh your Prisma Studio I'm really confident you should see nothing
really confident you should see nothing here that's right so it didn't work the
here that's right so it didn't work the reason it didn't work is because we
reason it didn't work is because we forgot one crucial thing so it tried to
forgot one crucial thing so it tried to go to our localhost 3000 slash API slash
go to our localhost 3000 slash API slash web hook but we are giving it a 401
web hook but we are giving it a 401 error meaning that we are not
error meaning that we are not authenticated but how do we do that how
authenticated but how do we do that how do we fix that well very simply using
do we fix that well very simply using clerk so you have to go inside of our
clerk so you have to go inside of our middleware.ts right here and alongside
middleware.ts right here and alongside public routes we also have to add slash
public routes we also have to add slash API slash webhook like that and now our
API slash webhook like that and now our web Hook is public so let's repeat this
web Hook is public so let's repeat this process one more time so I'm just make
process one more time so I'm just make sure you log in make sure you go to
sure you log in make sure you go to slash dashboard
slash dashboard so manually have to go to slash
so manually have to go to slash dashboard go ahead and click on upgrade
dashboard go ahead and click on upgrade again and I'm gonna keep my terminal
again and I'm gonna keep my terminal running again and hopefully this time we
running again and hopefully this time we are not going to see 401 instead we're
are not going to see 401 instead we're going to see 200 and we're going to see
going to see 200 and we're going to see a new model in our Prisma studio so
a new model in our Prisma studio so let's go ahead and write this
let's go ahead and write this I'm going to use my name let's click
I'm going to use my name let's click subscribe
subscribe fingers crossed in a couple of seconds
fingers crossed in a couple of seconds there we go all events are 200 and we
there we go all events are 200 and we have succeeded this is a 404 page
have succeeded this is a 404 page because settings page does not exist yet
because settings page does not exist yet but we're gonna create that now and
but we're gonna create that now and let's see our Prisma studio if I refresh
let's see our Prisma studio if I refresh here there we go look at this my user id
here there we go look at this my user id my customer subscription and my uh
my customer subscription and my uh period so I can see if it has expired or
period so I can see if it has expired or not beautiful amazing amazing job great
not beautiful amazing amazing job great and now let's actually go ahead back to
and now let's actually go ahead back to slash dashboard
slash dashboard and let's create this settings page but
and let's create this settings page but before we do that let's create a useful
before we do that let's create a useful util to check if our currently logged in
util to check if our currently logged in user is subscribed or not so we can just
user is subscribed or not so we can just check whether it has a subscription in
check whether it has a subscription in the database we also have to confirm
the database we also have to confirm that it has not expired right so we're
that it has not expired right so we're going to create a util for that go
going to create a util for that go inside your lib and create a new file
inside your lib and create a new file called
called subscription.ds like this let's go ahead
subscription.ds like this let's go ahead and import out from clerk again
and import out from clerk again and let's import Prisma DB from Prisma
and let's import Prisma DB from Prisma DB or dot slash Prisma DB depending on
DB or dot slash Prisma DB depending on how you prefer it let's write a constant
how you prefer it let's write a constant for an entire day in milliseconds so
for an entire day in milliseconds so const day in milliseconds is equal to 86
const day in milliseconds is equal to 86 underscore 400 underscore zero zero zero
underscore 400 underscore zero zero zero like this great now let's write export
like this great now let's write export const check subscription
const check subscription is asynchronous Arrow function like this
is asynchronous Arrow function like this let's extract the user ID from out like
let's extract the user ID from out like that
that if there is no user ID in that case
if there is no user ID in that case return false meaning we have no way of
return false meaning we have no way of checking whether user is subscribed or
checking whether user is subscribed or not so we are just going to assume that
not so we are just going to assume that they are not next we're going to try and
they are not next we're going to try and find the user subscription so const user
find the user subscription so const user subscription is equal to await Prisma DB
subscription is equal to await Prisma DB dot usersubscription dot find unique
dot usersubscription dot find unique I'm just going to expand this so you can
I'm just going to expand this so you can see a bit more like this where user ID
see a bit more like this where user ID is equal to user ID or you can use the
is equal to user ID or you can use the shorthand and we're going to select the
shorthand and we're going to select the following we're going to select stripe
following we're going to select stripe subscription ID to be true we're going
subscription ID to be true we're going to select stripe current period and to
to select stripe current period and to be true we're going to select stripe
be true we're going to select stripe customer ID to be true and we're going
customer ID to be true and we're going to select stripe price ID to be true as
to select stripe price ID to be true as well
well now let's check if we actually got that
now let's check if we actually got that user subscription so if there is no
user subscription so if there is no active user subscription in that case we
active user subscription in that case we can also return false because obviously
can also return false because obviously this user is not subscribed to Pro and
this user is not subscribed to Pro and now let's check if it has a subscription
now let's check if it has a subscription but let's check if it's actually valid
but let's check if it's actually valid and not expired so const is valid is
and not expired so const is valid is going to be user dot user user
going to be user dot user user subscription dot stripe priceid and user
subscription dot stripe priceid and user subscription
subscription dot stripe current period and question
dot stripe current period and question mark dot get time
mark dot get time plus they underscore in milliseconds
plus they underscore in milliseconds like this is larger sorry greater than
like this is larger sorry greater than date dot now like this
date dot now like this so I'm going to expand it even more and
so I'm going to expand it even more and to fix this error you can just go ahead
to fix this error you can just go ahead and put an exclamation point right here
and put an exclamation point right here so basically what we are doing here is
so basically what we are doing here is we are checking if the current
we are checking if the current subscription period End plus one uh why
subscription period End plus one uh why we are giving it one uh day of grace
we are giving it one uh day of grace period is larger than the current date
period is larger than the current date and that's the way we check if it has
and that's the way we check if it has expired or not and we're just gonna
expired or not and we're just gonna return
return question mark question mark is valid so
question mark question mark is valid so please make sure you don't accidentally
please make sure you don't accidentally do this it's not the same thing I'm
do this it's not the same thing I'm using question mark question mark to
using question mark question mark to ensure that this is valid is always a
ensure that this is valid is always a Boolean like this
Boolean like this there we go so we now have that and now
there we go so we now have that and now we can safely create our settings page
we can safely create our settings page so let's go ahead I'm going to close
so let's go ahead I'm going to close everything I'm going to go inside of my
everything I'm going to go inside of my app folder I'm going to inside the
app folder I'm going to inside the dashboard routes and I'm going to create
dashboard routes and I'm going to create a new folder called settings like this
a new folder called settings like this inside of settings I'm going to create a
inside of settings I'm going to create a page.dsx and let's go ahead and write
page.dsx and let's go ahead and write settings page like that and let's return
settings page like that and let's return a div like this and let's add a heading
a div like this and let's add a heading component from s slash components
component from s slash components heading like that let's give it a title
heading like that let's give it a title of settings let's give it a description
of settings let's give it a description of manage account settings like that
of manage account settings like that let's give it an icon of settings
let's give it an icon of settings from Lucid react let's give it an iPhone
from Lucid react let's give it an iPhone color of text Gray Dash 700 and let's
color of text Gray Dash 700 and let's give it the BG color of BG Dash gray
give it the BG color of BG Dash gray Dash 700 10 like this and I'm just going
Dash 700 10 like this and I'm just going to separate this Imports and let's
to separate this Imports and let's actually try and go to our settings now
actually try and go to our settings now there we go so we are on the slash
there we go so we are on the slash settings and it's showing this exact
settings and it's showing this exact thing that we are calling right now
thing that we are calling right now great so let's stay here and below the
great so let's stay here and below the heading let's create a div with a class
heading let's create a div with a class name of bx-4 a large is going to be
name of bx-4 a large is going to be px-8 space Dash y-4 like this let's
px-8 space Dash y-4 like this let's create a div with a class name of text
create a div with a class name of text Dash muted Dash foreground
Dash muted Dash foreground and tax Dash SM
and tax Dash SM and inside we are either going to say
and inside we are either going to say you're currently subscribed to a Pro
you're currently subscribed to a Pro Plan or you're currently on a free plan
Plan or you're currently on a free plan so what is the conditional to use that
so what is the conditional to use that well we're going to use the udle we just
well we're going to use the udle we just created so let's go ahead since this is
created so let's go ahead since this is a server component we can just write
a server component we can just write const is pro to be await check
const is pro to be await check subscription from s slash lib
subscription from s slash lib subscription and make sure to mark this
subscription and make sure to mark this as a synchronous function there we go so
as a synchronous function there we go so now we have the is pro right here and we
now we have the is pro right here and we can use conditional now so is Pro in
can use conditional now so is Pro in that case you are currently on a Pro
that case you are currently on a Pro Plan
Plan otherwise
otherwise you are currently on a free plan like
you are currently on a free plan like this
this there we go you can see for me it says
there we go you can see for me it says that I'm currently on a Pro Plan because
that I'm currently on a Pro Plan because I just did a success I just did a
I just did a success I just did a successful subscription and you can see
successful subscription and you can see that my subscription is in the prisoner
that my subscription is in the prisoner studio and since I just did it it's
studio and since I just did it it's certainly not expired perfect so it
certainly not expired perfect so it works exactly as we expect it to work
works exactly as we expect it to work and what we want to do now is we want to
and what we want to do now is we want to create a button to show uh billing
create a button to show uh billing inside right so let's go ahead and let's
inside right so let's go ahead and let's do that so in order to do that we're
do that so in order to do that we're gonna have to create another component
gonna have to create another component called the subscription button let's go
called the subscription button let's go ahead I'm going to close everything
ahead I'm going to close everything going to components and create a new
going to components and create a new file subscription underscore button uh
file subscription underscore button uh sorry Dash button.ensx like this let's
sorry Dash button.ensx like this let's go ahead and Export cons subscription
go ahead and Export cons subscription button like this
button like this and let's write an interface for it so
and let's write an interface for it so interface subscription button props is
interface subscription button props is going to take is pro option which is a
going to take is pro option which is a Boolean like this
Boolean like this great
great and I did a mistake here so it should be
and I did a mistake here so it should be like this sorry and let's extract is pro
like this sorry and let's extract is pro here let's give it a default value of
here let's give it a default value of false and let's assign the props
false and let's assign the props subscription button props like that
subscription button props like that great and I let's just immediately mark
great and I let's just immediately mark this as in use client like this
this as in use client like this and let's go ahead and let's return a
and let's go ahead and let's return a button component from dot slash UI
button component from dot slash UI button or you can rename it to
button or you can rename it to components UI button like this and
components UI button like this and inside I'm going to use the is pro to
inside I'm going to use the is pro to either say manage subscription or
either say manage subscription or upgrade so depending on VR subscriber or
upgrade so depending on VR subscriber or not it's going to be different when user
not it's going to be different when user visits their subs their settings page
visits their subs their settings page and here we're gonna do the opposite so
and here we're gonna do the opposite so if it's not pro
if it's not pro in that case we're going to add the
in that case we're going to add the little zap icon we already did a couple
little zap icon we already did a couple of times from Lucid react like this and
of times from Lucid react like this and let's go ahead and give it a class name
let's go ahead and give it a class name of
of w-4h-4 margin left to and fill Dash
w-4h-4 margin left to and fill Dash white like this and now for the variant
white like this and now for the variant we're also going to use the is pro
we're also going to use the is pro condition here so if we are pro we're
condition here so if we are pro we're going to use default otherwise we're
going to use default otherwise we're going to use premium great and let's go
going to use premium great and let's go ahead and add on click to be on click
ahead and add on click to be on click which we have to create right now so
which we have to create right now so let's go ahead and write const on click
let's go ahead and write const on click it's going to be an asynchronous
it's going to be an asynchronous Arrow function like this uh let's open a
Arrow function like this uh let's open a try and cache block so error console log
try and cache block so error console log Billings error like this
Billings error like this inside of here let's go ahead and write
inside of here let's go ahead and write const response is going to be again a
const response is going to be again a weight
weight access dot get
access dot get slash API slash stripe like this so the
slash API slash stripe like this so the same place and make sure you import the
same place and make sure you import the axis so the same place we are doing in
axis so the same place we are doing in the pro model but what is the difference
the pro model but what is the difference well there isn't a difference but our
well there isn't a difference but our API
API our route for our stripe is very smart
our route for our stripe is very smart so it knows whether we actually have a
so it knows whether we actually have a subscription or don't so if we have a
subscription or don't so if we have a subscription in that case we are going
subscription in that case we are going to open the billing page otherwise we
to open the billing page otherwise we are going to open the checkout page so
are going to open the checkout page so you don't have to do anything different
you don't have to do anything different on the client which is great and then
on the client which is great and then let's just do
window.location.hrefresponse.data.url right here and let's just quickly add
right here and let's just quickly add the loading States a const loading set
the loading States a const loading set loading
loading is going to be your state false
is going to be your state false make sure you uh import this from react
make sure you uh import this from react of course
of course great let's set the loading the true in
great let's set the loading the true in the try Block in the finally let's do
the try Block in the finally let's do set loading to false like this and let's
set loading to false like this and let's add the disabled prop to be loading here
add the disabled prop to be loading here as well great so now we have this
as well great so now we have this subscription button meaning that we can
subscription button meaning that we can go back inside of our settings page and
go back inside of our settings page and just above below this div holding our
just above below this div holding our text let's render that subscription
text let's render that subscription button from add slash components
button from add slash components subscription button right here and let's
subscription button right here and let's pass in the is pro to be is pro like
pass in the is pro to be is pro like this there we go so you can see that now
this there we go so you can see that now it says manage subscription and if I
it says manage subscription and if I click on it let's see if it's gonna take
click on it let's see if it's gonna take me to the checkout page I think we're
me to the checkout page I think we're actually going to get an error yes so
actually going to get an error yes so we're gonna get an error if I look at my
we're gonna get an error if I look at my console there we go billing error in my
console there we go billing error in my console uh what we forgot to do
console uh what we forgot to do and a very easy way to fix it is to go
and a very easy way to fix it is to go inside of your terminal
inside of your terminal right here uh inside of here and there
right here uh inside of here and there we go I think this is we're gonna see uh
we go I think this is we're gonna see uh your error
your error so I'm going to zoom out so you can read
so I'm going to zoom out so you can read a bit better it's going to tell you
a bit better it's going to tell you exactly what went wrong and it says you
exactly what went wrong and it says you can't create a portal session in test
can't create a portal session in test mode until you save your customer portal
mode until you save your customer portal settings in test mode so if you can't
settings in test mode so if you can't find this link I you can just click on
find this link I you can just click on this link and fix it but if for some
this link and fix it but if for some reason you can't find this in your
reason you can't find this in your console let's go to stripe together and
console let's go to stripe together and try to find that right here so I'm going
try to find that right here so I'm going to close this
to close this right here and let's see so what does it
right here and let's see so what does it say uh I'm gonna scroll a bit down so it
say uh I'm gonna scroll a bit down so it mentioned the customer portal right so
mentioned the customer portal right so let's see how we can search that
let's see how we can search that customer portal okay so settings billing
customer portal okay so settings billing customer portal right here test mode and
customer portal right here test mode and you have to click this activate link
you have to click this activate link button right here so you can either
button right here so you can either click on that link from your terminal
click on that link from your terminal which is much faster but it's for some
which is much faster but it's for some reason you can't find that in your
reason you can't find that in your terminal this is how you do it and now
terminal this is how you do it and now let's refresh this and let's try the
let's refresh this and let's try the very same thing again I'm fairly
very same thing again I'm fairly confident that this time
confident that this time there we go it's loading and we are
there we go it's loading and we are redirected uh back to billing so let's
redirected uh back to billing so let's just wait a couple of seconds to see how
just wait a couple of seconds to see how that looks there we go perfect you can
that looks there we go perfect you can see when it expires and absolutely
see when it expires and absolutely everything great so let's go ahead and
everything great so let's go ahead and let's return back to AI SAS tutorial uh
let's return back to AI SAS tutorial uh perfect great great job
perfect great great job so before we do that I just want to play
so before we do that I just want to play around with more with this subscription
around with more with this subscription and all it can do so currently when we
and all it can do so currently when we click on manage subscription and get
click on manage subscription and get this loading State you can see that it
this loading State you can see that it says that it expires in 2055 right so
says that it expires in 2055 right so let's go ahead and try and modify the
let's go ahead and try and modify the values to see the one that matches so
values to see the one that matches so I'm going to go ahead and I'm going to
I'm going to go ahead and I'm going to remove my user subscription from Prisma
remove my user subscription from Prisma I'm going to click delete this record
I'm going to click delete this record right here so and now it's saving
right here so and now it's saving changes I'm going to refresh and there
changes I'm going to refresh and there we go no user subscriptions now I'm
we go no user subscriptions now I'm going to refresh here again and this
going to refresh here again and this time when I click on here it's actually
time when I click on here it's actually going to redirect me to the checkout
going to redirect me to the checkout page but before we do that let's go back
page but before we do that let's go back inside of our web hook right here where
inside of our web hook right here where we actually create the subscription
we actually create the subscription right here and let's see if we can
right here and let's see if we can modify the period end that to match only
modify the period end that to match only one month
one month and I just realized that I gave you
and I just realized that I gave you completely wrong information we don't
completely wrong information we don't have to change anything so what I read
have to change anything so what I read was the expiration for the credit card
was the expiration for the credit card not for the subscription my apologies
not for the subscription my apologies but still while we're here let's test
but still while we're here let's test out this button and how it looks when we
out this button and how it looks when we are not subscribed so make sure you have
are not subscribed so make sure you have removed the subscription from Prisma
removed the subscription from Prisma uh one more thing if Prisma studio is
uh one more thing if Prisma studio is not working for you the way you can
not working for you the way you can remove everything from your database is
remove everything from your database is by using the terminal so I'm going to go
by using the terminal so I'm going to go ahead and open another one and I'm going
ahead and open another one and I'm going to write ntx Prisma
to write ntx Prisma migrate reset like this so this is going
migrate reset like this so this is going to clear the entire database and just
to clear the entire database and just confirm that with yes and one important
confirm that with yes and one important thing after you do this make sure you do
thing after you do this make sure you do npx Prisma generate again and npx
npx Prisma generate again and npx freesma DB push so very important that
freesma DB push so very important that you do the npx Prisma DB push after that
you do the npx Prisma DB push after that so this just cleared the entire database
so this just cleared the entire database so now I'm also not going to have any
so now I'm also not going to have any Generations at all see so I just wanted
Generations at all see so I just wanted to give you that information in case
to give you that information in case studio is not working for you for any
studio is not working for you for any reason great so let's test this to
reason great so let's test this to upgrade now right here so I'm gonna give
upgrade now right here so I'm gonna give it a fake credit card
it a fake credit card my name and let's click subscribe right
my name and let's click subscribe right here
here after a couple of seconds we're gonna go
after a couple of seconds we're gonna go ahead and get redirected back to
ahead and get redirected back to settings let's click on manage
settings let's click on manage subscription this time and now we are
subscription this time and now we are here and there we go you can see that
here and there we go you can see that it's a month from now so right now it's
it's a month from now so right now it's July and we're gonna have to uh we're
July and we're gonna have to uh we're gonna have to renew in August great so
gonna have to renew in August great so make sure you have a subscription active
make sure you have a subscription active make sure that oops I just clicked again
make sure that oops I just clicked again whoop
whoop yes so make sure this says you're
yes so make sure this says you're currently in a Pro Plan make sure in
currently in a Pro Plan make sure in Prisma Studio that you have an active
Prisma Studio that you have an active user subscription working and now we can
user subscription working and now we can go ahead and actually enable this uh
go ahead and actually enable this uh these models right now so right now I
these models right now so right now I have all three generations so I'm just
have all three generations so I'm just gonna go ahead and fill them up so I'm
gonna go ahead and fill them up so I'm going to use this to create my first a
going to use this to create my first a one out of five free Generations I'm
one out of five free Generations I'm gonna go back in my Prisma Studio I'm
gonna go back in my Prisma Studio I'm gonna go to user API limit I'm gonna
gonna go to user API limit I'm gonna find the one for my user and I'm going
find the one for my user and I'm going to increase the count to five so I
to increase the count to five so I simulate filling up the entire uh the
simulate filling up the entire uh the entire uh three generations but still if
entire uh three generations but still if I try something now I still get the uh
I try something now I still get the uh premium model even though I'm obviously
premium model even though I'm obviously subscribed you can see that right here
subscribed you can see that right here so let's slowly go ahead in each route
so let's slowly go ahead in each route uh and let's go ahead and fix these
uh and let's go ahead and fix these things so first thing I actually want to
things so first thing I actually want to change is I no longer want to show this
change is I no longer want to show this three generations if we are subscribed
three generations if we are subscribed so let's do that first I think that's
so let's do that first I think that's the easiest thing to change let's go
the easiest thing to change let's go ahead inside of our components inside of
ahead inside of our components inside of free counter right here and what we're
free counter right here and what we're going to do is we're going to accept
going to do is we're going to accept another prompt here called is pro like
another prompt here called is pro like this which is a Boolean like that
this which is a Boolean like that is pro is going to be false by default
is pro is going to be false by default and in here I'm just going to add if we
and in here I'm just going to add if we are pro so it is pro return null as well
are pro so it is pro return null as well and now what we have to do is we have to
and now what we have to do is we have to also add that to the sidebar so let's go
also add that to the sidebar so let's go inside of our sidebar component right
inside of our sidebar component right here
here let's go ahead and add is pro Boolean
let's go ahead and add is pro Boolean prop right here let's go ahead and
prop right here let's go ahead and extract it here so it's Pro right here
extract it here so it's Pro right here to be false like that and let's pass it
to be false like that and let's pass it here to the free counter is pro is pro
here to the free counter is pro is pro like that and now we have to oh I forgot
like that and now we have to oh I forgot to put a comma
to put a comma okay and now let's go inside of our app
okay and now let's go inside of our app folder dashboard layout.tsx and let's
folder dashboard layout.tsx and let's just add const is pro to be away check
just add const is pro to be away check subscription like this from s slash lib
subscription like this from s slash lib subscription and pass in is pro to be is
subscription and pass in is pro to be is pro like this great so now if I extract
pro like this great so now if I extract this you can see that it no longer
this you can see that it no longer appears here because we are on Pro and
appears here because we are on Pro and what we have to do next is also do that
what we have to do next is also do that on mobile so let's go inside of our
on mobile so let's go inside of our components inside of navbar right here
components inside of navbar right here and let's add const is pro await check
and let's add const is pro await check subscription
subscription from s slash lip subscription and let's
from s slash lip subscription and let's pass this to mobile sidebar so it's Pro
pass this to mobile sidebar so it's Pro is pro like this let's go inside of the
is pro like this let's go inside of the mobile sidebar component which is inside
mobile sidebar component which is inside of your components folder right here
of your components folder right here let's go ahead and add its Pro Boolean
let's go ahead and add its Pro Boolean right here
right here let's extract is pro here and let's give
let's extract is pro here and let's give it a value of false and let's give this
it a value of false and let's give this a value of 0 while we are here and let's
a value of 0 while we are here and let's pass in the is row is pro right here
pass in the is row is pro right here there we go so now it's working on
there we go so now it's working on mobile sidebar as well great so we just
mobile sidebar as well great so we just fixed the UI for this and now what we
fixed the UI for this and now what we have to do is we have to go through
have to do is we have to go through individual routes and fix the generation
individual routes and fix the generation problem so still if I try since I'm in 5
problem so still if I try since I'm in 5 out of 5 on my count I'm getting this
out of 5 on my count I'm getting this pro model so let's go inside of our app
pro model so let's go inside of our app folder inside of API inside of
folder inside of API inside of conversation route.ts and let's go ahead
conversation route.ts and let's go ahead and resolve this so first thing I'm
and resolve this so first thing I'm going to add besides this API limit is
going to add besides this API limit is I'm going to add import
I'm going to add import check subscription from add slash lib
check subscription from add slash lib subscription right here and here where I
subscription right here and here where I fetch my free trial I'm also going to
fetch my free trial I'm also going to check const is pro to be a weight check
check const is pro to be a weight check subscription like this
subscription like this and then I'm gonna add to this if Clause
and then I'm gonna add to this if Clause so if there is no free trial and if we
so if there is no free trial and if we are not
are not bro only then do we throw the error and
bro only then do we throw the error and same thing goes for increasing the API
same thing goes for increasing the API limit so we only want to increase it if
limit so we only want to increase it if we are not pro so if question mark is
we are not pro so if question mark is pro sorry if exclamation point is pro
pro sorry if exclamation point is pro like this and now if you go ahead and
like this and now if you go ahead and test your conversation so test and click
test your conversation so test and click generate you can see that we are
generate you can see that we are officially on Pro meaning that we are
officially on Pro meaning that we are not blocked from using the open AI model
not blocked from using the open AI model because we have an active subscription
because we have an active subscription uh great and what we have to do now is
uh great and what we have to do now is we have to copy this in all of our
we have to copy this in all of our routes so let's go ahead and let's do
routes so let's go ahead and let's do that so I'm going to go ahead
that so I'm going to go ahead and I'm going to copy these two lines
and I'm going to copy these two lines right here so it's taking some time so
right here so it's taking some time so let me just refresh this and see what's
let me just refresh this and see what's going on
going on okay so what happened in my case is that
okay so what happened in my case is that the service randomly fell down so what I
the service randomly fell down so what I did was I shut down my application I ran
did was I shut down my application I ran npm run Dev again and I refreshed my
npm run Dev again and I refreshed my page that's it I also confirmed that my
page that's it I also confirmed that my usage has not been uh filled up great so
usage has not been uh filled up great so now that we have that working uh you can
now that we have that working uh you can see how it's no longer blocking us with
see how it's no longer blocking us with the premium model we have to do that for
the premium model we have to do that for the rest of the routes so go ahead and
the rest of the routes so go ahead and just copy this if clause and these two
just copy this if clause and these two lines right here because we're going to
lines right here because we're going to need them in the rest so let's go ahead
need them in the rest so let's go ahead and do code as well so replace this with
and do code as well so replace this with what with what we just copied import
what with what we just copied import check subscription from s slash lib
check subscription from s slash lib check subscription like we did right
check subscription like we did right here so I'm just going to expand it
here so I'm just going to expand it great and now that we have this let's
great and now that we have this let's also wrap the this so if we are not pro
also wrap the this so if we are not pro in that case let's go ahead
in that case let's go ahead and just do this great so now our code
and just do this great so now our code should work as well now let's go inside
should work as well now let's go inside of image
of image let's go ahead and replace this free
let's go ahead and replace this free trial as well let's import check
trial as well let's import check subscription
subscription from add slash lip subscription like
from add slash lip subscription like that let's go ahead and wrap this so if
that let's go ahead and wrap this so if we are not pro
we are not pro in that case go ahead
in that case go ahead and
and wrap this in this if Clause great let's
wrap this in this if Clause great let's do the same for music so I'm going to
do the same for music so I'm going to replace this paste it here import check
replace this paste it here import check subscription from add slash lib
subscription from add slash lib subscription like this great and here
subscription like this great and here again only if we are not pro do we
again only if we are not pro do we increase this API limit like this
increase this API limit like this and last one uh let's do the video right
and last one uh let's do the video right here so again select the if clause and
here so again select the if clause and free trial paste it import check
free trial paste it import check subscription
subscription from lib subscription like this and only
from lib subscription like this and only increase the limit if we are on Pro so
increase the limit if we are on Pro so if we are not on Pro in that case no
if we are not on Pro in that case no point in increasing this
point in increasing this perfect now let's go ahead
perfect now let's go ahead and let's check if this is working fine
and let's check if this is working fine so conversation we confirm that that is
so conversation we confirm that that is working how about we try this so a
working how about we try this so a picture of Swiss Alps for example let's
picture of Swiss Alps for example let's check if that is working fine now so I'm
check if that is working fine now so I'm just gonna wait a couple of seconds here
just gonna wait a couple of seconds here there we go that is working fine I'm
there we go that is working fine I'm just gonna quickly try and Trigger the
just gonna quickly try and Trigger the video generation for example clown Fair
video generation for example clown Fair swimming around a coral reef and I'm
swimming around a coral reef and I'm just gonna wait a couple of seconds to
just gonna wait a couple of seconds to confirm there is no model popping up
confirm there is no model popping up okay we are not gonna wait for the whole
okay we are not gonna wait for the whole video and same thing for uh the music so
video and same thing for uh the music so piano solo let's wait a couple of
piano solo let's wait a couple of seconds great no model popping up
seconds great no model popping up meaning that it's working and same thing
meaning that it's working and same thing for code generation so simple toggle
for code generation so simple toggle button using react hooks I'm just gonna
button using react hooks I'm just gonna wait a couple of seconds and there we go
wait a couple of seconds and there we go you have officially implemented
you have officially implemented authentication sorry a subscription in
authentication sorry a subscription in your project and you can go ahead and
your project and you can go ahead and play around with that great great job so
play around with that great great job so far what we have to do next is Implement
far what we have to do next is Implement crisp for customer support and wrap up
crisp for customer support and wrap up with doing a landing page and finally
with doing a landing page and finally deployment
deployment before we move on to adding crisp chat
before we move on to adding crisp chat for customer conversation what I want to
for customer conversation what I want to do first is I just want to add
do first is I just want to add a loading state for my pro model so in
a loading state for my pro model so in order to do that I just quickly gonna go
order to do that I just quickly gonna go back inside of my components inside of
back inside of my components inside of pro model right here and you're going to
pro model right here and you're going to notice that we're setting a loading
notice that we're setting a loading state right here but we're not using it
state right here but we're not using it anywhere so I just want to add it to
anywhere so I just want to add it to this button right here
this button right here so disabled is going to be
so disabled is going to be loading like this so I just wanted to do
loading like this so I just wanted to do that so our loading state is not wasted
that so our loading state is not wasted uh great so if you want to you can
uh great so if you want to you can remove your subscription and test the
remove your subscription and test the loading model again uh or well you can
loading model again uh or well you can just leave it like this and move on
just leave it like this and move on now what I want to do is I want to add a
now what I want to do is I want to add a some better error handling because right
some better error handling because right now if we get an error in any of this
now if we get an error in any of this models or stripe or anything we actually
models or stripe or anything we actually don't get any toast notification about
don't get any toast notification about it it just stops generating so let's go
it it just stops generating so let's go ahead and let's go inside of our
ahead and let's go inside of our terminal so yeah what I have running
terminal so yeah what I have running here is my npm run Dev here I have the
here is my npm run Dev here I have the Prisma studio and here I have the stripe
Prisma studio and here I have the stripe web hooks so make sure you have those
web hooks so make sure you have those running as well so I'm going to go ahead
running as well so I'm going to go ahead and I'm going to install a package
and I'm going to install a package called react hot toast so go ahead and
called react hot toast so go ahead and run npm install react Dash hot Dash
run npm install react Dash hot Dash toast like this and after a couple of
toast like this and after a couple of seconds go ahead actually yeah so I'm
seconds go ahead actually yeah so I'm already running the application in this
already running the application in this terminal but you can still just refresh
terminal but you can still just refresh uh great now let's go ahead and let's go
uh great now let's go ahead and let's go inside of our components and let's
inside of our components and let's create a new file called toaster Dash
create a new file called toaster Dash provider.tsx mark this as use client so
provider.tsx mark this as use client so let me just give you the full name uh so
let me just give you the full name uh so toaster Dash provider.dsx that's the
toaster Dash provider.dsx that's the full name of the component great and
full name of the component great and Export cons toaster provider it's going
Export cons toaster provider it's going to be a very simple function which just
to be a very simple function which just Returns the toaster from react hot toast
Returns the toaster from react hot toast like this great and now that we have
like this great and now that we have this what you can do is go inside of
this what you can do is go inside of your app inside the layout.tsx and the
your app inside the layout.tsx and the same way you edit model provider just
same way you edit model provider just add the toast provider toaster provider
add the toast provider toaster provider like this there we go and import it from
like this there we go and import it from add slash components toaster provider
add slash components toaster provider great and now that you have that let's
great and now that you have that let's for example go inside of app folder
for example go inside of app folder inside of dashboard routes conversation
inside of dashboard routes conversation page right here and here where we have
page right here and here where we have our error you can add an else to this
our error you can add an else to this pro model on open so this is the on
pro model on open so this is the on submit function right so go inside of
submit function right so go inside of here find this handling of 403 error and
here find this handling of 403 error and you can just add toast which you can
you can just add toast which you can import from react hot toast so I just
import from react hot toast so I just added that right here and I'm gonna move
added that right here and I'm gonna move it all the way to the top right here
it all the way to the top right here and you can just write those dot error
and you can just write those dot error something went wrong like that
something went wrong like that so now I'm going to purposely throw an
so now I'm going to purposely throw an error in here so in this try I'm going
error in here so in this try I'm going to write throw new error something like
to write throw new error something like this
this and I'm gonna refresh and I'm gonna go
and I'm gonna refresh and I'm gonna go inside of my conversation here and I'm
inside of my conversation here and I'm gonna try and generate and there we go
gonna try and generate and there we go now we have a nice uh toast that
now we have a nice uh toast that something went wrong so that's just what
something went wrong so that's just what I wanted to do in case anything in here
I wanted to do in case anything in here goes wrong let's at least give our users
goes wrong let's at least give our users a nice message here so let's do that for
a nice message here so let's do that for code as well so just find the on submit
code as well so just find the on submit and just paste it here and import toast
and just paste it here and import toast from react hot toast like this great
from react hot toast like this great let's go ahead and do the same thing for
let's go ahead and do the same thing for our image right here
our image right here so just catch that right there and
so just catch that right there and import toast from react hot toast again
import toast from react hot toast again and the same thing from music
and the same thing from music toast
toast like this and the same thing for video
like this and the same thing for video right here so there we go and don't
right here so there we go and don't forget to import toast here as well so
forget to import toast here as well so in all of these places you need to have
in all of these places you need to have toast imported from react hot toast and
toast imported from react hot toast and make sure it's in the else section of
make sure it's in the else section of this great and now that we have that
this great and now that we have that let's also do that in our pro model
let's also do that in our pro model right here
right here so instead of just rendering this error
so instead of just rendering this error right here let's just actually do the
right here let's just actually do the toast which you can import from react.to
toast which you can import from react.to error something
went wrong like this so make sure you imported the toast great and now that
imported the toast great and now that you have that let's also do it in the
you have that let's also do it in the subscription button component here so
subscription button component here so instead of console logging the error
instead of console logging the error there we go and of course import toast
there we go and of course import toast here as well great so now we have a
here as well great so now we have a nicer error handling in our project
nicer error handling in our project great so let's go ahead and let's set up
great so let's go ahead and let's set up crisp now so in order to do that the
crisp now so in order to do that the first thing we have to do obviously is
first thing we have to do obviously is we have to create an account for crisp
we have to create an account for crisp so either go to crisp.chat or write
so either go to crisp.chat or write crisp chat on Google and go ahead and
crisp chat on Google and go ahead and click get started or log in and of
click get started or log in and of course it's free so just finish this
course it's free so just finish this input I'm gonna pause the video and show
input I'm gonna pause the video and show you the dashboard
you the dashboard so in this step what you can do is just
so in this step what you can do is just name this genius and leave this to be
name this genius and leave this to be www.dummy.com so it doesn't matter for
www.dummy.com so it doesn't matter for now later you can add it to your actual
now later you can add it to your actual uh production website so I just wanted
uh production website so I just wanted to clear that up
to clear that up great so now that you get this message
great so now that you get this message right here the only thing that matters
right here the only thing that matters for you really is this code right here
for you really is this code right here so you can technically just add this
so you can technically just add this script but since we are working with
script but since we are working with react we actually have a package for
react we actually have a package for this so let's go ahead and let's install
this so let's go ahead and let's install a package and stay on this screen right
a package and stay on this screen right here
here so I'm going to go ahead and I'm going
so I'm going to go ahead and I'm going to install ambient install crisp SDK web
to install ambient install crisp SDK web like this wait a couple of seconds and
like this wait a couple of seconds and great and now let's go ahead inside of
great and now let's go ahead inside of our components folder and create a new
our components folder and create a new folder sorry create a new file inside
folder sorry create a new file inside called
called crisp.chat.dsx like this go ahead and
crisp.chat.dsx like this go ahead and Mark this as use client go ahead and
Mark this as use client go ahead and import use effect from react go ahead
import use effect from react go ahead and import crisp from crisp SDK web like
and import crisp from crisp SDK web like this and Export const press chat like
this and Export const press chat like this
this and inside views effect you're gonna go
and inside views effect you're gonna go ahead
ahead whoops
whoops add an empty array here and just run
add an empty array here and just run crisp.configure like this and inside
crisp.configure like this and inside you're going to paste this crisp website
you're going to paste this crisp website ID right here so let me zoom in to show
ID right here so let me zoom in to show you exactly what you have to copy so you
you exactly what you have to copy so you have window dot crisp website ID and
have window dot crisp website ID and copy what is inside of this strings
copy what is inside of this strings right here so you can copy the entire
right here so you can copy the entire string if you want to so all the way to
string if you want to so all the way to here like this there we go and then just
here like this there we go and then just paste it inside like this so make sure
paste it inside like this so make sure you don't accidentally have double
you don't accidentally have double quotes So if you have it like this this
quotes So if you have it like this this is wrong right you have to have it like
is wrong right you have to have it like this there we go and just paste that
this there we go and just paste that great so I'm going to zoom out now
great so I'm going to zoom out now whoops I'm going to zoom out here uh and
whoops I'm going to zoom out here uh and let's go ahead and just return null here
let's go ahead and just return null here great and now that you have uh that what
great and now that you have uh that what you have to do is create a crisp
you have to do is create a crisp provider so go inside components new
provider so go inside components new file crisp provider.tsx
file crisp provider.tsx so let me just expand this so you can
so let me just expand this so you can see uh the full component name so crisp
see uh the full component name so crisp Dash provider like this Mark this as use
Dash provider like this Mark this as use client again
client again and just write the import
and just write the import risk chat from dot slash crisp chat or
risk chat from dot slash crisp chat or slash components crisp chat and Export
slash components crisp chat and Export cons crisp provider
cons crisp provider like this return crisp chat like this
like this return crisp chat like this great and now that you have that all you
great and now that you have that all you have to do
have to do is add the crisp provider to your app
is add the crisp provider to your app layout so go inside app layout right
layout so go inside app layout right here and go ahead and paste it above the
here and go ahead and paste it above the body so crisp provider like this and
body so crisp provider like this and import it the same way you did with
import it the same way you did with toaster provider and model provider
toaster provider and model provider great and I think that you can now click
great and I think that you can now click on Discover my dashboard here
on Discover my dashboard here uh okay I'm gonna extend this and there
uh okay I'm gonna extend this and there we go you can already see in my lower
we go you can already see in my lower left corner that I have a crisp icon
left corner that I have a crisp icon here so let's test this out so yeah we
here so let's test this out so yeah we have some messages here let's read that
have some messages here let's read that and let's go back in our inbox and now
and let's go back in our inbox and now I'm gonna go ahead and write something
I'm gonna go ahead and write something hello I have a problem with image
hello I have a problem with image generation like that and you can see how
generation like that and you can see how it immediately goes back here
it immediately goes back here perfect great great job so you
perfect great great job so you successfully implemented Clerk and you
successfully implemented Clerk and you can of course uh respond to your users
can of course uh respond to your users so what are you having problems with
so what are you having problems with like this and you can see uh how that is
like this and you can see uh how that is immediately reflected here great great
immediately reflected here great great job you successfully implemented uh
job you successfully implemented uh Advanced error handling as well as full
Advanced error handling as well as full customer support
customer support let's go ahead and let's create the last
let's go ahead and let's create the last part before deployment which is the
part before deployment which is the landing page so first of all go ahead
landing page so first of all go ahead and sign out so you are redirected back
and sign out so you are redirected back to slash or just go to localhost 3000
to slash or just go to localhost 3000 without any routes right here so you're
without any routes right here so you're on this landing page which we are
on this landing page which we are finally now uh gonna go ahead and make
finally now uh gonna go ahead and make it look like something so go inside of
it look like something so go inside of your app folder and go inside of this
your app folder and go inside of this Landing folder right here and go ahead
Landing folder right here and go ahead and create a new file called layout.tsx
and create a new file called layout.tsx like this go ahead and create a landing
like this go ahead and create a landing layout component like this
layout component like this the props is going to accept is children
the props is going to accept is children so go ahead and destructure children
so go ahead and destructure children like this and immediately go ahead and
like this and immediately go ahead and give it a type of children react dot
give it a type of children react dot react node like this and inside go ahead
react node like this and inside go ahead and create a main element like this and
and create a main element like this and give it a class name of H dash full BG
give it a class name of H dash full BG Dash hex code
Dash hex code 111827 like this and overflow Dash Auto
111827 like this and overflow Dash Auto like this and inside go ahead and create
like this and inside go ahead and create another div with a class name of MX Auto
another div with a class name of MX Auto like this Max W screen Dash XL H dash
like this Max W screen Dash XL H dash full NW Dash full like this
full NW Dash full like this and inside you're going to go ahead and
and inside you're going to go ahead and render the children like this great now
render the children like this great now let's go ahead inside of our page.tsx
let's go ahead inside of our page.tsx here
here and we can actually remove everything in
and we can actually remove everything in here create a new div with a class name
here create a new div with a class name of h-4 like this and you can remove
of h-4 like this and you can remove these imports from here
these imports from here like that and the first let's end the
like that and the first let's end the landing nav bar like this component so
landing nav bar like this component so of course if you save you're gonna get
of course if you save you're gonna get an error so let's go inside of our
an error so let's go inside of our components folder and go ahead and
components folder and go ahead and create a new file called Landing Dash
create a new file called Landing Dash navbar.tsx like this go ahead and Mark
navbar.tsx like this go ahead and Mark this as use client like that go ahead
this as use client like that go ahead and import Montserrat from next slash
and import Montserrat from next slash font slash Google go ahead and import
font slash Google go ahead and import image
image from next slash image import link from
from next slash image import link from next slash link import use out from
next slash link import use out from clerk like this import
clerk like this import CN probably utils and import button
CN probably utils and import button component from dot slash UI button or
component from dot slash UI button or slash components UI button like this
slash components UI button like this let's add our font constant so font is
let's add our font constant so font is Montserrat like this
Montserrat like this and inside of its object right away 3
and inside of its object right away 3 600 and subsets to be Latin like this
600 and subsets to be Latin like this great now let's export const Landing
great now let's export const Landing navbar like this it's an arrow function
navbar like this it's an arrow function and let's go ahead and extract the is
and let's go ahead and extract the is signed in from use out like this so why
signed in from use out like this so why are we using use out here from Clerk and
are we using use out here from Clerk and everywhere else if you remember if you
everywhere else if you remember if you search through this import we mostly
search through this import we mostly used Alf as you can see here for example
used Alf as you can see here for example we used out here so what's the
we used out here so what's the difference well use out is one of reacts
difference well use out is one of reacts code available in client components so
code available in client components so that's why I really like clerk because
that's why I really like clerk because they support both client components and
they support both client components and server components so you don't have to
server components so you don't have to pick one or another so that's why in
pick one or another so that's why in here we have to use a hook right if we
here we have to use a hook right if we want to use out that means we are in
want to use out that means we are in server components great so now let's go
server components great so now let's go ahead and return
ahead and return let's return another element like this
let's return another element like this let's give it a class name of p-4 BG
let's give it a class name of p-4 BG Dash transparent Flex item slash Center
Dash transparent Flex item slash Center and justify Dash between like that and
and justify Dash between like that and before we go any further with this let's
before we go any further with this let's go back inside of our landing page and
go back inside of our landing page and just import The Landing navbar from s
just import The Landing navbar from s slash components Landing navbar like
slash components Landing navbar like this so we don't have this error and see
this so we don't have this error and see we can actually see what we are
we can actually see what we are developing great now inside here let's
developing great now inside here let's go ahead and add this link component
go ahead and add this link component which we imported
which we imported let's go ahead and let's give it an href
let's go ahead and let's give it an href property to go uh to a slash like this
property to go uh to a slash like this and a class name of flex item slash
and a class name of flex item slash Center like that and inside let's go
Center like that and inside let's go ahead and create a div with a class name
ahead and create a div with a class name of relative
of relative h-8w-8 and margin right of four and
h-8w-8 and margin right of four and inside we're going to render an image
inside we're going to render an image give it a fill property give it an out
give it a fill property give it an out of logo and give it a source property of
of logo and give it a source property of Slash logo dot PNG like this great and
Slash logo dot PNG like this great and now just outside of this div which is
now just outside of this div which is wrapping our image go ahead and create
wrapping our image go ahead and create an H1 element genius like this and go
an H1 element genius like this and go ahead and give it a class name which is
ahead and give it a class name which is going to be dynamic so we are going to
going to be dynamic so we are going to use CN text Dash to excel font Dash bold
use CN text Dash to excel font Dash bold text Dash white and then add a comma and
text Dash white and then add a comma and write font Dash class name like this
write font Dash class name like this there we go so now we use the Montserrat
there we go so now we use the Montserrat font beautiful so I'm just gonna expand
font beautiful so I'm just gonna expand it so you can see how it looks in one
it so you can see how it looks in one line beautiful great besides this let's
line beautiful great besides this let's go ahead outside of this link component
go ahead outside of this link component and create a div
and create a div and let's create a class name
and let's create a class name Flex items Dash Center Gap Dash X-2 like
Flex items Dash Center Gap Dash X-2 like that and inside create another link
that and inside create another link component like this like this with an
component like this like this with an href which is going to be dynamic
href which is going to be dynamic dependent on whether we are logged in or
dependent on whether we are logged in or not so if if we are logged in in that
not so if if we are logged in in that case we're going to redirect to slash
case we're going to redirect to slash dashboard otherwise we're going to
dashboard otherwise we're going to redirect the slash sign up like this
redirect the slash sign up like this great and now inside of this link
great and now inside of this link component create a button like this get
component create a button like this get started like that and let's go ahead and
started like that and let's go ahead and give it a variant of outline like this
give it a variant of outline like this and let's give it the class name of
and let's give it the class name of rounded Dash full like this beautiful so
rounded Dash full like this beautiful so you successfully finished uh The Landing
you successfully finished uh The Landing nav bar now what we have to do is create
nav bar now what we have to do is create a landing hero so another component
a landing hero so another component Landing a hero like this so same thing
Landing a hero like this so same thing let's go inside of our components and
let's go inside of our components and create a new file called Landing Dash
create a new file called Landing Dash hero.dsx like this let's go ahead and
hero.dsx like this let's go ahead and Export comes Landing the hero here
Export comes Landing the hero here I'm just gonna write their native saying
I'm just gonna write their native saying hero and I'm gonna go back inside of my
hero and I'm gonna go back inside of my landing page here and just import
landing page here and just import Landing hero so we don't have an error
Landing hero so we don't have an error and so we can see what we are developing
and so we can see what we are developing so let's go back inside of the landing
so let's go back inside of the landing hero and same thing here let's go ahead
hero and same thing here let's go ahead and let's use is assign in from use out
and let's use is assign in from use out from clerk like that
from clerk like that and now let's go ahead and let's add a
and now let's go ahead and let's add a class name to this div so class name is
class name to this div so class name is going to be text Dash White
py-36 text Dash Center and space Dash y-5 like this and yes we have to mark
y-5 like this and yes we have to mark this as client component of course we
this as client component of course we are using a hook here great now inside
are using a hook here great now inside of here create a new div with a class
of here create a new div with a class name
name of text-4 Excel for mobile devices on
of text-4 Excel for mobile devices on small it's going to be tax 5xl on medium
small it's going to be tax 5xl on medium is going to be tax 6xl on large it's
is going to be tax 6xl on large it's going to be tax dash 7 Excel like this
going to be tax dash 7 Excel like this give it a space slash y-5 and font extra
give it a space slash y-5 and font extra mold like this
mold like this and inside uh let's go ahead and write
and inside uh let's go ahead and write H1 element the best
H1 element the best a i 2 or like this and you can see how
a i 2 or like this and you can see how the more I expand my screen the larger
the more I expand my screen the larger this text can become and the more I
this text can become and the more I Collapse it the smaller it's going to be
Collapse it the smaller it's going to be great and now let's go ahead and install
great and now let's go ahead and install a package called typewriter effect so
a package called typewriter effect so I'm going to go ahead and run npm
I'm going to go ahead and run npm install type writer Dash effect like
install type writer Dash effect like this and I'm going to press enter there
this and I'm going to press enter there we go so just refresh your page and now
we go so just refresh your page and now just below this let's create another div
just below this let's create another div with the class name of text Dash
with the class name of text Dash transparent
transparent BG Dash clip Dash text BG dash
BG Dash clip Dash text BG dash gradient-2 dash R so to write like this
gradient-2 dash R so to write like this after that from Dash purple Dash 400 to
after that from Dash purple Dash 400 to dash pink Dash 600 so we're going to
dash pink Dash 600 so we're going to give a gradient to our text inside and
give a gradient to our text inside and inside write the typewriter component
inside write the typewriter component like this from typewriter effect so
like this from typewriter effect so import type fighter component from Dash
import type fighter component from Dash typewriter effect like this it's a
typewriter effect like this it's a self-closing tag and go ahead and give
self-closing tag and go ahead and give it some options like this
it some options like this strings
strings and we're going to write chat bot with
and we're going to write chat bot with the dot and copy this a couple of times
the dot and copy this a couple of times so the second one is going to be photo
so the second one is going to be photo generation third one is going to be
generation third one is going to be music
music generation this one is going to be code
generation this one is going to be code generation and this one is going to be
generation and this one is going to be video generation like this
video generation like this great and now let's also give it an
great and now let's also give it an option of auto start true and loop
option of auto start true and loop through as well great and now you can
through as well great and now you can see how it seems like this is a
see how it seems like this is a typewriting effect beautiful and it
typewriting effect beautiful and it changes with all of the features that we
changes with all of the features that we have in our application great so really
have in our application great so really neat component here uh great now just go
neat component here uh great now just go ahead outside of this div right here
ahead outside of this div right here create a new div right here with a class
create a new div right here with a class name of text SM on small devices but the
name of text SM on small devices but the medium is going to be text Excel font
medium is going to be text Excel font dash light and text sync 400 like this
dash light and text sync 400 like this and go ahead and write create content
and go ahead and write create content using AI 10 times faster like this there
using AI 10 times faster like this there we go and let's go ahead
we go and let's go ahead uh and let's try and expand this
uh and let's try and expand this so you can see how it looks
so you can see how it looks great uh and now below that go ahead and
great uh and now below that go ahead and create a new div and then add a link
create a new div and then add a link inside
inside give this an href it's going to be
give this an href it's going to be dynamic so if we are signed in again
dynamic so if we are signed in again it's going to be slash dashboard
it's going to be slash dashboard otherwise it's going to be slash sign
otherwise it's going to be slash sign Dash up like this
Dash up like this and make sure you import the link
and make sure you import the link component not from Lucid react from next
component not from Lucid react from next slash link like this
slash link like this great so we have that now and let's add
great so we have that now and let's add a button component from dot slash UI
a button component from dot slash UI button or components UI button like this
button or components UI button like this great and inside of this button let's
great and inside of this button let's write start generating for
write start generating for for free like this
for free like this and let's give the variant of Premium
and let's give the variant of Premium like this and let's give it a class name
like this and let's give it a class name of MD tax Dash LG e-4
of MD tax Dash LG e-4 mdp-6 like this rounded Dash full and
mdp-6 like this rounded Dash full and font large semi bulb like this so we
font large semi bulb like this so we create a bit of a custom style depending
create a bit of a custom style depending uh on the screen size so here is the
uh on the screen size so here is the Fuller version there we go you can see
Fuller version there we go you can see how nicely it increases depending on our
how nicely it increases depending on our screen size
screen size uh great now that we have our button
uh great now that we have our button finished I'll just let's create a new
finished I'll just let's create a new div
div with a class name of text
with a class name of text sync-400 text that excess and medium is
sync-400 text that excess and medium is going to be textlash SM and font Dash
going to be textlash SM and font Dash normal like this uh no credit card
normal like this uh no credit card required like this because we have a
required like this because we have a free tier so users can test this out for
free tier so users can test this out for free uh great so you successfully
free uh great so you successfully finished the hero component now all
finished the hero component now all that's left is the landing component so
that's left is the landing component so let's go back inside of our layout page
let's go back inside of our layout page right here
right here and let's add a new component chord uh
and let's add a new component chord uh Landing content like this and same thing
Landing content like this and same thing let's go inside of components create a
let's go inside of components create a file called Landing Dash content.tsx
file called Landing Dash content.tsx export const Landing content like this
export const Landing content like this and let's just return it div same
and let's just return it div same content let's go back inside of our
content let's go back inside of our landing page and import Landing content
landing page and import Landing content like this from components Landing
like this from components Landing content so this error goes away great
content so this error goes away great now let's go ahead and let's create a
now let's go ahead and let's create a class name here so class name is going
class name here so class name is going to be px-10 pb-20 like that remove this
to be px-10 pb-20 like that remove this add an H2 element same testimonials
add an H2 element same testimonials like this and a class name of text
like this and a class name of text Center text-4 Excel text Dash white font
Center text-4 Excel text Dash white font Dash extra bold and margin bottom of 10
Dash extra bold and margin bottom of 10 like this great and now let's create a
like this great and now let's create a new div which is going to be our grid so
new div which is going to be our grid so grid grid
grid grid grid Dash calls dash one on small
grid Dash calls dash one on small devices SM grid Dash
three LG grid Dash course Dash 4 and GAP 4 like this great and now let's go ahead
4 like this great and now let's go ahead and create an array of our testimonials
and create an array of our testimonials at the top of this page
at the top of this page so we can also Mark this as use client
so we can also Mark this as use client as well and let's write const
as well and let's write const testimonials like this
which is an array we're just going to have objects so name
have objects so name I don't know Antonio
I don't know Antonio Avatar is going to be a like this
Avatar is going to be a like this title is going to be software engineer
title is going to be software engineer and description
and description is going to be this is the best
is going to be this is the best application I've used or pretty much
application I've used or pretty much whatever you want inside great and now
whatever you want inside great and now that we have one element inside let's
that we have one element inside let's actually go ahead and render that
actually go ahead and render that immediately so you can see what we're
immediately so you can see what we're working with so testimonials dot map
working with so testimonials dot map uh item like that let's go ahead and
uh item like that let's go ahead and return a card so import card from dot
return a card so import card from dot slash UI card or from slash components
slash UI card or from slash components like this
like this let's go ahead and give it a key which
let's go ahead and give it a key which is going to be item.description and the
is going to be item.description and the class name is gonna be BG Dash uh hash
class name is gonna be BG Dash uh hash 192339 like this border Dash none and
192339 like this border Dash none and tax Dash white like this great and
tax Dash white like this great and inside add a card header again from s
inside add a card header again from s slash components uh UI card like this
slash components uh UI card like this great let's go ahead and give this uh a
great let's go ahead and give this uh a card title in inside so make sure you
card title in inside so make sure you imported car title as well great
imported car title as well great and give this a class name
like this of Plex item slash Center ngap-x slash two like this right so you
ngap-x slash two like this right so you can see a little component right here uh
can see a little component right here uh great and inside of this card title open
great and inside of this card title open a div open a paragraph and write item
a div open a paragraph and write item dot name like this and copy that and
dot name like this and copy that and write item dot title like this
write item dot title like this great and now let's give it some Styles
great and now let's give it some Styles so right here I'm gonna write class name
text LG like this and here class name is going to be tax Dash sync
going to be tax Dash sync Dash 400 and text last at the text Dash
Dash 400 and text last at the text Dash SM like this great so that's it for card
SM like this great so that's it for card title and now let's write card content
title and now let's write card content like that
like that inside and we're going to render
inside and we're going to render item.description inside great and give
item.description inside great and give it a class name of pt-4
it a class name of pt-4 npx-0 like this there we go and we can
npx-0 like this there we go and we can go ahead and copy this as many times as
go ahead and copy this as many times as you want so I'm going to copy it four
you want so I'm going to copy it four times and there we go you have your
times and there we go you have your testimonials page and you can go ahead
testimonials page and you can go ahead and edit this the way you like perfect
and edit this the way you like perfect it's a great great job you finished the
it's a great great job you finished the entire software as a service with
entire software as a service with landing page stripe authentication five
landing page stripe authentication five different AI models customer support
different AI models customer support you've done an amazing and amazing job
you've done an amazing and amazing job all that's left is to learn how to
all that's left is to learn how to deploy this application
so let's go ahead and let's deploy our application so first thing we have to do
application so first thing we have to do is we have to go inside of our
is we have to go inside of our package.json right here and we have to
package.json right here and we have to add a post install script to be Prisma
add a post install script to be Prisma generate like this great now I'm gonna
generate like this great now I'm gonna go inside of my terminal and you can
go inside of my terminal and you can finally shut down all of this web Hooks
finally shut down all of this web Hooks and Prisma Studios and whatnot so I'm
and Prisma Studios and whatnot so I'm going to shut down all of this and I'm
going to shut down all of this and I'm gonna only live uh one open like this
gonna only live uh one open like this great now what I want you to run is npm
great now what I want you to run is npm run lint so go ahead and check if there
run lint so go ahead and check if there are any errors in your project so I
are any errors in your project so I don't have any errors so great what I'm
don't have any errors so great what I'm going to do next is I'm going to go
going to do next is I'm going to go inside GitHub and I'm gonna go ahead and
inside GitHub and I'm gonna go ahead and create a new Repository
create a new Repository I'm going to name this repository AI SAS
I'm going to name this repository AI SAS tutorial like this it's going to be
tutorial like this it's going to be private for me and I'm going to click
private for me and I'm going to click create repository right here and since
create repository right here and since this is an existing repository I'm going
this is an existing repository I'm going to use the second option so push an
to use the second option so push an existing repository from the command
existing repository from the command line I'm going to copy all of this and
line I'm going to copy all of this and I'm going to paste it here but actually
I'm going to paste it here but actually before I do that ignore this go ahead
before I do that ignore this go ahead and give it a git add get commit
and give it a git add get commit and just add initial commit like this so
and just add initial commit like this so everything is committed great and then
everything is committed great and then paste this and push to master like this
paste this and push to master like this and once I refresh you can see that my
and once I refresh you can see that my project is right here along with all the
project is right here along with all the code great
code great now we can go ahead in our reversal and
now we can go ahead in our reversal and you can go ahead I'm just going to
you can go ahead I'm just going to refresh go ahead and click add new
refresh go ahead and click add new project right here and go ahead and
project right here and go ahead and select this AI SAS tutorial which we
select this AI SAS tutorial which we just created right here perfect what we
just created right here perfect what we have to do now is we have to add all of
have to do now is we have to add all of our environment variables here and we're
our environment variables here and we're going to have to change them once we
going to have to change them once we deploy so let's go ahead and let's go
deploy so let's go ahead and let's go inside of our DOT environment file and
inside of our DOT environment file and you can just go ahead and select
you can just go ahead and select absolutely everything and just paste it
absolutely everything and just paste it inside like this and then just go ahead
inside like this and then just go ahead and click deploy and of course you can
and click deploy and of course you can see that next public app URL is
see that next public app URL is localhost so don't worry about that
localhost so don't worry about that we're gonna have to change that but
we're gonna have to change that but first we need to see if our deployment
first we need to see if our deployment is going to pass so I'm going to pause
is going to pass so I'm going to pause this and see if there are any errors
this and see if there are any errors that I get
that I get and there we go my application is
and there we go my application is successfully deployed but now we have to
successfully deployed but now we have to change a couple of things so let's see
change a couple of things so let's see what that is I'm gonna click continue to
what that is I'm gonna click continue to dashboard right here and I'm gonna go
dashboard right here and I'm gonna go ahead and get my URL so you need to have
ahead and get my URL so you need to have your url so right here for me it's AI
your url so right here for me it's AI Dash SAS the dash
Dash SAS the dash tutorial.versal.app so what I have to do
tutorial.versal.app so what I have to do first is I have to go inside uh uh let's
first is I have to go inside uh uh let's first go into stripe
first go into stripe so stripe.com right here and we have to
so stripe.com right here and we have to change uh this web hook right
change uh this web hook right so let's go ahead let's go inside of web
so let's go ahead let's go inside of web hooks
hooks if there are no results just click on
if there are no results just click on developers again and go inside web hooks
developers again and go inside web hooks here and we have a local listener here
here and we have a local listener here right here but that's local so go ahead
right here but that's local so go ahead and click add endpoints paste your new
and click add endpoints paste your new URL slash API slash web hook like this
URL slash API slash web hook like this so webhook only one like this
so webhook only one like this and now you have to select the events
and now you have to select the events that we are listening to so what are
that we are listening to so what are those events well let's take a look in
those events well let's take a look in the web hook route right here so first
the web hook route right here so first event we need is checkout.session
event we need is checkout.session completed so let's go ahead and find
completed so let's go ahead and find that so we have the checkout option here
that so we have the checkout option here and let's select the checkout.session
and let's select the checkout.session dot completed like that and the second
dot completed like that and the second one we are looking for
one we are looking for is invoice dot payment succeeded so
is invoice dot payment succeeded so let's go ahead and find that as well so
let's go ahead and find that as well so all the way down we have an invoice and
all the way down we have an invoice and let's find where it is
let's find where it is invoice dot payment succeeded and click
invoice dot payment succeeded and click add events and add endpoint like this
add events and add endpoint like this and there we go now you have your
and there we go now you have your sign-in secret right here so go ahead
sign-in secret right here so go ahead and click reveal here and copy this
and click reveal here and copy this secret and now go back inside of your
secret and now go back inside of your project settings here so I clicked on
project settings here so I clicked on settings in this project go ahead and
settings in this project go ahead and click on environment variables and let's
click on environment variables and let's go ahead and find that webhook secret so
go ahead and find that webhook secret so it's last one for me stripe webhook
it's last one for me stripe webhook secret let's go ahead and click edit
secret let's go ahead and click edit right here and just replace it with the
right here and just replace it with the new one and click save make sure you
new one and click save make sure you copy the sign in secret and not whatever
copy the sign in secret and not whatever this is so it needs to be designing
this is so it needs to be designing secret great and what we have to change
secret great and what we have to change next is the next public app URL and that
next is the next public app URL and that is going to be uh this very URL that we
is going to be uh this very URL that we are using so let me see what this is so
are using so let me see what this is so https AI says tutorialversal dot app
https AI says tutorialversal dot app like this without the trailing slash
like this without the trailing slash like this so edit that
like this so edit that and paste it here just make sure there
and paste it here just make sure there are no spaces like that and save the
are no spaces like that and save the file great and after you change that go
file great and after you change that go in your deployments
in your deployments and click redeploy again make sure you
and click redeploy again make sure you don't accidentally check this so just
don't accidentally check this so just click replay like this so I'm gonna
click replay like this so I'm gonna pause the video again and I'm going to
pause the video again and I'm going to show you what it looks like what's once
show you what it looks like what's once it's finished
it's finished great so it's finished and one thing I'm
great so it's finished and one thing I'm gonna do uh before I visit the website
gonna do uh before I visit the website is I'm just going to reset my entire
is I'm just going to reset my entire database and I'm going to push it again
database and I'm going to push it again so inside my terminal I'm going to write
so inside my terminal I'm going to write npx Charisma migrate
npx Charisma migrate reset like this this is going to remove
reset like this this is going to remove the entire database so be careful uh and
the entire database so be careful uh and after this is done npx Prisma DB push
after this is done npx Prisma DB push again
again and after a couple of seconds I'm gonna
and after a couple of seconds I'm gonna go ahead and visit my website
go ahead and visit my website so we're gonna visit this right now and
so we're gonna visit this right now and there we go it's deployed right here and
there we go it's deployed right here and you can go ahead and click get started
you can go ahead and click get started for example I'm going to use Google
for example I'm going to use Google right here I'm going to log in with my
right here I'm going to log in with my account
and you can see that I have my three generations right here so let's go ahead
generations right here so let's go ahead and test it out now uh for example what
and test it out now uh for example what is the radius of the sun right here
is the radius of the sun right here there we go let's ask it what is the
there we go let's ask it what is the radius of the Earth right here
radius of the Earth right here let's try of Mars
let's try of Mars so I'm just using this up to fill up the
so I'm just using this up to fill up the questions uh what is the earth of the I
questions uh what is the earth of the I don't know penis like this
don't know penis like this it really knows everything huh and
it really knows everything huh and Neptune
great now we use five out of five so I'm gonna add another one now we get a
gonna add another one now we get a prompt so let's see if this is going to
prompt so let's see if this is going to work
work okay I'm gonna go ahead and add a fake
okay I'm gonna go ahead and add a fake credit card here
I'm gonna click subscribe right here and let's see if that is going to work or if
let's see if that is going to work or if we're gonna get uh any errors here
uh okay so I'm logged out I think that's something with the configuration but let
something with the configuration but let me log in again to see if yeah okay so
me log in again to see if yeah okay so we are on a Pro Plan great uh I'm not
we are on a Pro Plan great uh I'm not sure why we logged out I think it might
sure why we logged out I think it might be
be I think it might be because of the
I think it might be because of the redirection stuff or maybe some
redirection stuff or maybe some hydration error that triggered the log
hydration error that triggered the log out I'm not entirely sure that's
out I'm not entirely sure that's something I'll have to uh look into and
something I'll have to uh look into and I'm not sure it happens every time
I'm not sure it happens every time because for me it worked normally in
because for me it worked normally in production great so this works now and
production great so this works now and just one thing you want to bring your
just one thing you want to bring your attention to so there are stuff inside
attention to so there are stuff inside that are going to take too long to
that are going to take too long to generate for virtual hobby right for
generate for virtual hobby right for example if I do Swiss Alps like this I
example if I do Swiss Alps like this I think this is still going to work
think this is still going to work because it's not a very uh complex model
because it's not a very uh complex model so open AI Works faster so this works
so open AI Works faster so this works but for example if I try music
but for example if I try music generation like piano solo uh it might
generation like piano solo uh it might take so long that it actually throws an
take so long that it actually throws an error so that is because you are we just
error so that is because you are we just deployed Universal hobby plan right so
deployed Universal hobby plan right so we're using versal uh for free right now
we're using versal uh for free right now so what you can do you can see it says
so what you can do you can see it says hobby right here
hobby right here uh so what you can actually do uh is
uh so what you can actually do uh is either upgrade to a newer plan so you
either upgrade to a newer plan so you see for me it works but it there's a
see for me it works but it there's a chance that you get an error you can
chance that you get an error you can either upgrade to a larger plan and then
either upgrade to a larger plan and then you can increase how much uh what is the
you can increase how much uh what is the timeout for your API routes or you can
timeout for your API routes or you can go ahead and search for reversal AI SDK
go ahead and search for reversal AI SDK which is something I'm going to work
which is something I'm going to work with in my next tutorial so versatile AI
with in my next tutorial so versatile AI SDK works on the edge Network which is
SDK works on the edge Network which is also something you can google and find
also something you can google and find out more about it's basically has a
out more about it's basically has a larger timeout and is generally faster
larger timeout and is generally faster and it allow it supports streaming of
and it allow it supports streaming of content so that's what we are going to
content so that's what we are going to play around with uh in my next tutorial
play around with uh in my next tutorial so thank you so much for watching this
so thank you so much for watching this tutorial you did an amazing amazing job
tutorial you did an amazing amazing job uh remember to leave a like share and
uh remember to leave a like share and subscribe if you like this content and
subscribe if you like this content and see you in the next video
Click on any text or timestamp to jump to that moment in the video
Share:
Most transcripts ready in under 5 seconds
One-Click Copy125+ LanguagesSearch ContentJump to Timestamps
Paste YouTube URL
Enter any YouTube video link to get the full transcript
Transcript Extraction Form
Most transcripts ready in under 5 seconds
Get Our Chrome Extension
Get transcripts instantly without leaving YouTube. Install our Chrome extension for one-click access to any video's transcript directly on the watch page.