Build a SaaS AI Agent w/ Tools | Next.js 15, React, Better Auth, TestSprite, Stripe | Full Course
By TechWithEmma
Summary
## Key takeaways - **Build AI Agent w/ Next.js & AI SDK**: The video demonstrates building a full-stack AI agent called Wave AI, leveraging Next.js 15, React 19, and the Vercel AI SDK for advanced AI capabilities. [00:00] - **TestSprite for AI Testing**: TestSprite is highlighted as an AI testing agent that simplifies testing applications by allowing prompt drops directly into the code editor for instant execution. [00:13], [00:15] - **Key Features of Wave AI Agent**: Wave AI's key features include authentication with BetterAuth, web search and content extraction tools, tool chaining, Stripe billing integration, and deployment to Vercel. [01:03], [02:09] - **Tech Stack and UI Components**: The project utilizes Next.js 15, React 19, HonoJS, Tailwind v4, and Shadcn/ui for building a responsive UI, with Neon Database and Prisma ORM for data management. [00:09], [00:36] - **Authentication with Better Auth**: The video covers setting up authentication using Better Auth, integrating it with Prisma and Next.js for secure user management. [00:43], [43:34] - **AI SDK Integration for Chat**: The AI SDK is explained for integrating chat functionalities, allowing the agent to search the web, extract content from URLs, and chain tools for complex tasks. [04:49], [05:13]
Topics Covered
- AI Agent Extracts Content and Creates Notes from URLs
- AI Agent Searches Web for iPhone Features
- Installing Shanti UI with Next.js
- Successful AI Web Search and Content Extraction
- Successful AI Agent LLM Interaction
Full Transcript
Hey, meet WebAI, a second brain AI agent
full stock app. You build, test, and
deploy completely for free. This AI
agent can create, find extra content
from URLs, and even search the web.
Built with NJS, Honjs, Better, Vio,
Stripe, and Test Sprite. Speaking of
test sprite, test sprite is an AI
testing agent that make it super easy to
test your apps. All you have to do is to
drop a prompt right in the code editor
and thanks to it MPC server, it run the
test instantly. It work for both back
end and front end with detailed test
reports. And you can also run the test
in the test right app, schedule them and
monitor progress to keep the project on
track. And the best part is you can try
it out with a one month free trial using
my link in the description. Big thanks
to test for sponsoring this video. So
don't forget to subscribe and turn on
notification. Now let's dive straight
into the demo. On this beautiful landing
page, first thing we're going to do is
to sign in. So I'm going to click on the
sign in then log into my account. And
once I log into the account, I'll be
brought to this beautiful um dashboard.
So in this dashboard we have the option
to select multip different model. The
agent also we have the option to select
different tools. We have the create
note, search notes and web search. So
I'm going to create paste a prompt. Now
I'm going to tell the agent to extract
content from this URL and create a note
titled news intro introducing GB5 with a
short clear and concise summary of the
content. I'm going to click on enter and
this should go ahead and extract the
content from the URL. So it's going to
extract it using the extract tool. Then
it's going to go ahead and create the
note. So, and we're using CLI 4 to do
this process. So, we're going to wait
for this to complete the process. And
now we should be able to see it has
extracted the content and created the
notes. If I click here, we should be
able to see um the notes. If I click
here, we should be able to see the notes
as open here. So, we also have the
option to we can also ask the agent to
search for search the web for
information. So, I'm going to search the
web for new iPhone 17 features list at
least at least five of them. So I'm
going to click on enter and then the
agent is going to go ahead and search
the web. So it's going to search the web
and got the resources result from the
web and then it's going to outline or
list the features that found on the
internet. So and you can see cl is doing
a good work here. In this video we're
going to learn how to do all of this
completely for free. So this has
complete. We can see uh the details. You
can click here to save the notes or you
can copy um the notes here. So we also
have the option to search for notes. So
I'm going to go ahead and search for
notes in my note list here. So I'll
paste the prompt. I say search my notes
for all my meetings. So I'm going to
click on enter and this should go ahead
and search the entire notes. And if you
see that it has search all the notes and
it's listing out all of the notes for
me. This is so amazing and we can see it
has even given us summary of what was
inside the note and we can see content
created and the focus um in the notes.
So can also switch model from cl to gro
I'm going to select a tool here create
note I'm going to ask I need a not about
and if you go ahead and create the note
for us so it's going to first of
acknowledge that it's going to create a
note before you go ahead and create the
note so now you can see that it has g it
has acknowledged it's going to create
the note as requested then it should go
ahead and create the note for us so you
see that it has created the note for us
and let's wait for it to complete
and then is done. So I'm going to switch
back to CL and I'm going to ask the
agent to write code for me. So I'm going
to say write JavaScript link example
code for me and this is going to go
ahead and write the code and we can see
that the code will be formatted uh
because we're using a mac to format the
um code. So this is going to complete
and let's wait for this to complete
and it's just going to give us a
description of um what it did there. So
it's giving us a summary and we can look
at the um code it has written. So you
can do um any kind of thing with it. So
if you come over here we can look at the
history. So if I click on chart history
we can see all of the history of all
chart we've created. So I'm going to
just um close this. Then I'm going to
click new chart. You can click here and
this will open a new chart for us. I can
ask what model are you
and click on enter and this should go
ahead and respond to us. Say um claude
assistance search create organize note
and find existing note. So we can click
here to save. We can click here to copy.
Then we can still ask more question. We
can click here on this p plus icon to
create a new note. And then this is
going to create a new note. You can see
contents and click on save and this
should save the note. You can click on
this um and this will open a new notes
and click on save and this should update
in real time. So this is working fine.
So if we go back to our billing you
should be able to see we have plans
here. They have the free plan plus and
premium and we have um four left um to
use and after we've exhausted the four
remaining generation we going to have to
upgrade before um um starting with the
AI agent. So I'm going to go ahead and
exhaust all of the credit. So I'm going
to go back to a new chart. I'm going to
ask the news about I just want to
exhaust the remaining credit. So I'm
just going to just give this a check
and if you go ahead and can go ahead and
search the web and it's going to get
latest news and we should be able to see
it's giving us a summary of what it has
discovered from the internet. We can ask
more questions here. So I'm going to go
ahead and exhaust the credit. So we can
see um the where we try to send a new
message. So now we can see that we have
run out of free response. So I asked the
AI agent how to convince viewers to
subscribe and it went ahead and searched
the web to get some results. Then I
asked it to um write a big emoji
subscribe. So subscribe and turn on
notification. Don't miss out and hit the
subscribe button. So now we've exhaust
all of the um AI response. I'll go over
to B or you can click here and this will
take you to the billing uh section. Then
if you come over here you should see
where we have a free trial. We've
exhaust everything. So, I'm going to
click on upgrade here and this should
give us a check out and we should move
over to stripe. Then I'm going to fill
in my car details here. So, I'm going to
select card. I'm going to fill in the
car details and then I'm going to click
on uh subscribe here and this should
subscribe and if go it will redirect us
to the app. So, it has complete and this
should redirect us to the app and now we
should see that we are in the plus plan.
If I go over to the AI chart now, I can
send a new message and then this should
go through and we should not we not
going to be able to see the message
showing indicating that our AI response
has uh we've resisted our AI response.
Now we can be able to chat to the AI.
Then if you go back to building back, we
can switch plan from plus to premium. So
I'm going to click on um switch plan and
this will go right. This should take us
to Stripe. And now you see that it's
asking us to confirm. So I'm going to
click on confirm and this should go
ahead and extract the remaining balance
from our credit card and add it to our
subscription. So it's going to be direct
us back and if I go over to billing you
should be able to see we are in the
premium bank. So you can click here you
can see that here we have unlimited
generation. So lastly we can go over to
the settings page and we can switch this
from light mode to dark mode. And you go
over here you can be able to see this in
dark mode. So I'm going to also log out.
We can log out from the so I have my VS
code open. So the first thing we're
going to do is to install next. So just
come over to ui shanty.com shanty just
go back to shanti website then click on
get started click on next and then let's
copy this. So make sure you select npm.
So open my terminal
and I'm going to paste this here and I'm
going to click on enter. So this will
install um next and also shanti for us.
So I'm just click on yes.
uh then it's going to show uh after
whether we want to install for nextj or
nextjs mono. So just click on the first
one next year. I just put dot click on
enter and this should start installing.
So we're going to wait for this to
install. So this has installed this has
added to our project. So just um click
on enter. So this will add shant to
right now and then css. So if I open my
sidebar, we should be able to see um the
files there.
So it's okay, it's done. So I'm going to
delete one
and then I'm going to go ahead and you
can mpm rundev
and this is going to run the server. So
now we are done with this. Now let's go
ahead and install and add some of the
components that is needed for this
project. So go go go over to component
and then we can add some of these. So
I'm going to test this out. Then we can
close it and add. So I'm going to open
my browser, paste it local 30,000 and
you should make sure the um server is
running. We're able to see next.
So it has compile. So it's going to be
able to see. So this is working. So,
let's go back to uh Shanty UI and let's
add some of the components. So, I'm just
going to click cancel the server
and then let's uh go over to uh let's
say u shanty mpx
shanty cn add.
I think it's add
I think this is going to add everything.
Let me cancel this and
and mpx shanty add
to install shant again.
So now we're going to select um so let's
select um click on the space bar then
avatar badge um button card
um collable
dialog drop form input pay
uh what again select
separator
light bar skeleton
and I think this area
I think that's all.
So let's click on enter. So this will
add all of this component into our
component folder.
So when this is done we are going to
install
some packages.
So this has installed. So now let's um
let's check out we can see component
here and the component has added inside
the component the UI folder. So let's uh
install some packages here. So I'm going
to just paste that. I'll say npm install
UID date function uh remix icon react
zan and t query. So just click on enter
and this is going to install all of
these going to install the packages.
We're going to later install more
packages as we're going. So, let me wait
for this to install. So, this has
installed completely. Now, um let's go
into the app. Let's go into the layout.
We're going to uh change the
Let me close this. We're going to uh let
me remove
um this font. I'm going to leave this
one.
I'm going to leave one here. We see um
this uh let's take this place it here
and I'm going to just call this class
name
and we can add suppress um
so suppression warning then we are going
to add our provider here. So I'm going
to say I'm going to create a I'm going
to call this providers
and I'm going to paste children here. So
we're going to create this inside a
context and this is going to hold t
query the no and also the uh shanty
toaster. So I'm going to just go over
here. Let's create a folder. Let's call
this context.
And I'm going to say provider
cxce.
Save that. And then let's u import it
inside layout.
So now we're going to add the um props
here. But first let's quickly create a
file here and let's call this query
query provider
tx. And then we're going to also as we
export default
um function
it's going to be our query
sorry query provider.
This is going to hold the uh d create
query. We're going to use this to wrap
the entire app. I'm going say children
and it's going to be our props.
So, let me um come over here and let's
create the props here as a interface
props
and this is of type react
node.
Let's import that. And now can just call
this. So we're going to just say
constant query
client
is equals to
new query
new query client.
So let's import this t query. It's not
coming up here.
So let me import
as T stand.
Let me fix this here.
So we're going to query
client. Yeah.
And then let's return.
And let's say query
client provider.
And then we're going to pass in the
children here.
So here we're going to add client
and we're going to pass in a query
client here. So we are done with it. So
we can take this and add it inside our
providers. I'm going to rename this to
providers.
Yeah.
So inside here we're going we're going
to also we're going to also add pass the
um
children here.
interface
then children
we add um
we add node.
So we're going to add the props here.
like this. Then inside here we're going
to return
query
query provider
and then let me let's pass in yeah
children here
then below here let's add in to
sona
we can see from sona here let's
Let's add it here.
I'll say position
top center.
Let's give it duration
3,000
and then reach color like this. So that
we're going to let's wrap this inside.
Okay, the error has stopped. So we're
going to add team here. So let's go over
let's first of all come over let me
close this
and then I think we should go over to
dark mode not team let's click on dark
mode click on next years okay yeah we
need to install next team so I'm just
going to paste this and install this
then we need to create a file
team provider so I'm just going to copy
the name of the file Okay.
And then this was installed. So I'll
close this open. Then inside the context
I'm going to create a file. I'm going to
paste that. Then I'm going to copy this
and paste it here.
Uh let's also copy use client add it
into the provider here.
Then come inside the team provider.
And then we need to wrap this. So I'm
going to copy this. I'm going to go over
to providers. I'm going to wrap it here.
So I'm just going to copy this and paste
this and move this toaster inside. And
then let me import this here
from team team provider.
So let me go ahead and save this.
So that is it. So we can change this to
W with AI.
AI wave AI agent.
So now we need to go over and check
change the theme. So let's go over to
global CSS
and then here I'm going to we're going
to change the style and also the D. So
head over to this um just search for
shanty team generator and then come over
to this website or shantystudio.com.
Click on it
and then I'm going to click on this
color here.
Just click on the icon up here. And then
when you scroll there um type in this
color here 10 B 981.
Then once you've typed this color,
you're going to just click on copy and
then we're going to copy all of the sty.
So I'm going to copy this. Then I'm
going to come over here. We're going to
just
comment this out.
I'm going to just paste it here.
Then I think this also so we need to
also remove this. also remove this one
too
because we have it here already. Team
inline they added it to you can see it
here.
So uh that is it.
Um
so for the dark mode I'm going to um
also modify the color. So I'm going to
just replace this with this. So I'm
going to change the color to 0.20. 200
like this. So we are done. So let's go
ahead and um set up the app. So I'm just
going to uh come over to the page. Let's
just remove everything here. Just going
to say div
like this. Remove the images the image.
Then inside here we're going to create a
group route. So I'm just going to say
route.
Then inside here we're going to also
have API.
We're going to also have actions.
So inside the we're going to create
another group out. We're going to call
this dashboard.
And then we're going to also have um
we're going to have web.
We're going to also have um
So this page we're going to move it into
um web.
Then inside the dashboard we're going to
have different um going to have the
homepage.
Uh then we're going to have the um
the billing page
settings
and then the chat.
So we're going to also have the layout
heres.
Yeah. So we've completed the um page. So
let's go over to I mean the dashboard.
Let's go over to um layout um web loop.
Let's create layout
txx.
And then let's um let's write this. So
I'm just going to say export
export default
sync function.
I'll call this web layout.
And then let's just
so yeah, we're going to pass in
children.
So I'm just going to go ahead here and
just copy that here.
Let me just add it here. See
children
we do react node
like this and then let's just have a
div. Let's um return
and let's have a div
and then the children
like this. So let's copy this. come over
to dashboard and then inside let's say
the layout for dashboard let's paste it
here I'm going to just call this u
dashboard layout
and then the last one we're going to
also do the same for so I'll say layout
txx
and I'll paste it I'm going to call this
layout
So um that is it. So let me close all of
this.
So I think we are done with the route.
So let's go ahead and then start
building the layout. So inside the
dashboard.
So let me run the server first.
So I'm just going to call this um home
web page or landing page.
So we can see that when it load then
inside layout we can have uh we're going
to have the sidebar and also the main
content. So let me just load the server
npm rundev and this should load the
server for us.
So this is running.
So the first thing we're going to do,
we're going to use the sidebar from our
component UI. If you come over here, you
can see u the sidebar component. So I'm
going to import that here inside layout.
So, I'm just going to
open this here. And then we say sidebar
provider.
And then we're going to have um the side
the sidebar
insert.
So, I'm going to also wrap this in
suspense.
because I'm going to be using a package
called Noxia.
So this is required because we're going
to be using use search param and um when
deploying to vil or building it you need
to wrap any of the files or any of the
uh files you you used search params. So
I'm going to just use and not adapter
use um
us. So I'm going to just wrap it. So
we're going to see where we're going to
use that later on. So I'm just going to
save this and then I'm going to just
import this.
So let me import this from Nox here. So
I'm just going to move this up. Let's
import
Let's import from
So I've imported it here and now we can
add a fallback here suspens
here and I'm going to call the icon
from um we add um remix icon one we add.
So I'm going to say loader
loader
and this should give us field. So let me
see why I didn't import. So let me
check.
So let me let me try and import this
here
from um
remix.
we let's import this here.
So let's give this a class name
with 16
right 16
animate
as pin
and then give a test color of primary
like this. So let's also um add some
class here. Class name is equals to a
flex item center
justify center
and hide screen.
So save that. Now we done with it. So
let's come over to the uh sidebar. Then
here we're going to have the u the app
uh sidebar here.
Let me just add it as a comments
sidebar.
We're going to create a component for
that. Then this is going to hold the
main content. So I'm just going to open
this. I'm going to say class
is equals to relative
overflow.
I'm going to make it overflow x hidden.
Then I'm going to say PT sorry like
this. And then here we're going to just
pass in the children here
like this. So we can go ahead and create
the app sidebar. So I'm just going to
collapse this here. Then let's scroll
down to the component.
Then let's first of all create our logo.
So I'm just going to move it up here.
collapse this here.
So inside uh let's create logo first.
Inside logo I'm going to have index txx
here. Then below here I'm going to
create a folder. I'm going to call the
sidebar
and this is going to hold the uh cyber.
So I'm just going to create index here.
We're going to implement the cyber
later. So I'm going to say EC
I'll call it sidebar
or app sidebar.
So let me just copy this.
Come over to the layout. Sorry to
dashboard layout.
And then let's just add it here.
And let me import this.
So uh let's quickly logo then we can go
ahead and work on the authentication
side. So I'm going to come inside the
index.ts and let's fce
I say logo.
So let's uh change this to link.
Let's import link from uh next link. So
I'm just going to just copy this,
paste it here, and let's import
link from next link.
And then we're going to set.
So let's pass in a props
because we're going to be using the logo
uh in the authentication page and also
in the dashboard in the sidebar. So I'm
just going to set this to undefined
to be optional. Then I'm going to uh
let's
get the URL from the props
and I'm going to say URL and the default
is going to be slash.
So, I'm just going to replace it with
the URL here.
And there, let's add in some class to
the link.
Pass name.
We're going to set it to flex.
I then center.
And then gap two.
Gap.
So I'm just going to give it with
and then inside it we're going to have a
div.
We're going to have class name.
We're going to say flex
um aspect
square
size eight.
Let's say item center justify center
rounded MD.
Then we're going to have overflow
overflow hidden.
Then BG we're going to have the
background. Let's say this to
um BG
primary
text
primary
dash forground.
Then let's uh have remove this.
Then let's have image.
So I'm going to say src
logo.png.
So you can check out the logo. I've
added it already in the public folder
here.
You can see that in the source code. So
if I click on this, you can see the logo
here. So let me just remove this.
So I'm just going to just remove this
here.
I'm going to set a logo PNG. Then I'm
going to say width
36
then height
uh 36 here
like this. So we can give this all can
say wave AI
and then outside the div we're going to
create separate div. We're going to have
class name. And this will just hold the
content. So I'm going to say grid
um
let's say flex sorry
one text left
I'm going to give it a test uh test base
and then say leading
site
let's expand here
and let's say class name.
Let's say uh this is going to be font
medium
and let's say wave
AI
by this. So we're done with this now. So
let's go ahead and set up our
authentication because we are done with
all of this.
So let's go ahead and work on the
authentication page. So our server is
running.
So before we go ahead and work on the
authentication, let's first of all set
up our database and Prisma. So for
database, we're going to be using Neon.
So just head over to neon.te or
console.ne.te. tech. So, I've already uh
and then I'm going to sign up. So, just
go over to neon.te
and then let's let me log in. So, I'm
going to log into my account. So, I've
logged in. So, I'm just going to move
over to this screen and then I'm going
to go over to um I'm already lo here.
So, I'm going to create a new project
here. So, I'm going to just call this
wave
wave AI
and then I'm going to click on create
and this should create the project for
us. So, now we can come over here and
let's click on connect to get the string
connection string. So, I'm just going to
copy this here. So let me just uh let's
pick um Prisma here. Sorry, not Prisma
um connection string.
And then let me just enable the password
here.
And then let me just copy.
Let me just copy everything from here.
And now if you've copied this, let's go
back to the code and then paste it
inside the EMV.
So, I'm just going to close this here.
I'm going to create the EMV
and MV.
So, yeah, we're going to call this
direct.
Let's just call it database
URL.
and let's paste it here.
So, we're going to go over back and then
let's set up Prisma. So, I'm just going
to go over to Prisma. So, go over to
Prisma.io. Click on the documentation
and then we're going to click on next.js
and then here we can scroll down and you
can see how to install U. Scroll down.
We've already installed NJ already. So
we can see how to install um Prisma and
also you need to install Prisma
extension storage and also Prisma
client. So we can go back to the code
and let's install this here.
So here I'm going first of all let's
install Prisma. So I'm just going to
cancel this
as a dev dependency. So make sure we
have Prisma 6.15.0.
So click on enter. This should install
Prisma. Then we're going to go ahead and
install the uh the Prisma client and
Prisma extension. So this has installed.
Let me clear this. And then let's
install uh the Prisma client 6.14.0
and Prisma extension 2.0.2.
And this is going to install it. So
let's wait for this to install too. So
we've installed it now. So, let's go
over back to um um Prisma and
documentation and then let's continue.
So, I'm just going to scroll down here
and then we can go ahead and
set up Prisma, but we're going to do
that later. So, we can go ahead and
migrate after writing the um the schema
I think. So,
or let's check it's okay. Yeah, we need
to first of all um MPS Prisma in it DB
output. So it's going to generate the
schema for us. Then once we do that,
we're going to scroll down here.
I think that is all.
So if I scroll down to where we have and
deploy with VI
um you can see that Prisma says uh let's
go down here.
Okay. So let's go ahead and set up that.
So I'm going to go over back to my code
here and then let's let's uh initialize
Prisma. So I'll clear my terminal and
I'm going to paste it. And this is going
to generate uh the Prisma folder for us.
So if you have any issue, so what you
have to do is to um just write uh if
it's asking you to authenticate just
cancel it and just put NPS Prisma in it.
And this is going to just set up Prisma.
We can see Prisma schema is already
here. So I'm just going to Okay,
let me see.
So I'm just going to remove this. Okay,
set li generate Prisma. So I'm just
going to remove the lip. Instead, I'm
going to just create a generated folder
right inside here.
Yeah, like this. So let's go ahead and
then copy. Let's create a Prisma. Yeah,
we say Prisma.x
and let's go over to the documentation
and copy how to use Prisma with NJS. So,
if you come over to documentation, we
should be able to see um we have to
create Prisma.x and we can copy this.
So, if you're using Prisma Pro, this is
recommended. Let me use other database.
So, I'm going to copy this. And if
you're using um Prisma extension
accelerate here, I think we're going to
also remove that what we installed
because we're going to just use it
without it because if you're using it
with u um Prisma accelerate,
you have to set up um Prisma
like this. You have to um access Prisma.
I have to log into Prisma. So I don't
want to do that. So, I'm just going to
go back and then let's just click on
just select only the uh let me scroll
back up.
Just select only the other database and
let's copy this. And let's go back to
the code.
And I'm going to just paste it here.
So, I've pasted it here. So make sure
you pick the one for other database. So
I'm just going to remove all of this and
just say to generate Prisma. We going to
generate that later on. So let's just
leave it like this. Just save this.
Let's save. So we don't have any uh
model yet. So that's why it has not
generated the added placement to his
generated folder. So I'm just going to
leave it like this. Then um think I
think we're done. So let's go ahead and
um set up um authentication with Prisma.
So and inside the EMV we already have
the database URL
and then inside Prisma schema we have
the URL database URL. So let's go ahead
and do that. To add authentication to
our project we're going to be using
better odd. So let's go over to better
odds process. So I'm just going to open
a new tab and I'm going to search for
better o.
So just click on better o here
and then click on documentation here.
So with better o you can you can do
variety of um different type of
authentication. You can have your
socials here. You can social email and
password. You can have you have
different socials here. We also have um
database. You can see um Prisma
adapters. You can see database here. We
also have plugins and um think we have
integration. Yeah, we have for Huno
Express and also for NexJS. You can
click here and you can see how to um use
um better odds. Um if you want to use um
NestJS as a server and also as a client.
So I'm just going to go over to let's go
over to get started and then let's click
on intro installation here.
So we're going to install better. So and
then we're going to generate better o
secret. And we're going to also add
better o URL. This is going to be local
3000.
Then we're going to create a new folder
and we're going to create um tx and umts
and client too. So let's go ahead and do
that. So I'm going to install. So just
go over to my code and then let's um
install it.
Let me open the terminal. Let me scroll
down. Let me clear the terminal and let
me paste it here. So I'm using beta o
1.3
uh 1.3.7. So just click on enter and
this should install better into our
project.
So by default better is using cookie.
You can also modify to use um beer token
or different um ways you want to um want
to authenticate your users. So I'm going
to wait for this to install. So this has
installed. Let's go back to the
documentation
and let's see the next thing we're going
to do after installing. So we're going
to generate all secret. So I'm going to
click on this generate secret and this
is going to generate a secret for us. So
copy this and I'm also going to copy um
the embed URL.
So we're going to create an tx uh file
so we can paste this. So let's just go
ahead and do add those ones there to the
env. So I'm just going to close this.
Then
open the EMV
and then I'm just going to paste it at
the top here.
So I've pasted it. Now let's go let's go
back to the uh to the documentation and
then the next thing we're going to do is
to create the so let's copy uh let's
copy better and then you can see how to
configure the database first. So let's
go down here and you can see this you
can see Prisma. So this is how to
configure it with Prisma. So we can just
copy this here. So let's just copy this
and then we can then generate
the the tables or the models. So if you
come down here we should be able to see
the schema.
So I think show us here how um
okay
so let's just copy this first and let's
create a file called uh sorry this one
first. So we have two files here.
Okay, I think it's tx. So, just copy
this. Let's go back to the code
and let's come into the folder and let's
create.x here.
And I'm going to just paste it here. So,
let me just clear some stuff here.
And then, yeah, we're going to change
this to Postgress because we're using
Postgress, not MySQL.
I know this file is not available. We're
going to we're going to do that here.
So, let's just save this here. And then
let's um let's um let's um use better
all to generate the model for us. First,
it's going to generate the user model
and then we're going to push that to um
Prisma. So, let's wait for that. So,
let's go back to the documentation.
And then let's go ahead and then copy
the
let's go a say create tables. We need to
copy the CLI and this is going to
generate the schema for us. If you
scroll down here we should to see uh the
database schema. If I open this
you should be able to see uh scroll
down.
Yeah we can to see the core schema. Here
we have the user sections account and
also verification.
Then you can add your own custom tables
if you want.
So I'm just going to go back and let's
just copy that. Then once we copy that,
we're going to enable email and
password. We're not using social. So if
you're trying to use socials, you will
use social provider and set up and pass
in the uh particular socials you want to
use here. So let's just um
let's go ahead and then generate the
schema first. So let's go back to the
code
and then let me just
paste this here and click on NPS Prisma
and better all CLI generate and this is
going to generate it inside. So I'm just
going to click yes. So this is going to
install then it's going to generate the
Prisma model for us. So let's wait for
this. So I think this thing is failing
to generate the uh schema for us. So,
what I'm going to do is I'm going to go
back to the schema and then we're going
to just uh let's just add in a simple
model here. So, I'm just going to say uh
I don't want to use user. Let me just
use post here and let me just remove
this here. I just say text
and let me just let me just use notes.
Yeah. So, I'm just going to remove it
later. We're going to say UU ID
I think. U
ID
this. Okay. Yeah. U ID
string.
So let's try and generate this first. So
I just go into my packet JSON and then
I'm going to just um
paste in the
this here. So I'm just going to paste in
DB migrate and then DB uh M DB studio.
So this we saw inside the Prisma
documentation MPS Prisma dev name and in
it. So let's just run this and let's see
if this will generate the folder for us.
So I say uh mpm run
uh db migrate.
So let me save this
and let's enter. Let's see if this is
going to generate the uh generate folder
for us. Yeah.
So the error is going to stop.
So I'm waiting for this to to complete.
Um
so let me wait for it. So this has
complete. You can see that it has
generated the folder for us here. And
you can see Prisma inside here. So don't
we have um let's just save. Let me save
this. So now the error has stopped. So
we can go ahead and um and then use the
uh better o CLA to generate the schema.
So let's just go ahead and do that. So
I'm just going to
then click on enter and this should um
work now because we already have the
Prisma inside the generated folder.
So let's wait for this. So we can see
uh that this is
let's just say yes
and then let's open we can see it has
generated the uh schema for us. So I'm
just going to I'm going to take this
down here.
I don't need a verification. I'm just
going to remove this.
uh session user account is necessary. So
before we push, let's complete the um
Prisma uh schema. All of the schema we
need um for the project. So let's modify
this uh note. We are going to change
this to title
and then I'm just going to say content
string.
Then we're going to have uh created at
and it's going to be date time
and we're going to set default
to now
like this. Then we have the updated
this will be this time
and um updated sorry updated art. Then
let's have the user ID which is going to
be of type string.
And then we can just copy um this
relation field and just um paste it
here.
And then below here we are going to just
say u let's change the name map and
we're going to say this to note.
So let's go ahead to the user and let's
add notes here.
So let's say not
and it should stop this error should
stop. So we are done with this. We can
also add uh if you want to add index you
can add index here
and we can just say user id
like this here.
Then we should have model
charts
and this will have the ID. So I just
copy this, paste it here. And then we're
going to also have title. So I'm just
going to copy this and paste it here.
And then we're going to have created art
and um
updated art. So just paste it here.
So yeah, we're going to just have the
same thing we have here. user ID. Paste
it here.
And I'm just going to copy both of
these. Just paste it here.
Chat ID.
This should this error should stop.
Okay.
um ID
at
default
view ID.
So let me add the chart first in the in
the user schema.
Okay, let's change this to chats.
The error has stopped. So now let's copy
this and let's have message here.
So you're going to just have messages
here.
So yeah, we're going to have ID. We're
going to um change this to
row a row and there we're going to just
set a row here. We're going to define
that on the top.
Yeah, let's define it here.
Let's say in
sorry in row
and then we can have uh we can have user
assistance and system. So yeah, we're
going to change this to instead of user
ID, we're going to have chat ID and then
we're going to change this to chat and
then chat
and then uh chat ID.
Then we can have messages here.
Messages.
So messages
message like this. So uh we are done. we
can be able to push this now to um neon
post. So we are done with this
we can also have uh
so I forgot we need to also add um part
here and this is going to be JSON
and then let me just also add index for
chat ID here. So I think that is all we
need for this. So let's go ahead and
then push this. So I'm just going to do
the same to the DB
migrate. And this is going to um this is
going to migrate the schema.
So let's wait for this to um load.
And this will update this and generate
schema here.
Let me just wait for this to load. So
this has successfully pushed the um the
schema to neon. So let's go ahead and
check that on. So, I'll go over to uh
uh Neon dashboard and let's go over to
tables
and then this should load. You should be
able to see all of the tables. Yeah, you
should to see user
session notes message chat accounts and
then Prisma verific migration.
So uh we are done with migrating. So
let's go let's go back to the code
and then inside the code now we can
close this close this and then let's go
go back to u um Prisma and let's also
create the Prisma um client. So I'll
just go over back to uh say Prisma
client sorry and better client. So I'm
just going to go back to better
and then let's go down and continue. So
we've generated a schema with migrate.
So now we need to add uh email and
password.
Yeah. Then once we scroll down here we
can come down here. We can see we need
to create all client.tx here.
So this is for server. Let's use the
client side here. client and we can have
the um just add it here. So you can do
this if if you can add the base URL if
you're using u different domain but
since we're using the same domain
there's no point adding this here then
once you've done that you can go ahead
and use the create o client
sorry not create client we can go ahead
and use the client and this is going to
give us the sign in sign out sign up and
then use section so let's go back let's
just copy this. Let's go and create
the-client.tx.
So, let's go back to the code
and then let me create this here.
All-client
cx
and I'm going to paste it here. So,
there's no point adding the base URL.
We're having the same port.
So, now everything is complete. We can
make use of this now to um authenticate
user or we can use this to also make
sure user does not get to dashboard if
they are not signed in. So we can go
over to the layout and let's add it here
to all of the layout we have here. So
I'll just come down here. So I forgot we
need to also add in the tx we need to
also add the uh email and password. So
let's just add it here.
Let's add email and password enable
true. So save that. Then we can just go
back to the uh documentation for better
o. Just click on basic usage. And then
you can see we've added this to the we
can see how to make use of it. Then uh
we can see that when you try to sign up
this will auto sign the user into the
dashboard. You can also modify that to
size to force if you don't want if you
want the user to sign up and then login.
Then I'm looking for the server side.
How to use in server side. Okay, this is
when you want to sign up using the
server side. Let's go to where we have
sessions here. So on the client side,
you can just get sessions from the
client. But look at the server side. We
can get like this. And let's just copy
this. We're going to use that in the
dashboard layout. So, I'm just going to
um copy this and let's go back to the
code
and then I'm going to just come over to
the dashboard
layout
and then here we're going to just add it
here. So, let me just move this import
to the top
and then let me just remove this. Let's
import um from li folder here.
So now we're going to check if the user
does not have any session. We're going
to red the user um to the login page. So
let's just check this. If it's not um if
the user does not have session because
we're in the dashboard layout, we're
going to redirect the user to the login.
So I'm just going to paste that in. So
let's import red with direct from um we
navigation here. So let's just create
the uh folder for the sign in folder
inside the folder. So I say sign in and
you should have page txx
collapses. Then we're going to have the
other one for sign up.
Sign up.
And we're going to have page here. TXX
here.
So inside the dash, we're going to copy
the same thing here.
Come over to the web first. Let's add it
into the web layout. So I'm just going
to just paste it here.
And let me just import all.
So let me just copy the import here.
Let me move this to the top. And also
copy the headers too. So I'll go back to
layout.
Let me bring this down. Paste it here.
And also paste the uh too. And let's
import the uh redirect.
So if there session, let's redirect the
user to home.
Let's just copy this again. Come over to
layout and let's add it here too.
So I just go over to my layout here and
let's copy all of this.
And then let's paste it here.
And now this is going to be the room. So
we have added um
we've protected our dashboard from
unauuthorized user. So now I think the
next thing we're going to do is to go
ahead and set up the UI for the page. So
I'm just going to open my terminal here
and let's just npm run
and it's going to start our server.
Let's go ahead and um let's open this.
Let's open local 3000 in our page, our
browser.
So, I'm just going to just replace this
local 3000.
Let's wait for this to load.
So, we're at the landing page. Let me
just create uh let's AFC
as a page
or we can just change it to sign in if
you want. I just leave it to page. Copy
this and just paste it inside the sign
up too.
And then let's just say inside the sign
up we're just going to say sign up here.
So save this and let's go over to /
sign up
and this should show sign up here.
So now we have sign up here. So let's go
ahead and implement the um sign up. So
I'll just go back to Shantui
and then if I go over to or let's just
go over to Shantui review that in a live
screen
and I'm just going to go over to Shanty
UI
Shanty UI.
Then let's go over to blocks.
Let's scroll down to uh
so we can find the login screen.
So uh this is it. We going to make use
of this uh component here. We're going
to modify it, right? So we going to just
copy this here. Let's just copy
all of this here.
So just copy this. We're going to create
a locking form. We're going to do that
manually. So let's just copy this part.
And let's go to our code.
And then we're just going to paste that
here.
Let me just remove this here. So, we're
going to call this sign up
sign up form.
Let me just comment this out first here.
So, save this. So, let's uh modify this.
So, I'm just going to remove the um this
and we're going to just leave everything
like this. So, we're going to remove
this uh
this logo. We're going to replace this
with our own logo. So I'm just going to
say I think this is wrapping the entire
app. So we're going to leave this part
here. I think is the place we have the
data. So I'm just going to change this
to div here.
Let's change this to div. And then here
I'm just going to remove this here.
Then inside here, we're going to just
change this to let's remove the class
and also um sorry, let's just remove
this
and let's import our logo
our logo component. So I think I need to
import this
from component logo. Now
I think we are done.
Let's just add let me just remove this.
Let's just add justify center
and then wait for
like this. Okay. So now we're going to
go ahead and implement. Let me just add
relative here.
So, let me go ahead and let's create the
sign up form. So, I'm just going to
enable this and I'm going to just call
this sign up form. I'll copy this. I'll
go into um app route.
And let's create a folder. I'll call
this common.
And let's just say sign up
from txx.
A S A
let's change this to sign up form. Let's
go back and let's import it
like this. So I'm just going to move
this. We at the top
inside the signup form. Let's go ahead.
I'm just going to close this. So let's
first first we're going to do let's
create a schema um Z schema. So we say
sign up
sign up
is equals to Z let's import Z dot
let me import Z here
from Z
and say Z dot object
and we're going to have the name I say
set string
sorry
we're going to give this a minimum of
two
to two as character length name must be
so let's give it a message must be at
least this
two character like this. Okay,
we have the email
set email.
I'll just say invalid
and then let's give this a minimum of
one.
Email required.
Then we have the password.
You can set that to S string.
I give this a minimum of six character.
Password
must be
at least
six. Yeah, let's just add a character
here.
So we're done with this. So now let's uh
let's go ahead and set a type here. So
I'm going to say type
sign up
sign up form value.
It's going to be said we're going to use
s interfere. We're going to set the
type. Sorry,
it's a type
type of and then the schema sign up
schema. So we have this now. So let's go
inside the uh this and let's create the
form
is equals to use form
use form from uh
from react hook form
and let's um let's add a type here sign
up form value and let's open let's add a
resolver here
and it's going to be sold
uh we
reser going to pass in the sign up
schema. So let's import s and
let me import that here.
So I'm just going to import it at the
top here.
So yeah, we're going to set the default
value. default value.
So name is empty string,
email is empty string and then password
is empty string.
So now let's just say um async
function
on submit
and this is going to have values and
it's going to be of type sign up schema
value and here we're going to be using
uh await
client
dot sign up
dot email form from uh uh better. So let
me just unc comment this out.
So let me just open this. Let's import
client.
Sorry, should be capital letter. So
let's import this from um um li client.
So I'm just going to set this to use
client to
so this should be capital letter U or
small letter U.
And now it's asking us for the value. So
I'm just going to open this.
And then we're going to say email is
going to be values
dot email.
Password is going to be val
password.
And the username, let me just move it to
top. It's going to be val.
So now we need to add can add a call
back here too
/home.
Then we have other option. We can say um
sorry
we have on request.
Let's go back here. I think we have on
success. Let's check. Yeah, we have on
success here
and we have on error.
So we need to add the load state. So I'm
just going to come back what we have
this here. I'm just going to let's
import constant
router cuz we're going to route user to
the homepage. It's a cost to use router.
Let me remove this.
So make sure this is from next
navigation.
Then we're going to say constant
is equals to use state
and let's say it's loading
and set is loading
like this. So we're going to set this
here inside request. We're going to set
this to true.
Uh like this. Then below here, we're
going to have on success. We're going to
redirect the user to the home screen.
And then we're going to set is loading
to false. So just use home. And then for
error, we're going to say toast
toast dot sorry.
Okay. Um I think we've imported this.
We've imported the sona from sona. Then
we say error
and then we can just get the error from
here. CTX
you can just say ctx dot error
message by this.
So we are done with this now. So let's
go ahead and implement the UI. So I'm
just going to remove this and I'm going
to just set this to class name
flex flex column
and gapis
like this.
So we're going to use the card component
for
chant UI. I'm going to say class name.
I'm going to set this to background
transparent.
and then also um border zero.
Then let's get the card header.
Let's say class name
text center.
Then we have the card title
and the type um card title we're going
to just say create
an account.
Let's give this a class name
of text XL like this.
So we also have the description. So just
going to duplicate this here. I'm going
to change this to card description.
Copy this. Replace this here. And then
inside here, we're going to just remove
the uh
last name. We can just say
um create
[Music]
AI
account. You can put anything in there.
like this. Then now we are done with the
header. Let's go over to contents card
content here.
So inside the card contents, we're going
to we are going to define the form. So
let's import from from UI from fun to UI
and then let me just close this and
let's the structure the form sorry
the form that we divide the defined
here. Then once we've done that we need
to also uh set form here
and here we're going to just say on
submit
we're going to say form dot handle
submit. Let's pass the onsubmit here.
So, uh we can also add a class name
here.
It's going to be space-y.
Yeah. So, save this.
So now let's um get the form field from
UI um form
and then we can just sorry this is going
to close this can just multiple of this.
So let's have control.
It's going to be form control.
We have name and we're going to set a
name field here. Render.
Sorry.
Open this.
We're going to get the field.
And let's just return this. I say form
item
from Shanti UI.
Then we have the form label.
Let's h set this to name.
And then we have the form control.
And inside we're going to import impute.
Sorry
post.
And then we have the placeholder.
We can just set this to um John do or
anything.
And we can just set dot dot
field here
like this.
So below here I will have the form
message.
So let's this
from our UI.
Let's scroll back
and let's
sorry
this is some error.
Okay, let's copy this.
it.
Let me change this to email.
Change this to email.
And let's say
um at example.com
or Johnampample.com.
And then we're going to set this to type
like this. And let's copy this again and
do for password.
Let's change this to password.
Type password.
And then I'm just going to change. Let's
just asteric asteric here.
Then once we are done with this, let's
uh call button
from UI button.
Then inside here we're going to have
sign up here.
So we're going to type
submit
and disable
uh is loading.
Then we're going to have class name
say wful
and then text white.
So let's also say it's loading.
Oh, sorry. I meant to say I sorry to
import from
um icon.
Let's give this a class name
is equals to weight
for height for name it
spin.
Let's see this.
And then below the button, we're going
to have a lift. So this is import.
Make sure you import it. I've import it
from
um at remix icon.
Then below the button, we're going to
just have um a div that will say uh let
me import link from next link. Say text
and test more already has an account.
Then we can have the sign in there.
So I think that is it. Uh we can test
this out here. So I just go back to
to local
sign up and we should be able to see the
form.
So we're going to do the same thing for
sign in. So I'm just going to duplicate
this. I'm going to create a file here.
I'm going to say sign
sign in
form.x X in here
and we should al to see uh this is
showing this is okay.
Um let's just copy everything from sign
up. I'm going to just place it in sign
in. So let's copy everything from the
sign up and paste it inside the sign in
form. So I'm going to paste it here and
let's change this to sign in.
So copy this. Let's go back up.
change the component to sign in. So, I'm
just going to change most of this to
sign in.
Also, yeah, we're going to change this
to sign in.
So, I'm just going to change this to
sign in schema.
Copy this. Paste this here. Paste it
here too.
Change this to sign in.
We're going to come back for we're going
to come back to the um
on submit. So yeah, I'm just going to uh
let's remove the name.
We have the email and password here.
Then we can scroll back up and let's
just uh change this to log into your
account. Your account you can set this
to u anything will come back.
Welcome back. It's okay.
This is okay. So, let's go down here.
And here we're going to change this to
sign in.
And there sign up.
So, let's change this to sign up here.
Already have an account. We just say
don't
don't have an account.
sign up. So I think that is all. So
yeah, we're going to change this to um
login. So I'm just going to say instead
of sign up, we're going to use sign in.
So we're going to remove the name.
I think that is it. That's it. So we
just to home.
So um
that's pretty. So
let's go over to the sign in page. Let's
come over to sign up sign up page first
and let's just copy everything here.
Also in the sign in form I forgot to
remove the name here. So just remove
this from the name and also remove the
default value.
Then I'm going to go back to the signin
page and I'm going to just paste what I
copied from the sign up page.
Just paste it here. Import the logo.
And then let's import the sign in form.
So it's work. So before we go ahead and
test this out, you need to u So click on
sign in and let's see.
So it's compiling the sign page.
Yeah. And see we have the sign in here.
So before we go ahead and then complete
it, there's something I forgot to do
inside the API. We need to create an
O folder
and then we need to create a capture. So
let's go back to the documentation and
then let's see that. So if you go over
to the documentation here, let's go back
to better.
So I'm just going to load this.
Then we're going to go over to
integration.
Then click on next.js.
Then you should see that um in next year
integration we need to create an all
folder catch um we should catch all.
Just specify do all just copy this and
then we we can copy this. So once you
copy this test, go back to the code.
I think we don't have any
any other thing to copy from here. So
I'm just going to go back to the code
and then we're going to go over to all
here inside the API folder and let's
create that.
Okay.
on
all.
So I'm just going to say routx
tx
and let me just paste it here.
So I need to be sure I
do. So save this. And now this is going
to catch any API call from the get or
post.
So now we need to add some plugins here
because I want to also enable um
beer token by default and better to use
um cookie save the session in cookie. So
I want to also enable
um beer token. So what I can do is I can
go over to better and then add in the
beer plugin. And if I want also want the
um documentation then I can also add the
um the plugin for that. So let's go over
to documentation
and then let's do that. So I'm just
going to go over to my documentation
there and let's go over to let's quickly
search for.
So I click on search and say beer
and we can click here. You see um
then you can see u for art you can use
you can add in the plugin here.
So this is optional. You can skip this.
You can skip this one. It's not
important but I'm going to use this to
test the API. So that is so if we are
copy adding a um plugin we need to also
save the U token in local storage and
then we can we can set it here I think.
Yeah. Yeah. We can set it to the create
all client. So we get it. So every
request a token be token will be passed.
So basically that is it. So I'm just
going to copy that there and I'm going
to go ahead and paste it. So before we
go ahead and paste it for the
documentation we can search for
open AI
sorry
open API
and then for the open API this is going
to give us a documentation like this. So
you can see all of the API all of the
route
there the route there. So we can just
open uh API reference. So I'll just add
it too. So we can copy this plugin
for
open API and also add it and that will
just work fine. So I'm just going to go
back to B to make sure I copy the am
login to. So let's go back to the code
and let's add both of them. So inside
the
inside I think inside this here
below here we're going to add
plugins
and let me just sorry let me just paste
in the
out first.
So we have the open API. Let me just
copy this two.
I'll just paste this here too like this.
Let's also import the beer.
So this should come here.
So now this will add the two plugin.
Then you can access the um open air API.
from the auto reference. So what I'm
going to do is I'm going to create a
hook here and I'm going to um get I'm
going to use system to save the B token.
So we've already installed system. So
I'm just going to create the B token. I
want to use this to test the API. So um
so let's go into the uh sorry the hook
folder and let's create a file to set up
to save uh u token to this local story.
So let's create a file. I just call this
use
um
uh token
tx.
And then inside here we're just going to
have the interface first or let's just
say export
constant
use
token
and there let's just find the uh
interface here
Sorry,
token is going to be the state. So, I'm
just going to call it uh let's call it
state. Then inside here, I'm just going
to say um beer
beer token.
It's going to be a string
string n then we're going to say set
um beer token this going to be token
string or you can use that and where we
have um clear
be token void then here we're going to
use create from uh from just so I'm just
going to import that
uh before I do that let's remove this
Sorry,
I need to add a type here.
That is a state
token state. And then inside here,
you're going to open
like this. Then we're going to use
persist. So this is going to posess the
uh
pist.
So let me just import both of them here.
So import
from system. So let's import create
here. And then we're going to just open
this here and just say / middleware
And then we can import um past this
here.
So let me just copy this paste it here.
So now we need to define um the method
here.
We're going to have um set.
You can also have get here if you want
to use that. I'm not going to use get.
So I'm just going to only use the set.
So we have um
beer
token no
set um token to set token to token and
then we have the clear token here. Then
after this we're going to add here add
an object and then we're going to give
this a name. So here's the name
but it's odd storage
like this and the error should stop. So
I'm going to just disable this um
this suggestion.
So we done with this now we're going to
make use of this inside the sign in and
sign up. So I'm just going to copy this
and then let's go into the sign in
signing form.
And then let's come over here and
there's a constant
is equals to use token use token. So
import that
and then we can just get set be token
here
and to get it remember we can get this
from the header by the documentation. So
I'm just going to do that inside the
success here. So let's get the CTX here
and then there we can see constant out
or a constant to is equals to ctx dot
response
dot
headers
dot get.
And we're going to get set
set all
token
say if and token
then let's just set
sorry can pass in the token here
like this
like this is okay. So, we can also copy
this and go over to the sign up and then
we can use that. So, I'm just going to
copy this. Open this here. Um I don't
think we need it. We don't need it for
the sign up. So, I'm just going to leave
it here for the sign in. So, um
I think we are done with this.
We've added the rout. So, let's test
this out. So, I'm just going to go over
to the dashboard page. Make sure we have
the um home. Let's just create a page
here
xxx.
I just say fce
home.
And then here we just say homepage
like this. So we can go ahead and test
this out and see this work. So make sure
your server is running and then let's
try and sign in sign up first. So let me
just sign up. I'll click on sign up
and then let me just give this let me
give this a name
and this password. And if I click on
sign up now, you can see that this is
calling the um API
um all
and then this should sign us in.
Okay, so password too short. So let me
just change this.
2 3 4 5 6. So by default OS wants you to
provide all the files. You can change
that in. I think the error is not
stopping. So I need to go over. Let me
close this. I mean, sorry, the loader is
not stopping. So I'll just go over to
sign up.
Sign up form. Then scroll down where we
have if there's an error.
Just stop. Set this to first.
So yeah, we can do that here. So I'll
save that and then let's try this again.
Let me just reload.
Okay. So, we can change that. Just let
me let me change the password.
I'll click on sign up now.
It's the same password is short.
So, let me try.
So I type in 128. Let's see if this will
work.
So it work. So it's directing us to the
homepage.
And then this should be direct us.
Compile.
So now we have
we are now in the homepage. We can see
the sidebar and we can see the um
homepage. So that is it. Uh we're going
to go ahead and start working on the
dashboard UI. So that is it. So let's go
ahead and then work on the dashboard UI
interface.
So before we go ahead and work on the
sidebar, we can also modify here. We can
modify the email and password. uh we can
just modify it by passing the minimum
password length four. So this is not
going to um force it's not going to
enforce us to pass it um password. So
I'm going to set it to false and four
and save this. Let's go back to client.
So inside the client we need to also add
the fetch. Remember we saw that in the
documentation. If we're using B token we
need to pass it to all of the requests.
So I'm just going to import um the O
token. Then I'm going to just pass it
here. So you see fetch option. We have
the O type barrier. Then we have token.
Then we have use token dot get state. So
use token is from the hook get state dot
beer token. Let me set that to empty
string if there is no beer token. So
just save that. So that is it. So I'm
just going to remove clear my everything
and let's go into the sidebar. So, I
just click all of this and I'm going to
just go to uh index sidebar and then
let's um start this. So, what I'm going
to do here is I'm going to paste the
navbar. So, I'm just going to paste nar
here and then let me import all of this
from um Remix icon. So, just import all
of this.
So, import this.
and the last one.
So, so let me collapse this.
So, inside here, I'm just going to pass
in the props.
And then I'm just going to call this
react
dot component
component props. You're going to put
types
type of sidebar from
sidebar from react uh
sorry this
type of sidebar. So let me import cyber
function UI.
So after that we're going to just we're
going to set a router. So let me set
this to okay router
is equals to use router.
Let's import this from next navigation
and let me just say to use client here.
So scroll down. Then here we're going to
we're going to import the beer the use
because we're going to log out the user.
So we're just going to import this from
the hook. Then we're going to um get the
clear.
So clear beer token. You can see that
here. So this method is what we're going
to use to clear. Then we can also have
our loading state. So I just say is
signing out
then set is sign out
is going to be equals to use state.
I'll set this to false.
So let me import state.
So now um we can also get the uh
session. So this is going to we're going
to use to get the user name and user
email. So I'm going to say constant and
this is from O. So I'm going to say
we're going to import client. So client
is coming from lib client. Then inside
the client we can get the use session.
You can see the method here the hook
here use session and we can also have
the sign out here. So inside the use
session we can get the say use
use session
then we can get the u data sorry we're
going to call this session
and then we can get is pending.
It's going to tell us when it's loading.
Then inside we can get a user. So user
is equals to session
dot user like this.
So now we've gotten everything. So now
let's go ahead and um let's define the
handle first handle log out
it's going to be equals to
say if uh is sign
just return
then we can set um is Sign in.
It's sign out to true
like this. And then we say sign out.
You can just do like this. And you can
also open this and just pass in the
fetch option.
And then inside the first fetch option,
we can get on success.
And on success, we just return a method.
And then we're going to just clear
token.
And then we're going to route the user
to the login screen. So just say out
slash sign in
sign in.
Then we can set u a sign out to false
here.
I think we also have an error.
Now we can just
let's import that from sona dot
error and then here we can just have the
ctx here and then let's get the error c
sorry x dot
error dot message.
Then we can just um let's just set this
to um a sign out force here. So now we
have all of this. Now let's go ahead and
implement a sidebar. So I'm just going
to say sidebar
sorry
sidebar from
um okay we've imported that sidebar
and here we just pass in the props
let's have a class name
of
so I want this to have a Z index of So
let's just give it 995 or 999 like this.
Then we have the uh sidear header.
Then we have we can have a div say class
name is equals to widthful
lex item center
and then justify um between because we
want to we want to add a um the button
that toggles the sidebar here. So let's
uh let's pass in the logo first. So logo
from logo and we're going to pass in the
URL
to /home
and then we're going to say cyber
trigger.
Uh where is this cyber
trigger? Yeah,
I'm just going to add a class name for
this to m minus mx4.
And below here, we're going to just have
a border line here or we can call it a
divider class name. We're going to just
give this a class name of border
uh let's give it a border border
mx2 and then minus minus tpx
like this.
Then um we can
let's have the sorry after the we can
just have the side the search um button
I'll just comment that we can do that
later.
So here we can just have the sidebar
content.
So inside the server content we're going
to have um let's first of all set the
class name first. So your class name is
going to be PX2 PU2
then overflow
uh S2 overflow
overflow XCD
I think this will have overflow um Y
auto it's going to have the scroll bar
so I'm just going to also uh we're going
to create a component called navmin
and this is going to pass in the
call this items and nav.
So I'm going to just copy main scroll
down back and then paste it here. So now
we're going to just create let me just
quickly create this component or let's
just complete everything here. So I'm
just going to comment that first. Then
here we're going to have um the nav um
notes.
It's going to have all of the notes for
us. we're going to use up. We're just
going to comment that now. Then below
here, we're going to have the footer.
So, I'm just going to just come over
here, copy this,
this border line or z line. Just paste
it here. Uh, just give it like this.
Then lastly, we're going to have the nav
user.
Um, okay. I think this should be
Sorry, guys. Let me just copy this and
just add sidebar.
I'm going to paste it here. So now I'm
going to have the nav user. Then inside
here we're going to have is loading
and this is going to have the is pending
here.
Then we're going to have user
is going to be equals to an object.
We're going to say name.
The name is going to be user dot
we get the name I just said empty string
then we have the email uh user
dot email
I don't think we have avat
there to empty string like this
you can see user dot
image but we don't have image. I'll just
keep it empty like this or you can just
remove it. Then lastly we have um is
we're going to add the um is sign out.
Yes. So I'm just going to pass it here.
Then on sign out
it's going to be to handle
handle log out like this. So let's just
quickly go ahead and create the nav
user. So I'm just going to come over
here, create a new file, nav user txx
user.
So let me just import this.
So let's go back and complete this here.
So just have prop at the top. Let's just
pass in the prop type props is equals to
user is of type name string
u email string.
This is okay. And then we can just have
uh I think we have
let's go back.
Okay. Yeah, it's loading and then it's
signing out. So I'm just going to pass
that here. So it's loading.
of Tiban
then is sign out
is after boolean
then um we have um on sign
on sign out
is going to be
void method so I'm just going to uh we
can just get the props here. I just say
props
and then just getting the user
um is loading
a sign out and also on sign up too.
So inside there we are going to use a
constant
um
let's get this from use sidebar
once it is mobile. So we're going to
make use of that. So let's just um get
the side menu from shanty UI
that's from the UI u UI sidebar.
Sorry menu not sidebar
menu. Yeah. So, we have a sidebar menu
item
menu item.
And now we we're going to get the drop
the drop menu from UI from UI dropown
menu.
Uh let me remove the sidebar.
So inside here we're going to have is
ning.
If it's loading, we going to draw our
icon. So, we're going to get the loader
from
we add loader uh remix icon.
Let's pick five.
We say class name.
We have w five, height five,
animate spin.
Then else you're going to show uh the
drop down trigger
drop
down trigger
menu trigger
resize to as child.
Then we're going to have the sidebar
button.
Sidebar menu button.
So let's just um
like this. So inside here we're going to
give this size of large
and then we have a class name.
We're going to say data
uh states
um is equals to open. So we want to
change the color and we can just give it
PG sidebar
uh sorry asset
then we can also have data
states
um equals to open again
and then we're just going to do for the
test color
test
sidebar
accent foreground
like this. Okay. So inside here we're
going to have avatar
from UI avatar. I need to have a class
name.
Class name equals to um height 8 width 8
rounded uh large sorry rounded
large
like this. Then we have border and
border primary.
Sorry, not going to use image. So I'm
just going to use avatar
fallback like this. And this will have a
class name
from rounded. We're also going to do
rounded log.
Let me just say user
dot name
character at index zero.
Just like this. Then here we're going to
just have a div
last name
flex one
uh text left
x small
and leading
uh tight
like this. So we can just have the name
and also the uh image. So I'm just going
to say span.
We're going to have we're going to say
class name
font medium.
Let's have this again. So, one is going
to be for we're going to have one for
the username
name
and then the other one for the user
is. So below here, we're going to just
have an icon and just say uh
chevron.
I have chevrons up
down icon.
Just give this class
name
size four.
like this.
So now we have the trigger. So let's
also uh implement the the content. So I
think this is just for the trigger side.
So below here um below here we're going
to have the drop down content
menu content.
So here we're going to just have
name
width.
So let's just say um sorry minimum width
56
then we have rounded
large
then for size
you're going to say if is mobile
then we're going to say this to bottom
and then uh right
like this.
Okay.
Size does not exist.
So this is going to be side not size
side.
Then we have align
and then we have side offset four. Then
we can have um on close
auto focus
um
let's just
if he's signing out
then we can just say uh
let's just put e.revent prevent. So I'm
just going to add the E there. E it just
prevents defaults
like this. Then inside the dropown
content, we're going to have
a drop-down
menu label
from UI dropown menu. Then this will
have a class name
of padding zero normal.
Then we should have a div
name
flex item center
gap 2 px1
py1
sorry py 1.5
x left
x small.
So inside there we're going to also have
the avatar. So I'll just go there. Let
me copy that.
So, let's just copy everything like
this.
Let me collapse this. Bring it here.
So, I'm just going to paste it inside
here. So, let me just paste it inside
here
like this.
So, now we have the label. Now we can
just add a drop-own separator
menu
as separator from UI menu
and then we can have uh drop-down
drop-own menu
item
like this. So let's have a class name
here
relative.
Then we can have uh we can disable this
button
disable if is signing out.
Then on click
on sign out.
Then we can have icon log out.
box line.
Let's have our class name
text uh muted forground.
Then we can have um text primary or
let's just leave it like this. Then we
can just have a log out here.
Then below here we can have a sign in
out.
So we're going to show the loader
how I loader five view
and it's going to have a class name of
weight for height for absolute
right to and I amate spin
like this. So um we are done with this.
Let's go ahead and then work on the nav
menu. So I'm just going to scroll down
here the nav menu. So let's create a
file for nav
dash menu.
Let's say R A S C E.
So I'm just going to import this here.
So let me just replace this to Nav menu.
And this should be Nav menu. N.
So let me uncomment this and let's
import this here.
So, let's go into nerf menu. Let's
import. Let's set our prop type props.
So, I'm just going to go inside the um
let's add the items here.
Items is going to be title string
then URL of type string
then icon we can have this remix
icon icon component type.
Let me just move this up here. So yeah
we can just open it and just get the
items and set
uh the type to props.
like this. So inside here we're going to
have we're going to import router
from use router.
We're going to get router from use
router. So import use router from next
navigation.
Then we can get a path name
which is going to be equals to use path
name.
So import that too. Then inside here,
we're just going to have
we're going to have our sidebar
and side menu.
And then we're going to look through the
items
do map
item.
So let's say constant is active
is equals to name is equals to item dot
URL.
So let's return
then the side menu item.
So this should be an array.
So we're going to pass in a key here.
Let's say key is going to be equals to
item dot title.
And then we can just have our class name
relative
flex flex column
items
stretch.
So let's also have the side
uh the sidebar
menu
button.
So we have class name
we have group menu
button
font menu I mean sorry font medium
then we can give this u
um a gap of three
Let's give it a height first.
Rounded menu medium.
We can give this a background gradient
to right.
Then hover
bg transparent.
Let's have another hover which is going
to be from sorry from sidebar
ascent.
And then we're going to have over
again.
This is going to be for
sidebar ascent.
We're going to give this 40
the 0.4 opacity. Then now we're going to
say if
this is active
is true
and then we're going to say from
primary
20 0.2%.
0.2 opacity. So I say data
is active is equals to true. Okay, it's
going to have two primary
five
like this is okay.
So we can also have uh the and for
SVG
we can set SVG to uh size auto. Uh let's
just set the size
auto
like this. So here we can just have is
active
is equals to is active.
Then we need to also add pointer
pointer here. Then we can just have on
click.
Uh it's going to be
router dot push
item URL.
So here we're going to have the icon. So
I'm going to say item dot icon.
And let's have the class name here.
And it's going to be text muted welcome.
Then we're going to have group
data
add if true
the menu button
X primary.
So I'm just going to reduce this to 0.6.
So like this. Then we can just give this
a size
22
like this. Then we have the span here.
And this going to just hold the item
title
dot title. Yeah.
So we're done with this. Now the last,
let me check.
So let's change this to menu.
So I'm just going to create uh the last
one nav.not.
And let's import that here.
So inside here, we're going to list the
notes, but we're going to do that later
once we implement the API. So I just
want to create the menu first. So yeah,
we're just going to uh let's remove
this.
So yeah, we're going to have the
sidebar.
the sidebar uh group.
Then we're going to have sidebar
side by group label
and this going to call notes
and then we're going to have sidebar
group action.
And it's going to have an icon of add
from um we're going to import that from
MXU um icon.
Let's just give this a class name of
size five.
Let's also give this a class name.
Let's say margin top
1.5 pixel
then flex
item center
item center then we have uh
size
it's going to be 5.5
then we have founded
medium
MBG primary
0.2 border and cursor pointer.
So you can save this like this. Then we
can have uh below the label we can have
let's also add notes here. Sorry.
add a note.
Let's give this a class name.
So, we're going to just say to only SL
only. Then below here, we're going to
have the sidebar contents,
a group content,
and it's going to have a class name
of width for height auto.
Then minimum height
32,
maximum height
uh
360 pixel,
then overflow
y auto
like this. So here we're going to have
the sidebar menu
and we have the sidebar
menu item.
So, we're going to come back for this.
So, we're done with the sidebar. So,
we're going to go ahead and create the
main content. So, inside the layout,
going to dashboard um dashboard layout.
We have the sidebar. So, um we can just
Okay, we've already imported it already.
So now we need the main content for
this. So I'm just going to come over
here, create a folder. I'm going to call
this common.
I'm going to call this create a file.
Let's call this u main content
tx.
So a fce.
So this is going to have a props here.
Let's just set this to use client.
So let's have our type props
children
do react node.
And then let's just get the pass in the
props here and get the children.
like this. So yeah, this is just going
to be u
it's going to be
this
main
and we're going to just pass in the um
here.
So I'm just going to give this a class
name first.
relative
withful
height auto.
We can just say overflow
hidden like this is okay. So let's just
copy this. come over to layout inside
dashboard and let's just um add it here
and let's move this inside. So I'm just
going to import main content
um like this. So
So we're done with the uh dash um
dashboard layout. So we have the main
contents. We're going to go ahead and um
let's go into the home
the homepage. I think this should be
working.
So let's um implement the home UI. So
I'm just going to go into the home. So
I'm going to create a folder. I'm just
going to call this common.
So I want the page to be only for um as
our um
server side component. So I'm just going
to modify this. So I'm going to say
default. Okay, we already have that. I'm
just going to pass in um async here.
So like this. Then we can just have our
main contents here.
Sorry, main session here or home
session.
And this is going to be a self closing
tag. So let's just import this.
So let me just create this first.
So inside the page, we're going to just
import this here.
So inside here we're going to have the
header and also the component.
So we're going to quickly create that.
Yeah, we're going to do that.
So let me just come down here. So let's
have a div here.
And this is going to be a class name
relative
weightful.
Then we're going to have another div
here.
And this is going to be max with
uh 2 XL
MXO
and space
and Y5. Let's also add W.
So inside here we are going to have a
div again
and in this div we're going to have a
class name
withful flex item
item center
justify center margin top 16
and then we're going to have uh the text
H1 and this is just going to have
a text. How can
I help you
today?
Like this. And inside here, we're going
to have uh emoji.
We say
from um remix icon, we're going to say
emotion
happy.
Let's give it a class name
of size 24
pixel.
So let's give this a class here.
I say flex
it center
gap to
um front
heading
front board
semi
then text
uh
text Enter
tracking
tracking title. Then we're going to say
text
gray
800 on dark mode.
Sorry, on light mode. Then on dark mode,
we're going to have uh Dex
white.
Then on small screen we're going to have
text
size of 30 pixel
medium
text
size of uh
going to have size of 35 pixel
and then we have text 24 pixel.
You're going to have opacity zero
fade in
fade in up.
Let's just give you fade in up. Then
we're going to have um
animate
animation
delay
of 200
milliseconds
and then we just have index zero.
So like this. So for the f fade in up,
we're just going to go over to global.
Let's go back to global CSS and let's
add the style here. So I'm just going to
paste this side. So it's going to be key
frame fading up opacity and then
transform then opacity one then fading
up.
So just write this in the CSS and then
let's go back. Then let me collapse
this.
So I think below here.
Yeah, below here we're going to have the
uh chat impute.
So I'm just going to comment that here.
And here we're going to have the recent
note. So I'm going say div
last name
wait for
adding seven
and we're going to have span
recent
notes
and this will have a class name
of text small
uh on dark screen on dark and dark mode.
We're going to have text white
50
like this.
So, I'm just going to just cut this
here. Wrap this inside a div.
I'm going to just set this to class name
waitful.
And then below here, we're going to have
the
we're going to have the recent
notes
here.
So,
so that's it. So, let's go ahead and
create the header. So, I'm just going to
uncomment this and I'm going to come
over to dashboard here. I'm going to
create header here. TXX
say
header and let me go ahead and import
that. So I'm just going to import header
here.
Save that. Then go into the header
component. So for the header I'm going
to add a prop
type props.
We're going to have title and title is
going to be a type of string but it's
going to be optional because we're going
to be using this header for other
components. So I just want to set that
here. So I'm just going to say props
uh we're going to pass in the props
here. Then here I'm going to just say uh
constant
use sidebar.
So let's um let's change this. Let's add
the use client here.
Then here we're going to get if uh is
open if side by is open and if it's on
mobile
then we're going to just remove this and
let's just add header.
They're going to say uh if not open
or is mobile
then we are going to show uh the sidebar
trigger
a height of 10 like this. So let's just
give this a class.
So for the class uh first we're going to
have this to fix
top zero
left zero then uh set zero
insert index 9. Then we're going to give
this a height of 40 pixel.
Then flex
it center
x uh 8
y1
background color of background
like this. And let's give this a
backdrop.
Backdrop of blows small.
I'll just make this
like this.
So like this.
Uh then I think uh we're going to use
this for later on. So I'm just going to
leave this like this. I think that is
all for now. So we should be able to see
uh the
uh icon here. So I think this is
we can see u
this is not showing this is wrong. We
can see the note. We can see the plus
icon and we can see the menus here. So
I'll close this. I think this header the
icon should
left.
So let me just say medium
adding X.
So let me just do um PX2 here.
Let's see. Yeah. So this is okay. This
position is okay.
So let's go back to the cyber and fix
that u
that knife user.
So let me open the cyburn. Let's see.
So flex
create
this supposed to work. name and email.
Or let me just add block here.
So I'm just going to remove the block.
Let's say glid here. So if I click on
this, we should be able to see position.
So I'll scroll back up and let me add
grid to his. So add grid
and this should fix it. So now we can be
able to see the log out here and this
should be able to work. So I think guys,
so let's go ahead and um set up hon so
we can start implementing the um notes
API to create a note and to fetch all
notes.
So let's go over to Google and search
for honojs. So click on the first link
here. So once you click on hon the first
thing just click on documentation and
then you can see how to use hj. So h is
very simple similar to expressjs. So you
can just define app like this and you
get and just um implement this and
you'll be able to use this straight in
your next app. So what we're going to do
is to first of all we need to um quick
set how to install to install one of
first then we can come over to uh the
concept not concept let's click on get
started then we can see nextJS. So click
on nextJS and if you click on nextJS you
can see how to use honor inside NexJS.
So uh we can define that by creating a
capture route inside our API folder and
then making use of this inside our
project. So, we're going to copy this
and go ahead and just before we go ahead
and implement that code, I want to show
you uh something else that uh makes Huno
better. Hono support RPC. So, there's no
need for us to use um as or fetch inside
to call the endpoint on the client side.
So, instead we can come over to I think
it's helper.
Um let me check middleware.
Let me just quickly search for that
here. I just search for RPC
and then this should then we can see the
RPC here and let me look for where to
select. Okay, it's inside guide you can
see RPC. So inside the RPC you can see
that um RPC we need to make use of Z
validator. So this is going to be used
for the uh the payload or params or even
form. So if you scroll down here, you
can see how to use set the RPC. So we
have to create a a file that has the
type. We create the type app type and
you can see that here.
Then we can call it like this on the
client side. And this is going to work.
So this is so so so good. So we're going
to combine that with t query. So, so to
use it to to make sure to use it with
RPC, we need to combine all of the end
points together. So, if I scroll down to
where we have
uh
where we have this,
okay, RPC, you can see RPC for larger
app. You can see we can combine um the
get posts get all of them inside one
bunch of connected they chain together.
So with this we can use it with our PC
and this is going to give us all of the
types there. So basically that's how
we're going to pay. So let's go over to
next year again and let's go ahead and
copy that. So, we're going to just come
down here and then we're going to copy
this uh simple and let's go ahead and
create this cache. Yeah. So, I just go
back to my code and let's install u the
hon
inside here. So, I'm just going to open
this and let me just cancel server.
So, I'm going to just do mpm install
hono and install the version I'm using.
So, I'm using Hono 4.9.4.
4
and click on enter and this should
install HJ for us. So we're going to
also install inst validator too. So
let's just wait for this to install.
So this has installed already. So let's
just install
kono at hono.
I'm going to say ato slash sword
validator. Sorry.
And we're going to give this a version.
I'm using 0.7.2
like this. And then let's click on it to
install.
So this has installed. Let's just um
let's run the server.
And then let me close all of this.
So inside the main section first before
I go over and do that, you need to make
sure you add um medium size 40 and large
empty where we have this. How can I help
you today? So just um add that. So I'm
just going to go into my API. So let me
close all of this.
And then we're going to
let's create a folder.
And then let's have the
route.
And then let's have route here.
And I'm going to just paste it. Yeah. So
I've pasted it. So let's just also add
the patch put and delete here. So make
sure you've created this on router tx.
So I'm going to close this. Now I'm
going to also add um export runtime
constant runtime
node.js.
So we're going to just set the runtime
to JS instead of edge which is um good
because we're using Prisma and Prisma
require NodeJS environment. So, uh,
let's test this out. I'm just going to
make sure my server is running. I can go
back to the browser and let's see. Let's
type in local
3000. And then we have hello,
sorry, API first. API/hello.
Click on enter. And then this should
load this uh for us on the browser. And
we should be able to see hello next
year. And then we can see this. You can
see hello N. So this is working very
very fine. So now what we going to do
now is to uh we're going to
rearrange it here. I'm just going to
remove this hello. So this is going to
be hello uh um hello from Wave AI.
And then I'm just going to remove this
um part here.
So I'm going to just say constant route
is going to be equals to app dot we're
going to paste the base uh part here.
So now
and here I'm just going to change this
from app to route
like this. So yeah, we're going to also
define the type here
like this. Sorry, I should just change
this to route
like this. So yeah, we want to have
error handler. So I'm just going to put
there and we say app dot on error. This
is going to catch all error
and then it's going to get the error
here.
and see here.
So we're going to say if error
instance
of HTTP exception.
So let's import this
Okay, let me just duplicate this. Copy
this. Paste it here.
And then we're going to get from Huno uh
HTTP exception like this.
Then I'm just going to say return
error dot get response like this. Then
last we're going to return a seat. JSON
error.
Then internal server
internal
error
like this. So this going to catch the
errors for us. So now um we to set the
rout for this and then this.
So inj
let's say we have id here. So how to get
this? We can just say constant
uh let's say ID
uh something like that. Let's say id is
equals to c dot then we can get the you
can see uh c dot
request params here.
uh then we can just define ID and you
can see if you hover over over this you
can see the ID here. If you have uh
let's say we have page equals to
um we have page
like let's say we have query so I'm just
going to just copy this paste this here
and we say query
sorry this is going to be query
and let me say I'm passing a page I'm
going to just get the page here. So
basically this how to use JS when you're
trying to get the params the param then
if you're getting the post it's very
easy you can just say constant um let's
say the JSON
is equals to uh say just request
dot um yeah we're going to have JSON
here
and this is going to give us the body
where pass in the body while this give
us a query and this give us the params.
So if I just pass in ID
uh I just say ID here
and if I save this and test this on our
browser. So I'm just going to pass in
uh
let me just add
like this and click on enter
and then we can see the ID is showing
here. So that's it. So this how to uh
make use of basically the simplest part
of how to use honojs. So I'm just going
to remove everything here and let's go
ahead and start implementing the notes
API. So I'm just going to close this
here. So for the note API, we're going
to change this. Remember, we are using
RPC, so we're going to change most of
the um the APIs. So to make it cleaner,
I'm going to just create a file called
note. CX.
So let me just define that here. So I'm
going to call export constant note
route. So just import this here.
And now we can just copy the note route.
come over to route. Sorry, not route.
And then we can just say uh dot
dot uh routes sorry.
And then let's import the note.
And this is basically how we're going to
uh we're going to do implements there.
So uh let's go ahead and also so before
we go ahead and start implementing
endpoint we need to
protect our our endpoint. So we need to
create a middleware
uh which we're going to use better out
to validate the user that is trying to
access our endpoint. So I'm going to go
into lib. So first of all if you go into
go to the documentation
in honor you can scroll down and you can
see middleware. Yeah if you go over to
third party middleware we can see we
have different middleware for different
authentication like clock and others but
we don't have for better o. So we can
create custo create our custom uh
middleware. So if you go over here and
find factory,
click on factory here, you can see this
is a helper to help you create your own
uh middleware. So basically that's what
we're going to do. So let's go back to
the code and let's implement that. So
inside the code, I'm going to create a
folder here. I'm going to call this hono
and then I'm going to create hono
middleware.x
here. So inside export let's say export
constant
get
user
and this is going to be equals to so
let's import it here create middleware
from hono factory so I'm just going to
paste it here and there we need to set
the type which is u set env
so we can define them here type env V
and we have a variable here
like this variables
and then we can define what we have
inside. We have the user id string
email and this is this is coming from uh
this type is basically what is inside
session. So I'm just going to say better
session user. So say string
name
string
uh you can have uh created arts
dates
updated arts
dates like this. So uh inside uh better
we have the email verify
boolean like this.
So here we're going to set this to async
and we're going to get the context and
next.
So now you can use try catch here
and say constant session get session is
equals to await
dot API. says import
from
import
from
sorry
here
say do api
dot get session
So we need to define the headers
and we're going to say C do request. So
we're getting the headers from ho raw
dot headers
like this. So now we going to check if
not session
then we can use we can throw an error.
You can say new HTTP
exception
from Huno. You can set this to four
otherwise.
And then we're going to just return
JSON.
Sorry
error.
Let me just change this to message.
unauthorized
by this. So
if the user is authorized, we're going
to set the user.
Let's say user
session do user
like this. Then we can just say await
next.
And for the error we can just console
error.
And then we can just just copy this and
just paste it here.
I can even remove this if I want.
Okay, instead of using the JSON, I'll
just set message here
and just passing unauthoriz. So, let me
just remove that and just change it.
So, because we already have um inside
the owner, we have the our handler. So,
this is going to catch it's going to
catch the error here. So I'm just going
to scroll down here and let's just
So lastly, we're going to also create
the Ho RPC. So I'm just going to create
a file honc.x.
We going to export
constant client similar to what we saw
in the documentation. This going to be
close to HC. So we're going to import HT
from Hono client. So say import
HC
from honor
/client
and then we can just set the type to app
app type sorry app type.
So we have process envir
[Music]
URL app URL. So we're going to define
that in the EMV. So let me just go over
to my EMV and I can just do that here.
just put um http
local post 3000
just similar to what we have in beta. So
I'm just going to save that and let's go
into our PC back and let's also export
the API constant API is equals to client
dot API.
Sorry.
API.
Why is it saying on?
[Music]
Okay. Missing EMV
processor EMV.
Let me try. Let me try.
So I think we're having some error
issue.
[Music]
So this is this is giving us this is
showing unknown
when this supposed to show the type. So
I'm just going to comment it down. Let's
first implement the API first or not.
Then we can come back and enable it and
see why it's not working. So I'm going
to test this out the error handling. So
I'm just going to go out to my route and
then to add middleware in HJS we can
just add it in between here and let me
just import this here.
So I just change this to
hello like this and let's see if this
will throw an error. So I'm just going
to um load this. So let me just remove
the hello. No need for that. So going to
the server is running. So, I'm just
going to modify this. I'm going to
remove the ID and I'm going to just
click on
um local 3000 AP. Click and press enter.
Uh let's see if it's going to show the
unauthorized
or not.
So, I think we are logging. So, let me
try and log out and let's see.
So wait for this to load.
Let me just open this. Click on log out.
So log out.
So let me try it again.
Then we can see unauthorized. So let's
go ahead and create the note API. So I'm
going to go into the note file.x
and we're going to create the first one.
We're going to have post here. So we're
going to change this. So just say sorry
post.
And then inside here we're going to call
this / create.
Then we need to add the Z validator to
validate our payload. So I'm going to
use the S validator
V from
from HJS. So I just and then the um
let's import this first.
So let me just import this from JS.
So now um inside validator we can get
the we can get JSON from query params
and others here. So since we're using
post request and we want to get the
payload we're going to use from JSON and
then we need to pass in the schema. So
I'm going to define the schema here.
Sorry. Yeah. And a constant note
schema
is this equals to sobject. So let's
import
and we can just pass it here
like this. So inside here we need to
define the uh values. So we can just say
the title
is s string
and this we have minimum of one
and then we can have the content
s string
like this. So let me add comma here
like this. So let's just pass in the u.
So we want to pass in the
get O user
and then let's add async
and get our context
and return this. Now we're going to use
try catch here.
We're going to get the user. So remember
we set the user. If you go into the get
remember we set the user here. So I'm
just going to get user now. say user
is equals to C do get
and then user.
So now we need to get the uh
the title and content. So to get that
instead of using the C contest
request JSON so this time we're going to
use we're going to use request
content valid and there we can get the
JSON. So inside here we can get the
title and you can see that this is going
to give us can see title and we can see
context here.
So we can just create a note say note is
equals to await Prisma. So let's import
Prisma from
uh Prisma.
Prisma from the leaf folder
sorry.
Yeah. Prisma
dot nodes
dot create.
So we'll pass in data title.
We pass in a title
and we can pass in the content here.
Then the user ID
it's going to be user dot ID
and like this. So let's return
return our response C do JSON.
So I just say success
true and then data is going to be the
not
and here we can just throw
new error http let's call http
exception
pass in 500 and then we can pass in the
message
failed to create not
like this. So let's just um I just
cancel the area
like this. So now we've done for the
create note. So let's go ahead and do
for the update note. So, I'm just going
to remove this. Um, yeah.
And let me move this up here.
So, I'll collapse this. And then after
the post request, we're going to also do
for the um upate uh endpoint. So, I'm
just going to add dot here.
Then, we're going to use the patch.
Now we need to define best passing /
updates
and then the params id. So here I'm just
going to set the validation for this.
We're going to define the ID and also uh
the uh payload that's the
body too. So for the body, we're just
going to just use node schema partial.
And there we can just say constant
node
ID schema.
Let's just use u.
So let me just copy this.
Yeah. And then let's change this to
um ID here.
like this. And then we're going to add
let's add a message here. Note ID
required. So here we're going to add the
um
the S validation. I'm just going to copy
this.
Paste it here. We're going to paste it
two times. Here we're going to have the
one for um the PMS. Let me just add
comma here.
params here and JSON here. So I'm just
going to change this say note ID schema
and then note update schema
and then we need to pass in the uh get
user
and then async
and let's return this. Yeah, let's get
the uh C
and then let's set our try catch here
and then let's get the user is equals to
context do um get user
and then we can get the ID
from um
request dot
valids.
ID.
Let me duplicate this and change this to
JSON.
And then we can just set just get the
body here.
And I need to check the note. We need to
confirm if the note exist. So I say
existing
note is equals to await prisma.
Note
find first
where
ID is ID and the user ID
is user do ID.
Then below here we can check if uh if
not existing not
let's throw an error
SCP exception
for
message notes not found
like
And then let's update this.
So say constant update notes
updated not is equals to await
Christmas.not note
update
where um ID
then data
title is on body dot title
and content
body dot content
like this. So we can return this. We can
say return
C.JSON
success
true
and data is going to be equals to
updated not.
And here we can just get the error. So
if error
instance of um HTTP exception
error here
let's just throw 500 error
Um internal sorry HTTP
exception 500. So um message
internal server error.
So, we're done with this. Let me just
So, let's collapse this. We're going to
go ahead and work on delete um point
delete part of the note. So, let's So,
let's just u come over here and add dot.
Then we can set delete.
And this is going to be delete
slash
um ID.
And then we just say s
validator
params
and then we just pass in the notes
not id schema
then let's set get user here
we have async
and let's return this get the context
and let's get try catch here
and then below here we can get the user
user is equals to C do.get
user and then get the id
is equals to C do request
request of valid
params.
So we can just do the same thing we did
here. So I just copy this
and I'm going to just paste it here.
So if existing not just throw not found
then we can delete await prisma
do not
do delete
and then we can just pass in
here
and then pass in the ID.
So this should work. We can return.
Let's just return success here.
And then we can just say message
not deleted
like this. And then let's also get this.
So copy this and let's paste it here
too.
So that's it. So let's also work on the
end point to get all notes.
So I'm just going to say all
and then let's pass in get um all user.
So we don't need to pass in any uh any
parame.
So I'm just going to say
return this and let's get the context.
So let's get try catch here.
Then let's get the user is equals to
contest um get
user
and then we are going to pass in the uh
query. So what I'm going to do I'm just
going to get the query direct say query
is equals to c do request
dot query
like this. Now we can set page is equals
to query
dot page
is equals to
going to pass into the
query page
then
then we set this to one. So we can just
set this to like this is okay.
Set this to one. Then we can copy this
and paste it here and just change this
query limit.
So let's just say limit here
and then change this to limit and the
maximum limit here is 20.
So we need to define the skip here. It's
a constant
escape is equals to um page minus one
time limit.
Now we need to get the note.
We say equals to await promise
dot all
I will say Prisma
dot note
dot find menu
where
user ID is equals to user do ID
And we're going to do order by
updated at descending order.
Then we can pass in skip.
Sorry not we should use created that
and take
and limit.
Now we need to define Prisma
dot note dot count
user id user do id.
So now we can calculate the total pages
to get cost to math
do.
So
um total
sorry we didn't get the total here not
total
divided by limit.
So now let's return this. I can say
return
sj
success true
data notes
and then we can just say pageation
total
page
limits
total pages is
I skip
and then we need to copy this
and let me just paste it here.
So we can just console lock error.
So now we've gotten the uh all nodes. So
let's also implement the last endpoint
which is to get a single note. So I'm
just going to say slash ID
and there we just you're just going to
get the params here. So I'll copy that
and paste it here. So now let's um let
me just copy this here.
So yeah, we can have you try catch here.
Let's get user equals to context dot
uh
sorry context get user
and also the id.
So now we can get the notes note is
equals to await prisma
dot note
dot find first
id and then user id
is user dot id.
So if not not
then we can just throw
http
error exception
404
message
not found
like this.
So now let's return this
contest JSON
success true
and then data notes.
So, I'm just going to go up here and
let's copy this
like this. So, we are done with this. So
let's go back and check the uh okay
think if I hover over this now the route
we should be able to see bunch of um can
see the impute JSON this is for um the
create
we can see input and we can see the
output we can see for updates note we
can also see for orers so I'll just go
over to the RPC and let's see if this
will stop showing the error of unknown
and it does stop we can be able to See
this everything's connected together.
So um to make use of this we're going to
create uh a folder.
I'm going to call this futures.
So inside future I'm going to create use
not here.
So this is going to this way we're going
to use t query with um with the um hono
RPC to get the user um to connect with
the data with the endpoint. Yeah. So
we're going to make use of this API. So
instead of fetch or as we're going to be
using horn and then we're going to use
query to um together with it. So let me
go into use note and let's implement
this.
So let's u define constant. Let's export
this constant. So the first one we're
going to do is the create note. So I'm
going to call this use
note
and it's going to be equals to
empty string like this. So we're going
to return
use motation from create query and then
we're going to call this here.
So what we're going to do, we're going
to get a response
equals to await. Then we're going to
import API.
Sorry, not inside here. We need to
define the modation function first
like this. And then let's get JSON here.
And then like this. Let's import uh API
from our PC. Now if we click on dot, you
can see note. Then we can click on
create.
Then now we need to say dot
post.
So let's pass in the JSON here because
post require us to pass in the title and
then string here.
So now we can return await
response
JSON
like this. So this is giving us um
error because we've not define the
types. So how do we get the type? We can
use that from um Hanu. So we can just
call this response
uh sorry request
create not. So first of all get the um
the request first create not type. So
we're going to import interfere
request
from hono
and then we're going to call this type
of
API notes
dot create
post
and then we just define JSON here like
this. Then we can duplicate this and
instead of request
we are going to use response here
and then response I'm just going to
remove this here.
So let me import response
and then let me change this to instead
of request response.
So here we have the use notation we
going to define that here. So I'm just
going to open this like this. So first
we're going to we're going to define the
response here
error and then the request
like this and we can see the error as
stop.
Great. So inside the mutation after the
mutation function we can get the
unsuccess from answer react query
and then we can say note here
and then we can get error too. So I'll
duplicate this and I'll just call this
an error.
So if error
we can to
dot error
error
dot message
field to create notes
and then inside here we can also after
creating note we can call the all notes
endpoint. So we're going to use the tact
query the query client to invalidate the
note endpoint that's the all note
endpoint we're going to work on that. So
let's just do that. So what I'm going to
do is I'm going to do let's come over
here and let's do constant query client
is equals to use query client.
So now I'm just going to call this here
dot invalidate
queries
and then we can define the query keys.
I'll set this to not
then I can just set refresh type to all
like this. So for now we're going to
skip the note. We're going to come back
for that. So let's save this and then
let's uh let's go ahead and implement
the the second one. Let's go and get the
all notes here. So here we're going to
say export constant use
note
and then we're going to pass in the page
of type number.
This is going to have default of one and
then limit of type number
is going to have default of 20.
So now let's uh return
let's return use
query client. I'm sorry use query not
use query client.
So import that from
Let me import this.
And now we need to define the query key.
And since this is to fetch all notes and
we have note key here. So I'll just copy
this and just paste it here.
So when we create note, this is going to
recall the uh use note uh I mean the the
note endpoint the note endpoint. Yeah.
So yeah, we need to also pass in page
and limits.
So when this changes, this will record
this end point. So we need to also
define query function.
So async
now we say
response await
API
nodes.
dot get
so query.
So let's paste pass in page and limit.
So say constant
is equals to await response.json JSON
and let's just return
data. Yeah,
sorry.
Like this.
So we can also check if not response do
okay.
We can show an error or we can return
error. So let me just show an error
here.
To fetch not
like this. So this is it. So let's also
get the one for
let's also
and let's do for single note. Yeah. So I
just change this to not
sorry I'm going to just change this to
ID
of type string.
And then this I'm just going to change
this to
uh ID and single notes here.
So instead of or we can just change this
to uh
and let me remove This
sorry just return this mark. So instead
of dot I remove the dots here. So like
this and then we have um
instead of query we have params
and let's pass in the ID.
So now this will work.
So we can just also add below here
enabled.
You can say uh if id
this to run you can also change this
just use boolean instead
like this. So we can also define the
other one the last one for update. So
I'll just copy this
and then yeah I'll just duplicate this.
I'll change this to use update notes.
And then for use of the not we can also
define
the types here for update. So let me
just copy this and paste it here.
And then request update notes.
And then instead of create we're going
to change this to
um note
update.
Then we can just wrap this inside.
I can wrap this
and then pass in the ID
and also u the patch
like this. So let's also change these
two
uh response
updates
note type. Then we can just copy the
same thing we did here.
Let's come over here.
and paste it here.
So now we can just replay changes. Copy
this. Come over to where we have the and
just change it. So request will be here
and then up it. I mean response will be
here too.
So yeah, we're going to just change
this. Instead of create
we have um updates
update here and then ID
also um patch.
Now let's open this. We need to pass in
the params.
We pass in the ID. So we need to get the
u ID of the we need to pass in the ID
and we need to also pass in the JSON
here
like this. So now how do we get the ID?
We're going to pass the ID inside the
request. So what I'm going to I'm going
to copy this and I'm going to just
extend string here.
I'm going to say
this
uh like this. So inside here I'm just
going to open this and say id
and the error should stop.
So here we have done this already.
So let's also keep a toast here. To do
success
changes
save
and this is going to uh record the all
endpoints and then we can change this to
update.
So save that we have done everything. So
I'm just going to call this update
notes.
So that's it. So let's go ahead and
start working on the on the UI. So first
of all, I'm just going to go to where we
have let's implement the create note. So
to create a note, we need to go over to
the sidebar nav uh nav note. And
remember we had a plus icon here. This
is going to um open the dialogue the
create note dialogue and then this is
going to then inside the create note
dialog is where we're going to create
the note. So while here we're going to
list all the notes. So let's first of
all log in the end point to create notes
here in this option. So I'm just going
to come over here and let's define a
function for that. So let's call
constant on create
is equals to
Then we say uh let's import constant
use not sorry not use not use create not
we going to also
we're going to also get the um use
constant
use notes
and then we're going to say data not
then is pending
it's going to be uh let's say is pending
like this then inside the use create
note we're going to get mate
and it's pending
so let me just change this to is loading
Okay.
Then inside here, we're going to say
mate,
we're going to pass in the title.
I'm going to call this untitled
and the content is going to be an empty
string like this.
So now uh we're going to call this
method. Yeah. Here we have the cyber
group action. So I'm just going to say
on click.
We're passing the u on create method
here. So now we can also get all of the
notes here. So I'm just going to do that
now. So I'm going to scroll down here
where we have the all not. I'm just
going to remove this here.
So I'm going to check if not
length
is equals to zero.
Okay, this is saying
okay let me remove this. So I just come
down here and say constant not is equals
to data dot
dot data
empty array.
So if this is equals to zero then we can
just define a div here and just say no
not
then
you can have the else
is pending.
So it's pending is coming from use notes
and then we're going to
we're going to call it div here.
So you're going to have class
flex item center
justify center
and then we can have um loader
load five field
let's have the class name
width eight height It's animate spin
like this.
And then let's give this a test color of
primary.
And then below here, we're going to map
this. So I'm going say not
do map
notes.
So let's get is active
or is selected
id is equals to note
id.
That's your time.
Let's return this
sidebar
menu item.
So, I think I'm making a mistake here.
So I fix it. So I have to add this. This
was missing.
So
currently we don't have the note ID.
We're going to get another later. So
let's just pass this here.
A key
equals to not
do ID.
And let's get the side
bar menu
button.
And let's get let's set the class
name
um flex
item center
grateful.
And then we can say on click.
Let's just say for now we're just going
to leave this empty.
So it has span
last name
with eight
height it's
bg bg secondary
bonded uh large
and then flex item center
and then justify center like this and
inside here we're going to have the icon
from Remix
Remix icon. So I'm just going to get
file
text
view
and let's get the line
and let's say class name
with
for height for text primary
uh test primary like this
and then below here we can just have h5
device
and this is going to show the note dot
title.
So class name
flex one
truncate
like this. So we've done this. So we're
going to go ahead and um so we need to
add the loading. So I just remove this.
We have the loading here for creating.
So what we're going to do, we're going
to create a an overlay, a loader overlay
that once this is showing, we have we
create a new note and it's loading the
overlay will appear. So what I'm going
to do, I'm going to collapse this here
and I'm going to define the component
inside the component folder. So I'll
just come over here and let me create
that. I'll say loader
overlay
index cx
loader overlay.
So let me just
import that inside the sidebar note.
So let me just import this here.
So let's go into the uh overlay index.
And so let's define the props here. I'll
say type props.
We're going to have show boolean.
Then we're going to have text which is
optional to string.
And then we can define that here. We say
props. Let's just open this props.
We have show.
We have text. So I just set default to
creating not.
And then here if uh not true
then just return
no
like this. Then here we can just have a
div
a class name
X
to 0 PG background
let's give it opacity of 0.2 two then
backdrop
I'll change to extra small
Z index of 50
flex item center
justify center
like this
and we're going to have a div
and it's going to have a class name
of flex flex column
item center and then gap two.
So let's close this.
So inside here we're going to show the
loader here. We're going to import um
we're going to import the loader from
remix icon. Then below here we're going
to have a P tag
and this is going to show the text.
So just a class name
is going to be equals to text
small then text muted foreground
by this. So we are done. So I can go
back um inside the um I'll copy this
over back into the nav sorry nav note.
Then yeah we need to pass
um
pass show is going to be it's loading
like this. So there's no need to pass in
the text because we've already set
default to ging
not. So or we can just copy this and
just pass it.
So let me just pass it here
like this.
So now if I try to create now, let me
try and create a note. So let's make
sure everything is okay. So let's test
this out. So I'm just going to go back
to local 2000. Let's sign in again.
So, I'm going to sign in. So, let's
wait. I'll click on sign in.
And this should take me to the homepage.
So, now this is on the homepage. So, I'm
going to click here.
So, let me click here and then let me
click on this plus icon. And we can be
you can see the creating not here. And
then we can see the note is showing
here. So we need to be able to if you
click on this note we need to display a
dialogue. So let's go ahead and work on
the dialog. So to make the dialog um to
go or open and close we going to use
Nox. So remember we installed a package
here. This package
the Nox and again inside the layout we
wrap the entire layout with it. If I go
over to layout, no is um I think it's
inside the dashboard layout. Yeah, we
wrap this Nox adapter. So the Nox
adapter, the Nox is going to help us to
um add the values to the UR to the URL.
So it's just like a search program. So
it's going to enable us to quickly add
um the search like this view and also
remove it from the URL. So basically
that's what Max does. can just search it
up and see the documentation. So, so
like to implement the dialogue to show
um yeah, we're going to create a file
here.
So, first of all, let's go to the hook
and let's create the use
use not IDX.
So, this way we're going to handle the
Nox. We're going to create a hook that
holds the that add the um note ID to the
URL. So I'm going say use not
ID is equals to let's just return this
constant
note id
just going to say set
not ID
is equals to use query
states.
We're going to import that from
I'm going to import
use query
state.
So here we're going to define the name
note
id and then we're going to set the
default to string. So say pass
as string
dot. So let me import this
dot with default we set this to empty
string.
So now we need to define the method
here.
So below here let's say constant set
the note ID.
It's okay. Let's just set this to
underscore here.
And let's return
set not ID and pass in the ID. So we're
going to get the ID from here string.
So save that then duplicate this and
then we're going to say close ID or
clear ID I mean
clear not ID and then we can just set
this to null.
Let's remove the ID.
And then below here we can return
note ID.
Set
note ID.
Then clear
note ID. Then let's export this.
Export default.
Use note ID. So now we have this. So
let's um go into the component and let's
create the
let's create the not um overlay
or sorry note dialogue
and then inside I'm going to just say
not
dialog or I can just say index or let me
just dialog
txx here. So you just say E
notes
and dialogue
like this. So here we're going to um use
the sheet from sheet component from
Shant UI.
So inside here we're going to let's
import it as a constant
is equals to use not
ID and then we're going to get
um clear note ID and
set note ID
sorry note ID we're going to get note ID
and clear note ID then here we can just
say constant is open
is equals to boolean
not id like this. So here we can also
have constant
handle
handle close
is going to be equals to
note id.
So here we're going to we're going to
call the sheet component
from UI from URI sheet
and then here we're going to say open is
going to be equals to is open
and then on open change is going to be
handle close.
So now we need to import
the sheet content. And here we're going
to give this side to write.
And then we can have the class name
of padding zero. Um border
we can just say border left. Yeah. Uh
we should have width let's give it width
of 1 / two sorry 1 / two
then maximum width
we give this a 50
u vw like this.
So save this and then inside the um
inside the sheet contents we're going to
have sheets header
and then just say class name.
So is going to just have
padding Y
sorry P Y2
and we're just going to give this border
B and then BG muted
like this and then we're going to also
pass in let's add in the padding here
for then I'm just going to import sheet
title here.
So after the header, we're going to have
a div
and it's going to be a class name
x1
minimum height
20 maximum height
screen
and overflow
y auto
say if not ID
Then
we going to uh show the notes. We're
going to create a component called note
view
or you can call note editor.
So inside here we're going to pass in
the note ID
ID like this. So let's go ahead and
create that. I'm going to just create
that inside here. I'm just going to call
it note view
txx.
FC
and let's go back and import this here.
So, we're just going to pass in the note
view.
Oops.
Note ID
note ID type string
like this. And the error should stop.
So, just go back and let's save this.
So yeah, we're going to call the end
points for updating and getting a
single. So we're going to let's come
down here. Let's create a state
use state.
This is going to be of type string.
And then we're going to have the title
and set title.
duplicate this. We're going to have the
content
and set content
like this.
So yeah, we're going to have uh we're
going to get the data for to get a
single note. So what I'm going to do,
I'm just going to say constant
is this equals to use not. So we're
going to import this from
the future.
Sorry, it's use not not use not
the single one and then we need to pass
in the not ID.
So yeah, we're going to say data
is loading.
So let's check this. This is going to be
data data.
So you're going to also get the updating
the constant update notes
is equals to use
use update notes like this.
So let's just import this.
I'll just say um
mot
and then we can get the is pending.
So let me change this to is pending
like this.
So yeah, we're going to use a use effect
and we're going to check if not.
If not, we're going to set title
to note. Sorry, if data
we say data
dot data or let's just quickly just get
say not is equals to data dot data.
So I'll just use notes
not data
I mean not title. So let's duplicate
this set content
and let's pass set content and here it's
going to be content like this and here
we can just pass in the notes
and let me just import this use effect.
So now we have all of this. Now, we're
going to uh we're going to define the uh
leave here and the end uh the
text area. So, I'm going to be using a
different component for the test area.
So, we're just going to come over to the
search bar and search for
auto
uh auto size
area
shanty UI.
So, click on the first link here.
So once you click on this first link you
can see um this is this is a component
build to use chanting UI. So you can
copy the code here. So what I'm going to
do I'm just going to come over to my UI
sorry
UI and let's create a component. So
we're going to say
auto size
auto size test area
text areaX.
So let's just copy the code. Expand
this. Copy the whole code here. Paste it
here.
Now this is using this is using test
area.
So I'm just going to save this.
So that is it. So let's go back to the
code
um the notes view.
So below here we're going to set the div
here. I'm going to have a class name
relative
and then width full
height full
and then B6.
So let's just remove this here. And then
for this is loading. We going to come
down here and let's just set this to if
is loading.
We're going to return.
Let's return a div here.
And this is going to have the same load
that we had in the overlay. So, I'm just
going to go here. Just copy this.
paste it here. So let's import this.
So now we have the class name
flex item center justify center
weight full.
We'll give this a height of um 20 VH
like this.
So now let's complete it. We're going to
have a div here.
And this is going to have a class name
of widthful
adding left two
matching bottom three.
Then we have a div again. And inside
this div, we're going to have the uh the
auto size
text area.
So we're going to define a ref here.
So let me just comment this out first.
So value
is going to be title.
Then we're going to have unchange
is going to be a
set title
a target event.target target dot value.
There we have our placeholder
unit notes.
Let's have the class name
withful
resize
none.
It's going to say border none.
outline on.
We're going to also have PG transparent
font B.
And then we need to um set the styling
for the placeholder. Placeholder. We're
going to have text muted forground.
Let's give this opacity of 40 here. Then
we're going to make the text large 4 XL.
Then leading
line height to light
and then overflowing.
Let's set padding X0.
Then on focus
visible, we want to set ring to zero.
Then on focus again
visible
ring
offset
to zero.
like this.
Let's also have a class here
other B like this. So, um below here,
let me collapse this too.
We're going to have a div.
Let's going to have class name
with full and then padding left two.
So let me just copy this text area from
here.
Paste it here.
And then we're going to change this from
title to content.
And then this is going to be set
content. Copy this.
paste it here
and then we can change it to start
writing
like this. So yeah, we can also do this
outline BG. So we're going to remove the
font code
then the um placeholder text then font
size we're going to change this. Let's
just remove it.
And then let's change this to text base
instead.
Then instead of leading, we're going to
do relaxing
relax. And then I'm just going to remove
the overflow
and then padding X0
like this. So let's give this a minimum
height.
That's a minimum height
65
VH
like this. So this is going to be our
content area.
So then below here we're going to have a
div
last name
stick key
bottom zero ping Y2
let's
justify end
then set 50
BG background
and here it's going to have the button
You got to call the save changes
click.
Click
disabled
is updating
is pending.
If not not ID
not not content
sorry content
let's have the class name
of rounded
four
adding X
large
pointer
then disabled
opacity.
I'll give this 80 or 75 is okay.
Then we're going to set the size of the
button to large.
So say it's pending.
I show the loader here.
Let's import this class name.
is to wid seven
height seven
and image spin
like this. So I'm just going to point
this out. Let's go at the top and let's
fix the ref for both of them. So I'm
just going to scroll up here and then
I'm going to create a method to handle
uh update.
Let's just do that here. I just say
constant handle
update
is equals two.
So let's just copy this. Scroll down
back
and let me pass it here.
This will stop.
So inside here we're going to have
say
we're going to pass in the ID
not id
then JSON
title is two
content
content like this. So we need to also
check if not if there's no just return
like this and then the error should
stop. So now to define a ref we're going
to come let's come at the top here and
let's define the ref here we say
constant
is equals to title
title ref
area ref
is equals to
use F.
So, import that from React.
And then this is going to just have a
type. Let's set this to north.
We're going to import auto
auto size
text
area refer.
So just duplicate this and let's have
for content
like this. So we can copy this
constraint here
and let's just paste it here.
Let's also copy the content test area
ref.
And then let's come down here too
and paste it here.
So now we need to use effect to set once
the user open the dialogue we need to
set this to focus. So, I'm going to use
a use effect. So, I'm just going to come
down here and let's say use effects.
Let's remove all of this.
And I'm going to say if
if um if not um it's loading.
Let me check.
Okay.
If not loading
then we can say constant
I2
text
area
element
is equals to
title text area ref
current.
We say if
title
elements
then we can say test area ref
text area sorry just sorry not test area
test area elements
do text area
sty
minimum height
You can just set this to auto.
Then we can just copy
um this.
And then let's set this to
dot dot text area
focus.
Let me let me duplicate this and set
maximum height
to auto like this. So I'm just going to
pass in it's loading here.
like this.
So now we going to also have u
a div we're going to define on key down
for the title. Once you click on enter
this is going to
shift the focus to the content. So I'm
just going to do that here.
I say constant handle
by two key down.
So yeah, we're going to say a is of type
re.
Sorry. Y dot keyboard event
HTML
text area
element.
So we say if
event key is equals to enter
then we say it does prevent default
then we can get the ref from for the
content.
Now just say content text area current
text area
focus
like this. So just copy this
come over to here and let's just pass in
on key down
and pass this here. So now we're done
with this. Let's just copy the uh the
nav dialog. So copy this. Let's come
over to that for layout and let me just
uh for the notes
dialog component.
Let's import it.
this. So we need to go over to the side
by again and let's
let's update this the notes
and there we can get the uh let me just
say constant
use use
not
ID.
So we can just get the note ID
and also the set note ID. So we're just
going to also come back here and let's
just
unc comment this
and then we can say it's active
active like this.
And then for the set not you're going to
let's just define a method say on click
is going to be
set not ID. Let's just pass in ID here.
And let me just pass in ID. So just copy
this. Scroll down to where we had the on
click.
And then I'm just going to say on click
and then let's pass in notes do ID
like this. So let's copy this and let's
um go over to features use note
features. Scroll down to where we have
and create note and then here we can
just import this.
So I'm just going to say set note here.
So I'm just going to um
import this. Then below here, copy this
and then we can get the notes. Yeah,
just say not
as a constant or let me just change this
to response.
Constant note ID is going to be equals
to response dot data
dot um ID
like this.
And then we can set
note ID
like this. So we done with this one. Now
we can test it out and see if this work.
So let's go back to
local host home
and let's try and click button here and
see if the dialog is going to open.
So use effect
note view. So let's go back to note
view.
So let me try and reload this again.
Why is it failing? So I set use client
already. Yeah,
this should compile.
So let me just cancel this and then run
mpm rundev again.
So let me load.
So I'll also set this to use client too.
So I've connected back. So let me just
close this and then let me click on
this. Click on the notes
and this has open.
So let's check. I think I say this to
small. I say to um
one / two. So I think let me also set
maximum width
um
or let's just set to
1 / 2
is for last screen.
Um let's just say large screen
then for medium we can have with let's
say with four let's see
this cover everything. So we can click
here to cancel and this will close
like this.
This is okay. So for the heading I want
to move the
um let me see I can say show close
sorry
show um close
let me just
let me just create this component
I I think
this
this should be close. Should close
it. I wanted to hide the close then
display it inside the header. But this
is fine. You can have the close like
this. So I think setting width to full
for
we can just make it n / 12
one like this I think the is okay so
that is it
and we can write let's change the title
say new note
AI notes
content
and let's click on save
changes.
So this has changed and we can see this
has changed. So let me go back to the
button. The button didn't change.
say.
So this is fine. So the next thing we're
going to do is we're going to go uh
implement the recent notes.
So let's just close this,
go over to the route, go over to
dashboard, and then we have um so inside
the main session, we have the recent
note. So I'm just going to create a file
here. I'm going to say recent
note
tx
a fce
recent
notes.
So let me just copy this. Come over to
the main section.
Let me just replace paste this here. So
import it.
and let's go into um recent notes. First
we're going to import we're going to
import the let's just set this first to
use client
and then let's import the use note ID
and then we can get the note
it's going to be close to use not
and I'm going to set the limit to say u
page one then limit or set this to eight
you can leave it to five if you want so
I just set data
is pending
I'll just set this to loading here
and here we can just get on create
some rotate
is spending
use create notes going to also import
that too. So we can have also the same
thing we have constants
on create
it's going to be equals to
method
title
on title
content empty string
like this. And then here we're going to
have on click just similar to what we
did before in the sidebar.
We're going to pass in the ID here
string
set not ID ID
and then we can just say div
last name
waitful
margin of 1.5
and there we can just list the notes
You say uh
list
name
flex w
minimum width zero.
So flex column 4
and gap
two.
So here we're going to check if the user
let's check sorry if loading
um
if loading then let's create a div first
class last name
let's it center
justify center
and then let's import the um the um icon
Um
loader
loader file field.
We have class name
width 10
height 10
animate spin
then text priming.
So I screw this up. So yeah, we're going
to say else if not
get the notes here. Constant not
is equals to data
dot data
empty string.
So if not length
uh is equals to zero
then we can just set a if for now we're
going to create an empty state for this
and I'm just going to say else
dot
map
Let's
return.
Yeah. Let's pass in the key.
It's going to be not id dot id.
Then class name
is going to be we're going to define
relative here.
So yeah, we can have the button. So the
button is going to if you click you're
going to open the um note dialogue. So
I'm going to say flex
dot weightful
dot item
uh center
dotgap
2
py1
dot text small
dot dark
sorry dot dark I'll just Open it like
this.
Then we say that and text
wides
80.
And then we have text left.
Then hover
ascent
rounded
sorry rounded small.
So this should be button not div.
And then let me ask the on click here.
It's going to be
on click
and let's pass in the notes do ID
like this. So flex with with full item
center gap to ey1 text small dark mode
we have text white percentage I mean 0.8
opacity 0.8 text left over bg as center
and
rounded small. So inside here we have
span
we have class name width 8 height 8
is secondary
bonded
rounded large
flex it center
justify Enter.
So inside here we just have the loader.
So I'm just going to copy this. Paste it
here.
The loader I mean the icon text the note
icon by text
by text line. So I'm going to change
this to four.
And let's remove the aminate pin
and dark mode. So I think this is okay
like this light dark mode has a text
primary. So lastly you can come below
here and there's a H5
and then this will just have the not
title.
So we have class name
one and truncate
like this.
So if this is pending
okay
we're going to go ahead and create the
component for empty state. So let's go
into the component and let me just
create a folder. I'll call this empty
state
index
xx
c
empty state
like this. So yeah, I'm going to set the
props here. Type props
is going to be equals to title string.
Then we can have description if you
want.
This will be optional string.
And then we have the icon
which is optional
and this is going to be a remix
um icon component type.
Then we can have the icon name.
This can be optional too.
Then we have the button text.
This can be optional to string.
Then we have on on button click
optional.
So now we have this. So let me just copy
this
and then we can just say FC let's import
this
and just pass it here
and then we can get title
description
icon
to this capt icon. here capital um I
we're going to set default to
um I by
text
line
I remove this
and then we can say button text
default we can just say create
then we I have the other ones here. The
icon, class name, the button, sorry, the
on button link.
So yeah, let's have class name
text center.
that we can have the icon
class name.
Um, let's because we're passing a a
class here, I'm just going to just use
CN. So, import CN from UTS.
And there I'm just going to pass
with 16.
height 16.
Then text
muted forground
MXO
MB.
So we can pass in the icon class name
here.
So below here we can have H3
and this will have a class name of text
large
font medium.
So I'm just going to set the default
value for this to nothing or empty
nothing.
Um nothing.
Nothing here like this.
Oh, no record.
No record. So, let's pass in the title
here.
So let's also add um matching bottom
three.
So we have the description.
Let's add a class name.
So this going to be text muted program
MBC
and like this.
So this one
um let's just add a default here.
uh create something.
What I just let me just if no uh
description
just like this. So I'm just going to
remove it.
So the last one is the button say on
button.
If there's un
then I show the button here.
on click
on button. Click
last name.
We have a plus
pointer
and there we can just pass. Let's pass
in the U
button text
like this. So here we need to also add
um button loading
or you say loading.
It's loading.
boolean.
Let's just get this loading.
And then here we can just set this to
disabled.
Uh it's loading.
And here let's put an icon of um plus
say um add
uh add line.
Then here we say if if um if is loading
let me just import this.
Let's have class name
width five height five
and let's give this margin right one.
like this. So, we can make use of this
now. So, I just copy this,
go straight into the recent note,
and then yeah, I'm just going to just
import it here.
So, let me just import this.
So, yeah, we're going to see it's
loading.
Um, it's pending.
Then f2
you can just say create
and then on
button.
So I'm going to change this. Let's set
on button first
on create.
Let's just say no not
created or no not yet.
Then we can set the icon. Let's set the
icon class. We can give this um width it
and height it here
like this.
Then I think um we gave this an icon
here. So I'm just going to click here.
We give this an icon. Default icon here.
I think that is it. So let's check it
out.
So we have the not here. Let me scroll
down
inside the recent note.
I think your text is open.
It flex it center.
So let me just add I don't know why this
is on the top we added flex with it
center
um
and this
so let's uh let me say padding
margin top one let's see
So I think it's showing. So if I click
on this, this should open the dialog and
we can see this
save changes.
This is reloading. This is not
refreshing.
So I think that is it for the notes. I'm
able to create a note now and not
recreate. So I'm testing it out again.
So the next thing we're going to go
ahead and create, we're going to work on
the um chart. So I'll clear everything
in my
my editor. So let's go ahead and then
work on the um chat
chat endpoint.
In this session, we're going to look at
a SDK from vis. So just come over to
search for AIDK and then you go over to
a-sdk.dev.
So let's click on get started. So inside
the AI SDK you can quickly look at some
overview example here and you will see
how to integrate AI into your
application very very simple and quick
and this is how to um integrate um AI
into instead of using the open AI or GR
or cloud API directly in your app you
can use the key which gives you variety
of options to and makes things super
easy. So we have different model and the
ak has different model package created
for different model like now we can see
ak for gro we have ak package for open
ai we have for entropic we have for
google and you also have for custom for
like local local model and stuff like
that. So we can take this and just run
this and this is going to output the
response. So, I'm going to be using
Google to try out these examples because
Google is free. So, to get the uh Google
um API key, just search for just go over
to AI Studio Google. Just search this on
Google AI.google.com.
Once you come over here, just click on
the get API key. And once you click on
that, it's going to take you to this
page. Then here, just click on create
API key. And then you can select um you
can select a project and then click on
generate API key. So I've already
generated the API key. Just do the same
thing here. And once you get the API
key, we're going to paste it in the EMV.
We're going to create a new project, a
new um a new uh project we're going to
make use of to test this AIDS. So before
we go ahead and do that, let's just
quickly go and look at how to use AI. So
if you scroll down here you can see um
we have different let me scroll down to
where we have the next JS you can look
at you can use nextJS or different um
framework libraries then we have the
exec if I click on overview here you see
the same thing here if I scroll down to
generate text so we have different type
of um we have different type of output
where we use the sock provide generate
stream text and also generate object and
stream object. So generate we look at
the generate text and then we have you
can pass in the system prompt and the
user prompt and this is how to get the
output. So I'm going to also show you we
have what we call the stream text. The
stream text streams the output and this
is how to get the output from the AI ZQS
result. So we also have um these
are some objects some things you can add
and get from the uh stream text. We have
the on chunk unfinish and stuff like
that. So I want to show you
um the object. So I'm just going to
scroll down here. Okay. Yeah, we can see
generate structural data. So generate
structure data. We can see we can
generate object and this is using you
have to provide the schema. We using Z
you can use Z to define the schema and
um we also have stream object
you can stream the object. So so
basically that is the only part of
things I'm going to show you in this.
The last one is the two calling. So the
two calling you scroll down to two
calling with you can integrate to right
inside your application. So your chat
app with this we can just define two and
just give it um this impute schema you
can use s to define that then execute
inside the execute you can call anything
whether you database or anal API and the
AI will decide when to use the tool to
call the tool. So basically that is how
to use it. So we can scroll down. Okay.
Yeah, we also have um stop when. So we
stop when this define when to tell the
AI agent the AI to stop after a
particular. So by default um the
generate text or the stream text make
the call only once stop only once one
call. So since we're using uh if we're
using two we want the agent to call
multiple times. So when it calls the two
it will send response back to the LLM
and then the LM give us the output. So
we want to define the step stop when so
this will give you the maximum out the
maximum step. So we're going to you can
set five three any one you want but yeah
this example we showing five.
So then you can get the step out if you
want. So that is it. Um also support
embeddings, image generation, trans
transcription, script, speech and
others. Here is an example and we also
have thek UI and this is what we're
going to use in the UI user interface
when we are when we when we implement
the endpoint. So if you click on chat
boot here you will see how to just
implement the chat boot using the um
so yeah this is the back end while also
provide a use chat hook and with the use
chat hook you can just integrate it
together with the
for your back end the stream text and
this will implement the this will just
give you a simple chat port application.
We have this uh we have the two usage
here. We have others. So I'll just go
down to um
call. You can just scroll down to where
we have reference call and you can look
at all all what they have here and also
the UI. You can see all of the method
and everything and the hooks here. Then
we also have AI AI gateway. So with AI
AI gateway instead of using instead of
providing your own um let's go over to
generate text.
Let's come over to overview. So instead
of you to provide your own um API key
for GR open Google and I have to install
all of this package with uh let me open
this with it's AI gateway you can just
use one package one package and just use
one package just install
let's come over here okay you can see
that just have um the open AI then you
can just define the u AI gateway API key
with this you can use many uh model with
just one API key and this is what Vio
has offer here and we are going to make
use of this in this project. Then the
last one I'm going to show you before we
go ahead and test this out is what we
call the AI element. The AI element
they see has given us AI elements we are
going to use in this project. You can
see um this is how to use can you can
look at the input um just similar to how
chart DBT is. You can see actions. We
can see um artifacts here.
You can see the artifact. We can see
branches.
We have um chain chain of thoughts. We
have code block. We have um we have uh
conversation. You can see the
conversation here. images, loader
messages and also the prompt impute. We
have the reasoning.
You can see that we have response,
we have suggestion tax and then we have
to call to also the web view. Basically,
we're going to go over this when we
start implementing the front end. So,
let's just go ahead and test the
example. So, I'm just going to go over
to let's go back
to the SK and let's go ahead and then
test this. Make sure you've copied the
API key and then let's go back to let's
go to the code.
So, in this example here, I'm just going
to show you how we going to test this
out. So now in this this simple example
in my package addressing I installed the
AIK Google the AI from VCIK.
MV and Z
and then enter the example here. It's
just the generate text. So I'm just
going to test it. So ask question and
then I've given the generate text from
AI SDK and then the model I'm using
Google from AIDK Google and then this is
the model. This example is what we saw
in the documentation. And then I'm just
going to pass the prompt. Then let's
test this out. So I'm just going to
clear my terminal.
And then I mean node
index.jx.
And if I click on enter, this is going
to run this and we should be able to see
the response now.
And then you can see it has given us the
output here. You can say ask what is lm
and then it has given us a breakdown of
what is l&M here.
So now I'm just going to change this
from generate text to stream text. So
let me just change this. So can change
this to stream text.
And then let's change the import to
stream text.
And then here what I'm going to do I'm
going to allow us to pass the model
here. And let me change this to Google
Google model. So you can also just pass
multiple different type of model just
passing Google model here
by this then now once we output this
this is going to give us text and then
we can also get so let me just sorry
we're going to get the text so we have
the full stream we have the text stream
so it's going to give us the full and
the final text while this is going to
give us the stream so Here, I'm just
going to paste this here. So, this is
going to be for our weight constant text
of text stream. Then, we're going to
output that to the um we're going to
output that. Then, to get the final
text, if you don't want to show the
stream the streaming, we can just await
the text like this. So, I'm going to
save this and let's run this now. So,
I'm going to clear my terminal.
I'm going to run this now. Let's see.
This is going to stream the test. You
can see that this is streaming the text
right in the the terminal.
How great is that? So now we've seen
example of how to use generate text and
also the streaming of text here. So
let's go ahead and test out the generate
object and stream object. So for the
generate object, I've pasted the example
I'm going to use. So let's go through
the example. The example is I'm going to
import the same thing we import and then
this is the model here. Then let's just
collapse it for now. So here we're going
to just have generate generate recipe
I'm going to pass the dish here. Then
instead of here we have instead of
generate text this is going to be
generate object and we're going to get
the object from the output here. Then
we'll pass in the model. Now here we
pass in the system prompt we have
recipe generator always output JSON with
recipe details here. So, and then I'm
also giving it the um prompt. I'm also
passing the user I'm giving it um give
me a recipe for and then this is the
user imput. And then we need to pass in
the schema. We saw that in the example
of generate structural data. Then since
we're going to be using Z, we can define
the title, the ingredients, the step and
the cooking time. So just collapse this
now. Then we can return the object. And
if I run this now, let's clear the
terminal.
And this is going to generate the output
in JSON. And then we can sit in object.
I mean, you can see that it's giving us
the title, ingredient, the steps, and
then the cooking time.
So we're going to look at convert this
to stream object. So let me just change
this to stream.
Stream object here. Then I'm going to
just remove this
and I'm going to say stream is and then
here I'm just going to just paste this.
We're going to use the four constant
pass stream dot partial object stream.
So we're going to get this. Now I'm
going to just console the part and then
let me just remove this console here.
I'll just return like this. Now if I try
to run this now, so let's close the
terminal and then let's run node
index.jx.
Sorry,
it say stream. Okay, sorry we made a
mistake here. Stream.
So let's run this now.
I still complain. Okay, we didn't import
stream object.
So node index.jx X and then you can see
how it is is I think it's having object
is not defined
I think I made a mistake
stream text
but let's just remove this here
and let's remove the response there and
this should work
this should not show any error again we
can see the output here
object. So, we've seen um we've seen
generate object and stream object. Now,
I'm going to change this example. I'm
just going to remove it. Don't worry,
I'm going to put all of this in the
GitHub, too. So, I'm going to remove
this and I'm going to paste this example
here. So, this is a simple just to show
you system prompt. This is a simple
summarizer. Then I pass in the model. We
have the system. We have you are heavy
assistant that summarize test clearly
and very concisely. We have prompts. We
have input. We pass in the input then we
return the text. Now this is an an
example here. We have the summarizer. We
have the um I've given this a text for
this to respond. So I'm just going to
clear my terminal.
Let me save first.
And now if I run this this is going to
summarize the text for us. And now you
can see this has summarized the text I
pass for us because we've defined the
system prompt here. So we have
additional different way to uh set both
of this. We have what we call the
message and here I'm just going to um
copy that here and then I'm going to
remove this.
So inside the message we have um this is
called the model message. Inside the
message we have the row. So I'm just
going to say row and here we have system
assistant to and user. So I'll set
assistant and then we have the content
and the content we can define that here
we can say row
user
content it's going to be the input.
So I'm just going to um paste this. So
now I've pasted it here. If I just run
this let's look at it. So instead of the
prompt and um the
system we can just define this and this
will work. So I'm just going to run this
again
and this should summarize the text for
us. So this is working. So we done with
this now. So let's go. So let's test out
um preserving the chat history. So
preserving the history of the chat.
Let's assume this is a chat application.
We want to keep the history. So, we're
going to make an array of the messages
at the top here. So, I'm just going to
quickly paste all of this here. So, I'm
just going to remove them. Place this
here. So, I'm going to explain
everything. So, we can look at here. We
have messages here. This is an array of
messages. So, and this messages has a
type of model message. If you if you
check it out on the documentation, you
will see this has the rules.
Let's just quickly see that. So I'm
going to change this to TypeScript here
and then let me just import this.
So let's import this now.
So I just say type
and then if I hover this now you can you
can see um let's let's go into the
package then inside the model message
you can see system model message user
model message assistant model message
and two model message if I go into
system you can see row system content
string we have v tools content and then
we have row user and that is it. So let
me just change this back.
I change this back to JX
and let me remove the type.
So now below here we have chat um chat
recipe assistance
and then we have we push the user input
here as you just put it inside this
image inside this messages array. Then
we pass the entire chat chat history
inside the message. Then once the AI
responded, we push this inside the array
and then we return the message. Now we
can we can test this out. So I'm just
going to run this. So let me save this
first.
Let's run this.
So I just say response. This is not AI.
This is a messages.
So let's run this. And then this is
going to give us the output. Now if you
look at it, we can see um the row, we
can see uh the user and then we can see
the assistant response here. Cool, man.
So now we've looked at how to preserve,
we've looked at chat history,
messages history. Then we've seen how to
chat with and create a simple chat
recipe assistance.
And then we've seen um generate text
stream text generate object stream
object. Now let's look at the last part
which is the two colon. So I'm going to
paste the example. So let me just clear
all of this and let me paste it here. So
this is a very simple example.
This is similar to what we saw in the
documentation.
So I've import everything like this the
model here. Then we have tools.
So this is a very simple function that
just uh simulates like a weather lookup.
So we have the get weather. Then we
define the description which is show the
weather in a given city to the user. We
have the impute schema. Then this is
going to be the impute. We specify only
one thing which is a city. Then execute
is where we we run whether it's database
call or API. So for example, I'm just
going to just return a text with the
city pass inside the text. Now this is
the method. We have the generate text.
Now we have the system prompt you have
assistance that use tools when needed.
Pass in the user prompt. Then we define
the two. So here we can just uh let's
output a step and then we return the
result text. Now this is an example. I'm
asking what is the weather in New York?
So I'm just going to run this now. So
let me save this and let me clear
let's clear
this and then let me run this and this
is going to give us the output. So
currently, sorry, let me just comment
this out first.
And if I run this, this is not going to
give us any output
and you can see. So the reason is
because remember we mentioned this in
the I showed you stop when in the
documentation. So if I output the steps
and I run this now,
you should see that this has only one
step which is the two call. So it has
called it two but it has not yet
finished. It has not yet given out a
response. So that's the reason why we
don't have any output here. So we need
to tell the AI agent or the AI to run to
give it the maximum amount of steps. So
I'm just going to say stop when. So by
default this is going to just run it
once. So I'm going to say stop when then
we're going to say stop count. Let's
import stop count
from let me import that. So not stop
count step count
and then I'm just going to give it three
three. So it's going to run maximum of
three times. So it will give the AI time
to run the tool, get back a response
from the tool and then generate the
output. So if I run this now, let me
just comment this out or let's leave it
here. So I'm just going to clear my
terminal
and do a node index
and then we should see the output here.
Weather in New York is sunny 25°.
Then if you come over here now and let's
see the the um output the first step we
call the two. So it calls the two. Then
if you scroll down here you can see the
body the request.
Then if you come down here we see
another default step two again step
result. This is the content. So it has
finished calling. Then you can see um
the body
like this here and then this is the um
response. So so it called it two times
here. So after I stop calling it after I
stop the step then it gave us the output
here. So basically that is it for this
for this example. So now you can
increase the step counts can increase
the stop when five or whatever you want
you want the um the maximum amount of um
call you want the AI train to to call.
So so basically that is it for this
part. So let's go ahead and start
implementing the chat API. Before we go
ahead and start implementing the chat
API. So let's first of get the API key
for the AI key because this is what
we're going to be using. So make sure
you lo into your vis and then go over to
dashboard. So if I click on dashboard
now this is going to take me to my
dashboard page and then I'm going to go
to um AI. So just click on AI gateway.
And now we can see um here you can get
the API you can get the uh API key by
clicking on the create and then if you
look at the example they have many AI
model. So to see all the AI model for
inside the gate AI gateway. So I'm going
to just click on many more and then
let's click on this to see all this. So
let me just open this in new tab
and then if you scroll down you can see
all of the models provided inside in the
AI gateway and you can see all of your
model here.
So they have so many models here. So I'm
just going to pick some of them in this
project and their input token cost here.
You can see them here. So uh um let's
just and then we can see the charts
models filter by images
generation embeddings go embend open
area appendance and then oh then I'll
just close this. So to uh by default you
should see five credits here. So uh this
will give you five credits which you can
use it to try and test. So, I bought
some credit here. And if you click here
to com buy, you can see you can type any
amount like custom can buy $10 worth of
credit. You can buy 20,50 and so on and
so forth. So, I already have some
credits here and then just click on this
create API key and then click on create
and then type in the val. So, I've
already done that. Just type in the
values here and just click on create.
Then once you do that just copy the key
then uh let me go back quick start go to
quick start then you can see how to add
it. So just add this like this inside
the EMV and paste your API key here. So
just copy this and then that is it
and then and this how to use it. So
let's just go back to the code to our
project and then inside the project here
I'm going to let's click on let me click
on EMV example
and I'm going to show you. So for the
Google because the AI get API key has
little credits and we don't want to
exhaust all the credits. So we're going
to be testing we're going to be testing
with the Google API key instead. So once
we deploy we can switch we test it
before we deploy with the AI gateway API
but as as long as we're building we
going to be using the Google generate
API key to um to test out and to do the
build processes. Then then once we
deploy before we deploy we test the AI
gateway API key and deploy with the AI
gateway API key. So make sure the Google
API key you got from AI studio Google AI
Google studio just make sure you paste
it here and then also the AI to API key.
Make sure you paste it here. So I've
already pasted. So I'll just close this.
And then let's just go into the app and
then the API and then going to route.
And then let me just say chattx
here.
So yeah, I'm just going to quickly just
come over here and just copy this
export.
Paste it here.
So let me change this to chat.
And then let me go into route.
And then we're going to just paste it
here.
sorry dot routes
/ chats and then we just import the chat
routes
and the error should stop. So let me
just go back to
the chat route.
Then the first thing we're going to do
is to get the uh schema.
So let me just define that at the top
here. So I say constant chart schema.
This is for the um the imped body. So
it's going to be equals to s do okay. So
let me import sobject
and then we are going to pass in the id
of the chat. So I'm going to explain
that later on why we are passing the ID
of the chart here from the client from
the server side component instead of
generating the chart from the back end.
So the reason why I'm doing that is
because we don't want to block the
streaming from the user. So we don't
want situation where we have to create
the chart then add the message. So we
have to get generate the ID from the
front end side. We're going to just look
at that later on. So I'm going to just
say minimum to one and then
we want the message. So we're going to
get a message. Remember we're going to
be using AI SDK and use chat. So this is
going to return this going to send the
message to the back end. And that
message we can say custom
and this is going to have the type of
what we call UI message.
Sorry, let me just
let me import that from AIK. Yeah,
import
from
AI.
So, I didn't we've not installed AI yet.
So, let me just cancel this and let's
install this mpm install. So, let me
give you the version. So, I've pasted it
here. So, we have npm install AI 5.0.23
at AI exe Google 2.0. 0.11.
Then we're also going to install the SDK
for react. So this is for the client
side where we get the use chat hook. So
I'm going to click on enter and this
should install the packages for us. So
here we're just going to get a type of
UI message. So let's wait for this to
install then we can go ahead and
continue.
So this has installed now. Let me just
run the server and then then the error
should stop. So I'm just going to pass
the UI message here
like this. So UI message you can see
it's just similar to um the model
message but this is for the UI. So the
UI is going to be shaped in a different
way from the client side and then we're
going to convert it to the model
message. So if I go into the UI message
now you just see how it we have the ID
row metadata then we have the part you
can see we have parts in the um in the
UI message and the part will contain the
uh we have the text part which is a text
text string state and then we have the
reasoning part we have the type reason
type string state we have source we have
variety part so this is going to be
passed to the back end then we convert
that into a model message we're going to
see
So here I'm just going to also pass in
selected
model ID
to set string
and then we can just say as set
Z sip
and chart model
sorry charts model
okay we've now defined the chat model
yet.
So let me just remove this for now.
We're going to add the type later. Let
me just go ahead and implement that. So
we're going to implement that inside L
folder. We're going to list out all of
the model we're going to use. So I'm
just going to create a folder called AI
and I'm going to say models.tx
here. So yeah, I'm just going to say
interface,
sorry interface.
And this is going to let's export this
uh interface chats model.
We're going to have the ID of string.
We're going to have the name of the
model. We're going to use this in the
client side. when we are when we um
setting the mod drop down to select any
type of model. So I'm going to just add
description. This is optional. Just give
it a string.
And then I'm going to say export
constants chart model
and this going to be charts model.
So I'm just going to paste that here. So
I've pasted it. Now you can just get it
from the documentation. We saw the
models in the AI SDK. I mean the AI
gateway. So we have the uh entropic
plot. I'm using four because because of
the cost. You can see the token imp. So
I just want to use four. You can change
this to the latest version. We have
group four. We have open I4. We can
change this to open 5. And we can test
that. So I have some tokens. I have some
quantity
5 here. And then we have um Google
Gemini 2.5.
So this is it. Now I'm going to set a
default model ID. So I'm just going to
and then I'm going to also define the um
Gemini AI. Remember we said we're going
to use the Gemini AI to test. So instead
of using the uh AI gateway model, we're
going to use GI, but we're going to
define all of them inside a single
object. So I'm just going to just paste
this here. So now we have default model
ID. This is going to just be the first
one we're going to pick. This one is
going to show by default when the user
land on the on the page on the prompt
input. You will see um the blog blog
will be the first shown there. So we
have the so I'm just going to use the
development chart model and this is
going to be um the Google model. So you
see this is different from the way we
define um the AI gateway. So the a
specify the the brand which is the
platform entropic
uh grow open AI but if you define your
model directly with the model package
installed remember we installed the
Google uh if let me come to package or
JSON
if I scroll down we can see we installed
a Google. So with this we need to define
the model of Google and then the model
here and here I just um export model
option. So I just define this. So this
what I'm going to be using on the client
side. So once you So now after we do
this now we can we can go over to the
chart and let me just import this
and the error should stop. So we still
also need to define the provider in the
remember we're going to specify the
model in the string text. So let's
quickly do that. I'm just going to
remove this. Then inside here um to
define the model we can't use the array.
We can just get the data from the array
and format in a way we can provide the
model ID. Like here if I go over to the
chart tx remember we are passing the
selected model ID. So with that we can
get the id the particular model from the
list
from the uh chat model list. So we can
just divide that. Let's just create a
file called providers.tx
TX here and then inside here we just say
export. So let's say sorry not export
constant let's create
sorry export constants my provider
or can call it provider and then we can
define custom
custom provider. So why do we need it?
because we want to be able to add both
the want to combine the AI SDK
and the AI SDK sorry the AI gateway
model and then the the um the Google
model combine inside the provider. So
we're going to create a custom because
we have different type I want to set if
it's production use this model if is
development use this model. So what I'm
going to do is here I'm just going to
pass in an object here and here you need
to pass in the language model. So what
I'm going to do I'm going to define a
method. I'll call this create language
language
model
and this is going to be equals to
constant. We going to loop through the
models we define the chat models we
define inside the models f here. So I'm
just going to say constant models
as a record
string any
to object here. So now let's import
chart models
for each
model.
So now I'll just open this. I'll just
say models which is what we define at
the top. Now I'm going to say model id
is going to be equals to now we need to
get you need to install the ais gateway
you know we are we are trying to create
a custom provider so we need to define
the gateway um the gateway so this will
differentiate the different model you
can if you're using the Google uh the
Google package we can just say we can
say from the Google package we can say
google dot language mod. So now instead
of that for the AI for the AI gateway we
can say gateway
dot language model. So the reason why
we're doing this is because we are
setting a custom provider here. And if
you just want to use only you don't need
to do all of this. You can just quickly
just pass in the um selected ID directly
to the model. You understand? But since
I want to modify this to match with um
any model you added there in this list,
I'll just define that inside the
provider. So let me just install this
here. So I'm going to cancel my terminal
and let's install the um AI
AI gateway.
So I've pasted it here. So make sure you
install 1.0.23.
So AI SDK/ Gway at 1.0.23. Just install
that. So I've already done that already.
So I'm just going to test it out here.
So let's say gateway.
So let me import that here. I just
import
uh from
at gateway
gateway here. So I'm just going to say
gateway
dot language model
the model do ID. So with this if the if
we pass in the uh if we get the provider
my provider we just do my provider dot
um and just paste in the we pass in the
ID and this is going to get the so just
copy this just paste it here
like this and let me just import this
here
so let me just cancel this
let me save for the entire file then
let's return
models
and the error should stop. So we have
done for the uh the chat models. Now I
want to also append add the development
chat model. So with this we can just
point and just get the development chat
model here. Just a chat model ID or
something like that. So I'm just going
to add it here. So I'll just add modules
here.
So instead of me adding it inside the
model I just want to add it inside the
provider here so to differentiate both
of them. So let me just import these two
and this now we need to import Google.
So let's import Google.
Now we can say Google
language model.
And then let's just pass in development
chat model.
Now we need to because we're going to
also generate the chat to we sending
create a new chart then the user send
the first message from the message we
can determine the name of the just like
work. So I'm going to also define chat
model here um
like this. So let's just set a title. We
say title
model
is going to be equals to we can use the
Google model here
for the title or if you don't want to
use the Google mod let's say we only
putting the AI gateway API key directly
on the production we can we can set um
we can pass in is um is production then
define that yeah
um should we do
I say is okay let's just get the can say
EMV
um is
node
node sorry
node env if it's equals to process
env
dot node env.
So this going to be development or
production.
So I just say constant is production
is equals to this equals to
broad.
So it's going to be of type boolean. So
we can copy this and then we can pass it
inside here if you want. I'll just pass
it here to say um boolean
and then we can say if is production
then we can use the gateway model
and then instead of this we can just
pick uh let's just pick anything let's
say Google AI here and just paste it
here like this. So, uh, we going to be
using the AIDS directly in production.
So, we're going to save. Sorry, I made a
mistake. Uh, this is not it. This, uh,
I've made a mistake.
So, let me copy this or cut this out.
It's supposed to be here.
So, I hope you understand. So, I want if
I'm generating a chat title or any title
of the chat or any title. So I'm just
going to just define P2 model and then
it's going to just pick anyone depending
on where we are the environment we are
if it's in development we just use the
gateway uh language model this is not a
must you can just simply just take pass
the ID but I don't want to be passing
the ID so I just want to make this very
simple for the generative of text so
I'll save this now now let's go back to
we are done with this so let's go back
to our chat and let's go ahead and
complete this. So the last thing we're
going to also get from the client is a
selected to
so we're going to call selected to name.
So Z custom
I just say optional.
We going to define the type later on. So
I'm just going to leave it for now. Then
we'll go ahead and define a type for the
tools we have. So yeah, let's just pass
in postpost
then
validator. Let's import that
JSON and then we have the chat schema.
So now we need to also pass the get O
user then async.
Then let's have a try catch here.
It's a constant
user is equals to C.get
um user.
So let me get the context here
and then we can get the messages. I just
get the ID message
selected. So let me just say C do
request do valid
JSON
selected to name. So I'm just going to
do this we're going to get that let me
just get them here selected model and
seed to name.
So now the next thing we going to do is
to find where uh if we can get the chat
ID exist in the database. So I'm going
to say that chat is equals to await
Christmas
dot chart
find unique
where
ID
and then if not ID if there's not the
chat does not exist. So if chart does
not exist
let's
say constant
say chart is equals to wait
dot chart
dot create
let's pass in data which is the ID
then we can pass in the user ID here
user id
And now we need to pass in the title of
the of the chart. So let's quickly
implement the it. We're going to create
a function that generates the title. Say
generate
um I2
from user message.
Let's just pass message here. And you
know that this is messages type of UI
message. So I'm just going to create
this inside the action. So let's just go
into action. Let's create x action.x
actions.x.
And there is a export constant
generate.
Let me say function here.
And then we can say um
messages
of type messages
UI message
like this. So, let me just go ahead and
import this.
Why is it error?
Okay, so message me message.
Okay, the error stop. So yeah, we're
going to use the generate step. So let's
just implement that here. So I'm just
going to say try
catch
error say constant
constant is equals to wait generate
generate text
from AI.
Now I need to pass in the provide the
model. So let's import my provider
language model and let's just pass in
type two
model like this.
So let's just
let me pass the system prompt here and
then let's pass prompt.
So prompt is going to be JSON just
stringify
and passing the message. So reason why
we did that remember the message is not
the UI message is not a string
the text is inside user is inside the
part. So we don't know ex exactly where
the path is. So we going to just pass
everything to we're going to stringify
everything. So the AI agent already know
where the text is. So it's just going to
pick the text from inside the part.
So now we're going to just say um x
and then let's return
x. So if there's any error we can just
consume that error
and try to
error. Sorry.
Then I just return
on title here like this. So we are done
with this. So I just go back and then
let's pass the title here.
So now this is so the next thing we're
going to do is to get all the messages
that belongs to this chat. So we want to
combine all of them with the messages
new message and then send it pass it
down to the stream text. So I'm going to
call this messages
uh from DB
is going to be equals to await Prisma
dot message
find many
where
sorry
chat ID
is type ID
then let's order by descending order
created at
descending order.
So now we're going to map this to
convert it into into a UI message
format. So
remember we are saving the part if you
look at the schema we saving the part of
type JSON. So we need to um get that um
change and um arrange all of them into
get the ID part and then pass that into
the uh convert that into the um UI
message. So I'm just going to close
this. It's a constant map
UI message. This
and this is going to be of type UI
message.
So messages message from DB map.
Um we can say message
and let's just return this id dot id
want to pass into row row and then we
say as user
assistance
and then we can just say system.
Then we have the parts.
So let's just say the types UI message
UI message part
any
I'm just going to just set any any like
this and let's just import any for the
entire file.
And then that is it. You can also pass
metadata if you want to pass. And then
you can just pass created.
It's not compulsory. It's optional. Now
let's combine this. Now we say new UI
messages
is equals to let's just get the make a
copy of this
and then pass message here.
So now this is going to work fine. Now
after we've convert that into combined
the UI messages. Now remember we need to
convert this into the model messages
which is going to match the model. So
it's going to remove the parts and stuff
and just change everything to row
content and stuff like that. So I'm
going to say constant model messages is
going to equals to convert. We're going
to import as convert mod to model
messages. And let's just pass in the new
me new um UI message.
So now we need to save. Remember we've
not saved this message coming from the
use from the client. So we need to
create a message
dot message
just create
data
and then I'm just going to
and then here we're going to just pass
in the ID uh which is going to be
message
do ID.
So I'm just going to just paste this. So
this is going to we're going to this
going to generate ID on the client side.
We're going to set it um in use chat. So
use chat is going to generate that hook
use chat hook from is going to generate
ID or you can also specify the type of
ID you want it to generate. We're going
to look at how we're going to do that
when we're implementing the client side.
So now we have we have saved the
message. Now we need to get the modules.
So I'm just going to get the model like
this.
So, what I'm going to do is I'm going to
go back into where we have the provider
and then I think I'm going to just
uh let me export this too.
So, I say is production.
So, save this remove this. So, I'm going
to just is production.
I'll import from our AI provider. So if
it's production then we can use
the
sorry let me just put this in order let
me import
let me import this
so the model provider let's import
development chart model
so remember the de development chart
model is coming for the models if I go
into models here
we can see this is just the model Gemini
AI 1.5 flash and if we pass it is just
going to make use of this. So I'm just
going to remove this way. So now if it's
production we just use the AI SDK the AI
gateway sorry if it's development we
just use the Google but later on we can
comment this out and just take this we
can comment this out we don't want to
try to test it in development just
comment it out and just
just a constant
like this down so now let's implement
the streaming
so it's a constant result is equals
equals to stream
text sorry stream text
let's pass in the model which is going
to be model provider
now we need to get the system point
we're going to do that now I'm going to
do that then we need to also pass in the
stop the stop when which is going to be
of step
count is we're going to set this to five
because we have we're going to have
multiple tools. So now we have tools.
This we're going to have the create
notes to the search note to the extract
URL to and the web search to. So I'm
just going to comment this for now.
And then
here we going to also set two choice. So
we have two choice here.
and two choice. You can set auto auto
required if you want. So this is going
to be auto.
Then on error,
let's just console log the error
streaming.
Why is this?
So why is this training
the system parameter
[Music]
of prompt? Okay. Yeah, we didn't pass
the message. So let's pass the message
here.
Model
messages and the error should stop. So
that is it. So let's just return this
and then we just go ahead and work on
the pass in the system prompt and also
work on the tools. So I'm just going to
say return
result. So this is going to convert it
back to the UI stream response.
So inside stream response I'm going to
say you can say send they have so many
options here.
So we can have send source.
True.
We have um
I think it's send reasoning
true. Send reasoning true is um default.
Default is true. You can hover over it
and you see it. Default is true. So I'm
just going to remove it. Now we have
unfinish. We have the unfinish here. You
can see on finish on step finish but I
want to get it once it converts to the
UI message uh the UI message. So I'm
just going to say unfinish
and there I want to
I want to save the message here. So I'm
just going to say messages
from here. Let's just console the log
complete message
and there messages
I'll just say length but if you want to
get the response from the AI we can just
get you can see response message I'm
just going to just pass that here
the response message. So yeah we're
going we're going to save um the
messages here. So this is an array of
messages. So I'm going to say Prisma.
Let's ret try that here. I'm going to
say await Prisma
do message
dot message
dot create many
ID. Sorry, not ID. We're going to say
data
messages do um map.
We have id m dot id.
We have chat ID.
This is going to be the ID from the
Why is this?
Okay. So, we need to move this to the
top.
Then we have the path. So I'm just going
to copy this.
Then we have a created ads.
It says new data, new date, sorry.
Updated ads.
And then we can just say skip
duplicate true
I think. Why is this showing? Okay. ID.
Let's see. C trainer
dat
message it's not assignable to create
many id
okay it's saying who is missing
yeah sorry we need to pass in the row
so we need to also generate and define
and generate you ID. Why do we need
that? Because some of the messages, some
of the messages coming from the AI SDK
might not have an ID like the two call
and they might not have ID. So what
we're going to do, we're going to go
over and create a method. So I'm just
going to go into my YouTube
and let's implement generate UID. So I'm
just going to import that here.
And then here I'm just going to u
define the method here. Generate UID UID
4. So let's just copy this. Save this.
Go over to the chat.
And here instead of empty string, I'm
just going to just say generate if
there's no ID. I'll just um generate ID.
like this is okay.
So yeah, I just cons
like this. So here we can just say um if
error instance
of HTTP
exception
then true
error
and we can say true
HTTP
exception
500 SSH page
internal
server error.
So now it's remaining the uh two name.
So we're going to go ahead now and start
working getting the system prompt and
the tool call the tools here. Let's also
add um below here I'm going to add
original messages and I'm going to pass
in the new UI messages here
and save that. So um this should work.
So so let's go ahead and then work on
the tool. So the first thing we're going
to work is to create notes too. So I'm
just going to enable this.
So I'm going to say create
note and this we're going to create a
method called create note and this we're
going to pass in the user ID
ID here. So we're going to have for
search notes too. So let me just quickly
do that. So I'm just going to say search
note or find notes
and then I'm going to change this to
search not
and this will have the view sorry this
should be comma.
So let me just um
come over here let's go straight to the
AI. So I'm just going to create a
folder. I'm going to call this
uh tools.
And inside here I'm going to say create
note
create not to
CX.
So inside we're going to export first
export constant create note
is going to be equals to
the user ID
of type string.
So here we need to call two. So to get
to from a SDK
and remember we need to give the
description.
So I'm just going to um paste that here.
So I'll say create note create a note or
save save to note or save to not
with title and content. Use this when
the user asks to create save or make a
note.
Then we need to also pass in the impute
schema.
So it's going to have z. So let me just
import Z here
from Z
and then let's say Z object
let's pass the title which is al string
dot um describe
the title
of the notes.
Let me duplicate this. Change this to
contents.
And this is the contents
or body
of the note. So you can also have out if
you want you can define um out schema.
There's another um called out schema. So
I'm just going to leave that. So what
I'm going to do next is to call the
execute method and this going to be
async
and then we have title
content here.
So let's just console the log
create notes
to call
like this. So now we need to call try
catch here and then we can save the not
say note is equals to await prisma.
Let's import Prisma
dot node dot create
data
user ID first it's going to be user ID
title is going to be title
content it's going to be content
then we can pass in created or let's
just pass it we can we can leave that.
Yeah. So, let me just remove this.
So, we're going to just pass going to
return.
So, let just success true. And we can
just set a message here if you want.
Then we have um the note ID.
It's going to be note dot id
to note dot title
contents note
dot content.
So yeah, I'm just going to return
success
for
a message
to create notes
and like this
we can just console the error. Oh,
should we return the error?
Error.
Error. Wow.
So if error instance
let me just say error dossage
it's not going to work. So just say
instance
so instance
of instance of error
say error dot message
else
uh unknown
error.
So the uh this has stopped. So now we
have a we simply created the note create
notes too. So let's also um do that for
search.
Let me let me just remove this to make
it um cleaner. So for the search not
we're going to do the same thing export
constants
uh search not is equals to yes let's
return this
then here we're going to have the user
ID
string
then let's call two
from AI SDK
then we can have the description
So I'm just going to say search through
um search through the users notes by
keyword
in title or content uses when user asks
to find notes
or search notes
or look up notes.
So I'm just going to say impute schema
z. Let's import Z. Yeah.
So Z object.
So now we need to pass in query
Z string.
uh describe
search query
to find
um in notes
that we can also pass in limits. This
can be optional.
Z number
dot optional
dot describe
max number maximum
of results.
You can just set default
So now we can have the execute here
async
and let's run this.
We have the query
limit
the first 10.
So let's have the try catch here. And
then we're going to filter
constant note is equals to await prisma
dot note
dot find
many
where
user id
then we have the or
then let's define title
title contains
working
mode
insensitive.
We're going to do the same thing for
content. So I'm just going to copy this
paste it here.
contents
and then
after the array we're going to do order
by
sorry not here outside
order by updated at
descending order.
Let me change this to created at
So we can say take
limit.
Then we can select what we need. We need
the ID true.
We need the title true.
We need the content true
like this. So now we also need we can
also pass in the created.
True. This is okay. And then let's
return
success.
Then we pass in we set a message a note
here.
Let's just pass a note
like this. So here we're going to return
success
false
message
field
to search not
and then we can say error
sorry error instance
instance of
error
error message
unon
um
error.
So we are done with this. So, let's go.
Let's quickly go to the chats and let's
import this.
So, I think it's an error. Error here.
So, let me see what is the issue.
Create not return void.
So another reason why this is error
let's go back to this and let's just
remove this
let's just return
the error should stop. So search not
let's remove this you can add return
here if you want. So we didn't return
this. So I'm just going to scroll down
here and just remove this and the error
should stop. So I just go back to the
chat and then we can see the error has
stopped. Great. So now we've done the
we've added two tools here. So there's
remaining two modules and let's work on
that. We have the web search
the website to say this is going to be
web search.
Let me add comma here
and then extract
web URL.
So let's go ahead and work on these two.
So I'm just going to um open here and
let's go down to where we have all the
tools
and let's first of all create the web
search
here. Sorry, tx.
And then I'm just going to just scroll
up and just copy these two.
So yeah, let's say export
constant
website
is equals to
two. Let me paste it here.
Two.
Then description.
Sorry description.
And then we have the impute schema.
So object
really
z string
dot describe.
Then we have um it's a search search
query or search web query.
So let me just paste in the description.
So I've pasted the description. Search
the web for current information use when
you need up to date info or when user
has to search the internet. Then we have
execute
a sync
and now we have the try catch here.
Let remove it for now. So how do we how
are we going to implement the web
search? So, we're going to use a package
of a platform called So, let's let me go
over to the browser
and let's search for let's come over
here and let's search for
search for this uh platform.
So, just click on this click on this uh
first link and this is going to open.
So, with this platform you can you can
use this to search the web. They have
the search API. They also have the
extract API and also call API if you
want to call a particular URL. So I'm
just going to just come over here and
sign up. It's free just so I already
have an account. So I'm going to log in
and once I log into the app. So let me
quickly log in here. So I've logged into
the account. Now you can see we are
given 1,00 credit. So just click here
and you can see your API keys here. If
you want to look at the documentation,
you can come over here. We can come over
to API playground and then you can see
how to use the uh search. I think we can
see extract here. You can see extract
here. If we click on extract, you can
see how to use extract and you pass the
URLs. So we can click here to see
documentation.
If I click here, you should open the
documentation. Then click on quick
start.
Then you can scroll down to see
search.
So just click on click on it and then we
can see how to so we're going to install
this package. We're going to install the
package and we're going to pass in the
search and then we're going to get a
response from here. So just quickly go
back to the API and make sure you copy
the API key. So just copy this here and
once you copy, let's go back to the code
and then paste it inside the EMV.
So I open my EMV.
Come down to your EMV.
So just paste it here like this
like this. Just paste this here inside
your then paste in your API key. So I'm
going to quickly do that. So if you have
paste your own like this. So make sure
let's go back to let's install the
package. So I'm going to say mpm
npm install
and then just call this package namely
call 0
0.51.
So just click on enter and this should
install the package for us. So I'm going
to wait for this to install.
So now this has installed. So I'm just
going to close my terminal and let's go
back to the web search tool.
And here we need to define the package
here. So I'm just going to import it
here.
So I'm just going to say import
from.
So import from this package and then get
the so let's define this here. So
import this then pass in the API key.
So import this and um import the API key
and pass the API key here and then let's
use this. So inside here let's do try
catch
and then inside here we're going to say
constant response
is equals to await
do search
and then let's pass in the query
and then inside here we can include
answers true
we can include Um
icon to true.
We can say include
we have include uh images.
You can see images and image
description. So I just say this to false
here. Then we have maximum results. So
I'm just going to reduce this to three
results so that it does not um take we
don't
use all of our tom token. So let me just
um query
and then we can just define the results
success true.
Then sorry here we can just say constant
result
is equals to response
dot
dot result
and set this to empty array
constants. Okay,
sorry. I think I've moved this inside
like this.
So just wrap this and we're going to
have map
get any
and let's return title
our title
then URL we can get that from out URL
content you can see out content
then five icon
5 icon.
So let's see whether we can get the
let's look inside the results.
So inside the results I just go into the
result. We have content raw content
because we don't have the answer. Okay,
we have okay, we have answer which is a
standalone. So I'm just going to remove
the answer because I don't think we are
passing it to Okay, we can leave it. We
can pass it to the lm.
So after we do that, let's just pass
answer here.
So response
dot answer
I'll just say no sorry
no summary
no summary available
then results
it's going to be results
then uh we have the I think there is.
So let me just um import this.
So let me just um like make this any at
the top.
Then if you want to pass in the
response, we have the response.
If you go down here, we have response.
So not here.
Here we have response. If you override
this, you can see
response
time
can be response
dot
response ID. So response time.
Can use this if you want. So yeah, let's
just also return
a success for
and then we can see message
web search field
and then we have error error
instance
of error.
error dot message
else unknown
error
like this. So we are done with the
search. So let's just copy everything
like this. And then I'll just copy
everything here. Let's go to extract.
Search for extract. Sorry. Type create a
new um file and call it extract URL.
CX.
I'll just paste everything here. Scroll
back up. Change this to extract
web URL.
So yeah, we're going to change the
description. So I'm going to remove
description and just say extract content
for one or more URL. Use this to
retrieve summarize analyze page content
return structure data for page include
URL title content and five icon. So
yeah, we're going to also change this.
So this is going to be URLs, not URL.
So, we're going to wrap this um let's
just copy this set
our way
and let's just paste string like this
web URL
or we can just say URL here.
I say use search URL
describe
web URL
by this is okay
let me say website URL
so inside we're going to get URLs here
and then instead of search we can say
extract and Then let's pass in the URLs
here.
And there we can just we can remove
answer
images for you. You can also specify
topic here.
Can make this um general.
So let's look at this. So I'm just going
to go into the package going to
extract
function
and then go into the options. And then
you can see we have um include five
icon. We have format this can be markd
down or text
and we have um extract and depth basic
or advanc. So basic is the default. We
also have um I can't see this here.
We also have the topic.
So I'll just leave it. You can just
check this in the documentation and you
should see that here.
So I'm just going to go away from this
and then let's just change this to um
general. The topic is going to be
general and then we can leave format set
format to markdown.
Extract depth to basic
and let's set maximum maximum does not
exist. Okay. Let's leave it to maximum
of three. Let's just remove this
now. Let's remove the answer from here.
Then we have um the result. We can say
response result map. Then we're going to
have the URL. There's no title. So we
have um instead of content, it's going
to be raw content.
And then if there's no content, we just
say no content
extracted.
like this. Then we have the five icon
like this. It's okay. And then I think
there's no message. Let's look at this.
The response
there's no images. This is okay.
So result here.
And then
we can return the URLs too.
Yeah,
let's remove this um response time here.
So, I'm just going to set this like
this.
So, this is okay.
And then we need to change this to
extract
extract URL fields
content field. So I just need the
response time there like that and I
think we are done with this. So let's go
ahead and import this. So let's go over
to chats
chat and let's import the website and
then the extract
URL. So we have completed the two tools.
So the last thing we're going to do um
for this endpoint is to um define the
prompt the system prompt. So I'm just
going to scroll back to where we have um
AI folder and let's create prompt here
ex
I'm going to just paste in the prompt
say export
constants get
system
prompt.
So here we're going to pass in the
selected to name
of type string.
So let me just quickly paste that. So
this is the prompt system prompt. So
system prompt we have the base point
you're a professional help not taking
assistance. Your primary goal is to
assist users by provide accurate
information and actionable suggestion.
Always follow the structural behavior.
So we have the core behavior.
Acknowledge requests briefly before
asking. Provide comprehensive results
with actionable. Next step must confirm
confirm before two chain. Always ask for
explicit permission before ching to wait
for confirmation keyword like yes confir
go ahead. Then I'll just say etc. I
execute only one to per time. I wait
confirmation before proceeding to the
next in a in a chain in a two chain.
Then if if a new request may immediately
abandon the previous request and
confirmation state to handle the new
request
the previous request
or confirmation and
state and handle and handle the new
handle the new request. So we have the
available tools here. You can copy that
from the GitHub. Copy this one from
GitHub. We have a create search not web
search and then the extract web URL. So
we have decision and response flow. Then
we have two selection and execution.
This is the initial acknowledgement.
Then we have the two selection and
execution. Then we have
action after every to provide a detailed
and compressive explanation of what
you've accomplished. Then we have the
next step and suggestion. Then here we
just give this two selection response
guide. So use this for this extract
content and stuff. Then this is like an
example of the response for each uh two
and then once the user selects a two
manually select then we tell the AI
system that manually to force override.
So user selected
first with a conversion conversational
action based phrases phrase. So if two
is this okay I will create the notes as
requested. So this is just an example
for each of the um two selected two.
So and then we just return
return the base prompt here.
So that is it for this prompt. So, I'm
just going to copy this
and then let's go let's go back to chat
and then let's scroll down to where we
have the system. I'm just going to paste
this here and let me import this.
So now let me just pass this here
not selected model selected to name.
So let's Okay, this is of type. Oh no.
Okay. Yeah.
Okay. We've not set the type for this.
So let me just set this to string.
So inside the get system point, I'll
come back here and I'm going to set this
to um optional
or no.
So if there's no this this is not going
to append this particular this prompt to
the page the entire prompt here. So I'm
just going to cast this. Now we are done
with this part of the endpoint. So let's
go ahead and work on the next endpoint
here. So below here we're going get all
chat. So let's just do get
slash
and then we say get out user
then async
let's just try catch here
constant user is equals to request sorry
do request
dot get not request user.
So we are getting the um user. Then we
say constant charts is equals to await
prisma.
Let's import. Okay, we have Prisma ready
dot chat
dot find menu
where
user ID user do ID
order
order by
created at
descending other
I think we don't need this.
So yeah, let's just return
um s JSON
success true
data charts
and then let's throw
sorry
new HT
exception 500
and then we can have message
build or internal server error
server error
like this. Let's just console up
error.
So, we're done with this. So, let's go
ahead and work on the single below here.
I'm just going to I just copy this
paste it here and then we're going to
just pass in ID and then here we can
just get a single ID here.
So I just say constant chat
ID schema
is equals to Z object
ID
string
dot
just put minimum one like this. So let
me just copy this.
So you're going to say Z validate
and pass the id should stop. So now we
can just get the id
see the request
valid.
[Music]
So let's just say um chat find
find first
um ID
and then user ID and then we can include
a message here. So I'm just going to
come down here and say include
messages
order by
created at
ascending order.
Then we can select what we need or we
can just leave everything. So I'm just
going to let me just remove the select
and then below here before we done we
need to convert this to message UI
message. So I'm just going to say let's
first of all say if not chat
sorry if not chats
then throw
new http error
exception then we can just say um sorry
404
message
okay no instead of th an error here
let's just Done.
I see your JSON.
See your JSON.
Sorry guys. See the JSON. Then just say
success
true and then data.
So the reason why I didn't throw an
error is because initially we're not
going to have any um charts
on a single page.
Okay. What if we don't have any chats?
We don't have any message.
Okay. The ID.
Yeah, this is correct. We may not have
any um
chats
while fetching a single
a single chat.
Okay, let let me just let me just remove
this here.
So then we're going to say constant UI
message
and this is going to be of type UI
message
is equals to chat dossage
messages do map
and let's return this.
So we just have the ID to message id.
Then we have row
message row.
Then we have parts
message parts.
Then we have u. Okay. We have we can add
metadata here.
created at
messages created at.
So now to return the data we're going to
say constant chats
with message
is going to be equals to do chat
and then messages
UI message. So here I'm just going to
say as
user
assistance
system
by this
is showing some error here. So I think
it's this part as UI message
part
any
why is it typ
okay So what I'm going to I'm just going
to remove everything here like this
[Music]
format everything like this metadata
part row and ID I don't know why
throwing some error here we have user
assistance
UI okay sorry we need to add array here
and this should stop so I'm just going
to change this just pass data
and pass this like this error the error
should stop. So now we are done with
this
and then we can say fail to fetch chat
intern error.
So that is it for this um API. So let's
go ahead and start um implementing the
um clen part of the chat endpoint.
So let's go over to the chat. So I'm
going to clear um everything here. So
I'm going to collapse this. Then inside
the app, we're going to go into route
dashboard where we have charts. Let's
create a page
x x. Then we going to have the chart ID
here and this going to have page.xx.
So inside here we can just say um export
default
async
function
page.
Let's call it a chat.
And here we're going to return.
Let's have a div
and it's going to be class
name
um
relative withful.
So here we're going to then define the
chats interface.
So this is a component we're going to
create. So this component is going to
hold the chats conversation and also the
input. But since we're going to be using
this inside the homepage inside here
where we said I mean inside the main con
section
you're going to be having the chat
interface here. So this in the chat
interface we're going to have um we're
going to have a field we are going to
call only impute. So in the homepage
we're going to only show the impute.
While here we're going to show both the
conversation and the impute or the
prompt impute. So I'm just going to
we're going to pass u I'm going to pass
initial
initial
message
messages
to empty array.
Then we say initial
loading
to first. So the reason we are passing
this is because we're going to still use
the same component inside the single
page. And remember inside the single
page where we have the ID by ID we're
going to call an endpoint to get the
chat and then we want to be showing a
loading and then we can get all of the
initial messages from the single chat
and then pass that inside the chat
interface. So because we're going to be
using it here in the chat currently the
user doesn't have any chart yet. So this
is going to be empty by default. So I'm
just going to also pass the only input
and this is going to be false. So we're
going to um use this in the homepage.
This is going to show the impute and
it's not going to show the conversation
um um UI. So and here since um we need
to generate the ID from the client side
from the from this side the server side
component instead of the back end.
Remember we're not getting the ID in the
back end. So what we're going to do we
can use
constant id is equals to generate
id.
So remember we've already defined this
ID here inside the you can see there. So
the reason we are passing we generating
ID on the client side on this server
side component this is not the um this
not the client this is the server side
component of the component. So if we if
we generate the ID the ID won't change
because the server side will not um when
the client side render it's not going to
affect the server side component unless
you make a hard refresh or you make a
full refresh then this ID will change.
So we're going to pass
uh chats ID
here.
So we can also pass key here. We're
going to force a new component instance
when the ID changes. So this is going to
only happen when the server side when we
refresh the page or uh the page is
rendered. Yeah, that's when you load the
page. So the server side is going to
force to change the ID. Then we are just
is going to remove the existing um
component in and then create a new uh
force a new component instance. So I'm
just going to save this here.
Then let's go ahead and create this uh
component. So chat interface.
So inside the component we're going to
say chat
and just say index dot
cxx here. So you say
let's change this to chat interface
and let's have um type
robs
and there we can have let's check what
we pass here chat ID
initial let me just copy all of this
so I just have chat ID
of type string. The initial message this
is going to be empty array
and then this is going to be boolean
and then this is going to be boolean.
So yeah, let's go ahead and let me just
pass this here. I'll just say props
So now I can go uh let me go to where we
have the page t and then import this
here.
So let me just remove this. So so here
we're going to let's also pass in uh and
let's also pass in impute disabled. So
when the when the um the page is loading
we're going to just disable the impute.
is only this is going to be useful
inside a single chat page. So yeah,
that's just a constant
um props
and then let's get all of this. It's a
chat ID initial
then initial message
messages
and then we can say only
input. We set this to false by default.
Then I think that is off and you just
get the impute disabled here. So inside
here we going to say constant impute
just set impute
is equals to use state
use state
and this is going to be of type string.
So let's come over here. Let's use
clients.
So now we are going to be using the
let's console the chat ID. Let's see
ID here.
So we can look at this.
So you remember we're going to be using
the um we installed if I go back to
package JSON
we installed the SDK V component. So
here we're going to get the use chat
hook and we've seen that in the
documentation. Let's go there and look
at also we're going to also install the
um the AI
the AI SDK sorry the AI element. So I'll
go back to VC
and then out here inside the AI SDK
components sorry documentation then if
you scroll down you can see the AI SDK
UI and then inside the SDK if you click
here you can see the use cart.
Let me click on this use chart.
So we can see the use cart here and we
need to you can get the use chat from
the SDK and there we can just pass in
the transport which is default
transport. So if you didn't pass any for
please just go with API chat and then
you can pass the API credential header
body. We also have PPS send message
request.
There's some options here and um we also
have ID message on two call. We have on
finish we have on error on data resume
and a bunch of all of this here. So
we're going to use this. So let's first
of all go and click on the AI elements.
So inside the AI element we're going to
install this. So just copy this. You can
copy this or you can copy from add this
function to UI
like this. So let's just copy this one.
I just going to add all of this
component inside our inside our project.
So let's go over to the code and let's
um let's install this or let's add this
here. So I'm just going to let me just
paste this here. MPX AI elements latest.
So this is going to create this going to
add this inside the UI component. It's
not UI. It's going to create a separate
folder for AI element.
So I'm going to wait for this to add the
AI element inside the component. So it
has added the component here. You can
see I see it here. You can click on AI
elements and you should see all of the
components here.
So now let's just close this.
Let me go back to this and let's let's
import this from let's import this chart
from
AI react
use
chat
like this. So let's come down here
unless a constant
is equals to
use chat
like this. So yeah, we're going to
change this to UI message.
Let's copy this and do that here.
it. So the first going to pass is ID. So
I'm just going to pass chat ID here.
And then we have the messages. You're
going to put the initial
initial messages.
Then we can pass generated ID.
I'll just say generate
U ID.
generate a UD
and then we can say transport.
So let me just leave it like this
and we can define transport here.
And we have new
default chat transport.
Then we have the API. This is going to
be SL API/ chats.
Then we also have prepare
prepare send message request.
And this is going to give us we're going
to get the uh messages
id and then body.
And here we need to return
body
the ID the message
and the message is going to be messages
dot
to get the last message
and then we can pass selected
model
ID. I think we've added in the back end.
So, I'm going to set this to default
default um chart model.
So, let me just go over to the models
here.
Yeah, default model ID.
I just paste it here and let me import
it.
So then we need to just pass in the body
structure that and just pass body.
So now this is it. We can inside here we
can get the messages.
We can get set messages.
We can get send message.
We can get the status.
You can get stop and you can get L here
like this. So if you scroll down here um
after the transport we can also say on
two core we have on two core
um async here. Then we have unfinish
and then we have an error.
So yeah, I'm going to just say console
log
SK error
chat error. Yeah,
like this. So yeah, we're going to add
some things here. Here we can get the
particular to that was called like a
note two and then we can just refresh
the note.
Yeah. So we're going to do that later.
So now inside the initial message, we
need to uh set the message. This is
actually going to set the message. So
what I'm going to I'm going to use use
effect.
So let me just import this.
So I'm going to say um initial messages.
So let's say if initial message initial
message length
is greater than zero then we can say set
message
and we'll pass in the initial message.
Let's just pass set message here too
like this.
So now we can say if only
impute here we can just return
let's return a div here
I say class name
waitful
relative
and then inside here we're going to
define a chat impute.
Yeah.
So we're going to leave it for now
because in the chat and page we know
you're setting on only input force. So
let's go ahead and implement the actual
chat interface. So yeah, we're going to
have a div and it's going to have class
name
relative sorry flex column
minimum height. Let's give this a
minimum height of
um or um height or screen
the minimum width
width of zero. Then we give it overflow
X overflow horizontal hidden then we're
going to have BV background.
Then here we're going to define the
chat. This is going to be the chat
conversation. So I'm just going to call
it chat messages
here. So then we're going to also define
a div. This is where the prompting is
going to the chat input. So it's going
to have a class name. It's going to
stick to the bottom
then sorry bottom one
then we're going to see asense
Y1
then flex gap two
padding um X4 then padding um bottom
one margin top two then we give this a
full width and then background VG
background. We can give this u
x
like this.
So set index.
Let me make confirm.
We don't have this. So I'm just going to
set this to one. So inside here we're
going to have a div last name
and then we're going to say with full
relative
um MX auto and we're going to give this
MD of maximum
um width 3 XL.
Let me change this to large. MD is okay.
And then let's define the chat impute.
So the chat impute we're going to pass
in the chat ID
we're going to pass in um
the impute.
We're going to say set impute is equals
to set impute.
We're going to also pass in the
messages.
So the messages is coming from the hook
here. We're going to also pass in the
status from this hook.
And then we're going to pass in stop.
Then we're going to also pass in the uh
the let's say the um default
the default uh where is it?
The default model ID. So I'm just going
to pass it here. I'll say um initial
model ID
it's going to be default model id and
then we can say set messages
is going to be equals to set messages
then send messages or sorry send message
is going to be send
message like this. So let's go ahead and
create this component. So just copy this
and let's come over here. Let's say chat
impute
txx
and let's import this.
Let's define the prop here
type
chat ID of type string.
Let's just add it here. FC
is this then here we pass in the input
here
string
also uh we need to also add a class
name. So I'm going to add class name
here
with
let me just copy this
over back to the chat input and let's
pass name. So make this um a string and
this will be optional
and then we have to pass in the set
impute
and this is going to be dispatch
set
state action
and then this is going to be
string Okay,
now we have the status.
The status is going to be use um
use chat.
Let's check it from
let me come over into the uh index and
let's look at the type
chat status. So I'll copy this
[Music]
and let me just paste this here. So let
me import it from AI.
Then we have messages.
It's going to be an array of
who I message.
Then we say set messages.
This is going to be let's also check
that. So set messages.
It's going to be of type um
UI message. So I'm just going to use let
me use the use chat
helper
and then we say UI message
set messages. So let's duplicate this
and then change this to send message
and then change this to send send
message.
So let's set send
and then we can have the initial
model id
of type string
then stop
void like this. So I think the error
should stop.
Okay.
is model
ID
and the error stop. So now let's go
ahead and then get all of this from the
top. say um charts ID,
impute,
initial um model ID, status,
class name,
then set impute,
set messages,
send messages,
send message,
stop.
Yeah. So we've got it. So now what we're
going to do here.
So inside here we're going to import um
prompt impute from AI elements like
this.
Then we're going to have class name
here. So let's say class name
CN. Let's import that from YouTube
relative
PG white
from dark mode we say PG
let's give this 242
6 like this sorry 28
like this then we can just set ring
border
then shadow
MD then on dark mode we can show shadow
um black
and let's give this opacity five the
rounded
3 XL so I set this to
and then I'm going to divide
y z
have um adding button. Then let's pass
in a class name here
[Music]
like this. So yeah, we're going to have
the unsubmit
here. Say unsubmit
prevents
prevent default.
So it's not working.
Okay. So, let me just set this to
constants on submit.
Let's use score back here.
And then let's go.
like this. So inside here, let's create
a div.
And then below here, we're going to
create is a class name of relative.
Inside here, we're going to get the
prompt
prompt text prompt impute text area.
So inside we're going to give this a
placeholder
and then we're going to say row two
auto focus
and then we're going to say value impute
on change.
Let's come over here and define this
here.
So set the value
to the set impute and then let's also
give this a class name
of a minimum height 16
adding top two overflow hidden
and then text
small
like So for the placeholder I'm going to
define that here.
Let me just say constant um placeholder.
Yeah, I'm just going to say ask search
or create note. So we're going to check
this. If the tool is search, we're going
to change the placeholder to search the
web. But else we're just going to show
such operations. Then we need to also
track
constants is generating.
It's going to be equals to if status
is equals to streaming
or status
is equals to submitted.
Then we're going to make use of this to
determine if to show the stop or uh the
stop button or we don't show the stop
button. So we're going to just use that.
So let's come down here um after this
div. And then we're going to have our
prompt impute. So it's a prompt impute
um to bar
then let's say prompt
prompt impute to
then let's create a component Let's call
this model selector
and let's say on select
and then we're going to set the default
initial
the initial model ID. So I'm going to
come over here and then for the default
initial value I'm going to let's move
this to the top. Here
I'm just going to say constant
selected
model ID.
I'm going to pass in the initial model
ID. So the reason why we're doing this
is we're going to store the model ID in
the local storage. So once we save that,
so we're going to implement that later
on. We're going to check if the model ID
default model ID is in the selected one
is in the local storage. We're going to
just uh replace it with this. So I'm
just going to copy this.
Let's say selected model ID.
Select model ID. So let's create this
component below here. Say function.
So I'm just going to say props
select the model ID
is of type string.
and then I'll select
and okay yeah we need to return
and the error should stop here. So now
we're going to um come over here. Let's
say prompt
impute
model select.
So import that. And here we're going to
pass in value.
It's going to be the selected
uh model ID.
And then we say on value change
um on select.
Let's add that here
like this. So inside here we're going to
say prompt
impute
impute a model select
trigger.
So let's import these two
and there we can just say class name bg
white
and dark bg
we don't want any border
set I mean sorry we need border here we
need to set border
so here we are going to say and prompt
model select value.
So, we're going to also have P model
select content.
So, now let's go over to the models
and let's copy the model options here
and then let's come over here and let's
say model dot map.
Let's import this
the same model
and then let's import sorry font
model select item.
We set the key to model dot value
and then we are going to set the value
it's going to be equals to model dot
value.
So here let's say model dot label
save that.
So we have this. So we can get the
value. Let's uh set the let's go ahead
and implement setting the u the model
ID. I think I'll set that in the local
storage. So before we do that, let me go
straight to the app the um app
controller dashboard chat page. I think
we already have this so we can check
this out.
So let me go um
so make sure the server is running. I
just try to restart my server. Then
click here and let's go over to AI
chart. And once you click on AI chart,
this should open the page and we should
able to see the impute the prompt
impute.
So it has open the charts page.
Now we can see the inputs here. We can
see the models here. uh we can see and
we can type here
how great. So we're going to also uh
implement the other part the impute and
then the um submit button.
So let's go back and then so I want us
to also implement so inside the chart
remember we inside the input we saying
that we're going to store a selected um
ID in the local storage. So once users
so that um you can be able to have the
selected model even when the user um is
at the homepage or in the chat page. So
I'm just going to create a hook to
handle um the chat uh
going to handle all the chats in the
local storage. So, I'm just going to go
over to hook and then inside the hook,
I'm going to just say use local
local chats.x
here.
Yeah, we're going to import
and then pist. So, I'm going to say
interface.
Um, this is going to be local
and chat states.
So here we're going to have the local
model
ID is going to be of string and then we
can have the set model
uh the set local model sorry
ID
and it's going to be of ID or string
and void.
I also want to also save um is history
um
is history
open. So this is going to help us to
toggle the um history. So that is going
to be a like a simple sidebar.
Um that's going to toggle the history of
the chart. And then I'm just going to
copy and paste this. I'm going to just
say this should be um on toggle
history.
And then this is going to have a like
this. Okay. So let's say export constant
um use local
local chart is going to be equals to
create.
Let's pass in the local chat state.
Let's pass in pist.
and let's get
sorry
let's click set and get here
and then we're going to set the default
local
model ID to empty string
then is history open
to false
then we can have the Set
local model ID.
We're going to say ID.
Then set
local
model ID
to ID.
And then for the double history,
we're going to say
set
um his is history
is history open
not get dot um is history.
Sorry, I need to call this this is
straight open like this.
And then
let's add comma here.
Let's name this
name local charts.
Why is he trying
Sorry, I done with this now. So, we can
we can call this inside the um chat
impute.
So,
let me just call this here.
Let me move this down.
Let me call this here constant
use
chat.
Let's import this
use chat hook and then we can get the um
local
model ID and set local model ID. So I
just um bring this and say if not local
model ID then we're going to make use of
the initial model ID. Then I'm going to
say come down here say handle
handle select
is equals to
value string
and let's paste this here value.
Then we can copy this. Scroll down to
where we have the on select. Let's just
past this like this.
So now this should be working. So let's
go ahead and implement the U tools.
We're going to list out the tools here.
So we're going to show a popup over
popover. So let's import popover
function to UI. So I say pop over.
So pop over.
So import that from UI popover. And then
let's come to the top and let's add a
state to toggle the popover. So I'm
going to add that here.
And let's import use states.
Let's set a type to boolean.
So now let's scroll down to where we
have the popover. And there we can just
say open.
Open is equals to two to open. Then open
change is going to be equals to set
to
open. So yeah, let's u let's import the
popover trigger
from UI popover and let's set this to as
tried
and let's import prompt
prompt impute
prompt impute button
from AI elements.
So let's give this a class name
class name
of text muted foreground and then let's
give the size
small and then variant
outline.
So here we're going to just import from
Lucy React we're going to import um
settings.
So settings
and let's give it a size of 16
and then I just choose
and then below the trigger you're going
to have the popover content
import from UI popover not UI.
So let's give this a class name
with 48.
Give this a padding
um X padding horizontal 1.5 p Y 2 and
drop shadow
small.
And then let's give this a line
start.
And there we're going to list out the
available tools we have. So I'm just
going to say class name space
YPS.
Now we need to define the available
tools. So what I'm going to do, let's go
ahead and define that. I'm going to go
straight into my AI uh inside a lip
where we have two AI tools. Let's create
a file. Let's say constants
cx here. And here we are going we're
going to set it to Z. So let's first of
all set the interface.
I'll say uh let's export this first.
I'll say available
available to type.
We're going to have the two name and the
two name we're going to define to name
here. So let me instead just say export
constant let's say the enome here and to
name
en
let's say create note
it's going to be um
sorry let's add equals to here
create notes
so this must must be similar make sure
this is similar to which the one we have
in the chat
in the chat endpoint here.
If I open this
and make sure we match this create not
search not web search and extract URL.
So I'm just going to go back to
constants and then let's also add for
web search here. I mean search notes
here.
So we have search notes
then we have web search
extract
web URL
extract web URL
And let's set it as constant.
So let's say type here is export type
to name
to name value.
So let's say to name type
it's going to be of type of
two name and key of
type of
to name by this. If I hover over this we
can see create not the actual two name.
So I'm just going to copy this. I'm
going to paste it here.
And then we can have the type of the
two. So the type of the tool is going to
be the ID of the two. I mean it's
actually like the ID. So using um the VC
SDK, this is going to convert this to
Yeah. On the client side, we're going to
see this as instead of um website, we're
going to be seeing it like this. It's
not going to return the two name. It's
going to be two dash the and the
and the actual name of the two. So this
is going to define the two ID. This is
similar to all your tools here. So this
is how we're going to get the two. So
that is going to determine the tool
type. So what we're going to do, we're
going to go to constant.
And then let's also copy this and let's
set the two uh
let's call it the two type.
And then here we just going to just add
two
two
and then two
like this. So we can just also copy this
paste it here. Now let's just say two
type.
I'll just change this to follow.
And then let's copy two type.
Okay, let's change to enum.
Two type enum. Then this will be two
type.
Yeah, this is okay. Two type in
two type. If I hover over two type to
see the two type. So let's just copy
this and paste it here. So now we have
the name, the two name and the two type.
So we have the name which is of type
string
and then
we have the icon
which is of type Lucy
Lucy um icon. We can give this a
description if you want. This is
optional
type string here.
So let's export the actual available uh
let's say available
to
going to be cost to type of available to
type
and then let me paste the two here. So
I've pasted it here. So we have the two
name which is two name uh we get the
enum here. this enum to name enum create
note type two type enum create not
create note description and the icon. So
import that from we have the search not
the name search not description and the
icon we have the web search web search
description so I didn't add the extract
so I just these three tools on the to
display on the client side on the UI so
just save this and then we can copy this
so make sure you've written all of this
so just go over back to the chat impute
there we can just Import.
Let's import a label to do map
to
so I'm just going to say key is equals
to two dot type
like this. So here I'm just going to
also get the icon. If we over here we
can get the icon. So I say icon is
equals to icon. And then let's define a
button here. It's a button.
And here we're going to give this a
class name.
Let's first set the icon.
Let's set this to size
14.
And then we can give this a class name
that's a text muted forground
like this. Then we can just say the tool
dot name
like this. So let's give this a class
name. Last name it's going to be wait
for
Lex it center
gap to
uh P2
rounded medium
then we set over PG accent
then text left
X text Let's
give a transition
color like this.
So now in the bottom we're going to also
have the on click and this is going to
set the two. So, I'm just going to come
over to the top here and let's just
duplicate this and just say selected to
then set selected to.
And then this is going to be of type
available
available to
or no.
And let me just set this to no like
this.
So now below here we can define the uh
we can define a function here. Let's
just do that here. Say constants insert
on select two on select two.
So say two is going to be of type
available to
and then we can just say selected to
paste it here and just say to like this.
So copy this and let's scroll down to
where we have the button. Then let's say
on click
on click
on click. We're going to say like this
select two and then we pass in the two.
So once this select we need to also
close this. So I'm just going to copy
the set to open. Then come over to
unselect to and let's just set this to
false
like this.
So now when the user select we want to
throw the two in this at the top of this
uh compute this area. So once you select
any tool, it will show here to indicate
to user that this tool was selected. So
I'm just going to let's say if two is
selected then we're going to show a g.
So on select we're going to set this
into
like this.
So let's come over to this div. Let's
give this a class name
flex
right and center
gap one padding top one let's say 1.5
then padding left two
so let's give it a different another div
so let me close this div
so let's give this a class name
of inline flex
right center drop one
bj primary opacity 0.1 then text primary
adding uh horizontal padding x2 adding
y1 then rounded medium
X extra small and then font
let's give it font medium
and let's set border like this.
So here we going to
so you remember inside the tool we have
the icon. So I'm going to just set the
icon here. So selected to do icon I'm
going to give this a size of um 12.
Then let's expand
and let's select it to name
dot name
and then add a button here and this
button is going to have uh let's see
close
sorry X icon from Lucat
And let's give this a size of 10.
Let's give this a class name um margin
left one on hover.
We give this BG primary
opacity of 20 rounded small
adding 0.5
and then let's just add transition
colors like this.
So now we need to also set just copy the
on select on select two.
Should we see on set to unselect to or
let's say onset to
unset to I'll just copy this. Let's just
copy this and let's say
uh remove two.
Remove two.
then let's set on click here.
So let's let me remove the we're not
using this we're not using this
function. So we've created a separate
function for that. So um the last part
we're going to implement is the um the
submit icon and the submit button and
also the uh the stop button. So I'm just
going to come down here where we have
the prompt impute to here and yes let's
say if is generating
sorry
we're going to show the stop button
and there we're going to pass in the
stop.
Let's pass in the stop here.
And let's just quickly create the method
for that. I mean the components for
that. So function
function stop button
then we just say stop
like this. Then we can get this stuff
from there. So I just return
and then let's also fix this part. So
yeah, we're going to say prompt
prompt imput submit.
Let's give this status
status
then disable
if not impute
trim
and then let's give this a class name
absolute
right to bounded
bottom
1.5.
And then I'm going to say text white.
And then let's give this an icon. I'll
just say arrow.
Arrow up icon.
Let's give this a size of 15 or 25.
Let's give size of 25.
So we're done with the with the um
prompt submit the submit button. So
let's work on the stop button here. So
yeah, we're going to say button. Let me
just import button
from UI button. And there we can just uh
let's just see
size icon
last name
say BGE
100
that mode we are going to use um BG
I will say border
and then cursor pointer.
So let's have the on click
on click and let's get it stop.
So I just pass stop here
and then inside here we going to say um
let's say let's import the stop icon
from uh remix UI
and square field
we have size of 14
last name
X back
and on dark mode we have text white
like this.
So I'm going to also come over here and
let's also say constant
and dole stop. So I want to show toast
I say stop
toast. So let's import those to do info
generation
stopped.
So I'm just going to copy this handle
stop and I'm going to replace it here
and just handle stop here.
So let's implement the onsubmit here. So
yeah, I'm going to set async here
and then inside here we're going to say
if not impute
trim
let's return we can just say um
we can toast
dot sorry dot we can say
error
Please,
please type
in a message or point
and then also we can set if not child
ID.
Let's return.
We can also to here
say please reload
please reload
ID
was found
and let's pass in the input
and also the chat ID.
So now we're going to also check
if status
is equals to streaming.
Let's also return
and say toast
dot error.
Please wait
for the current
response
to finish
or stop
it first
[Music]
like this. So let's pass in status
like this. So then we can just send the
message. So send message.
Send message.
We can say await here.
There's no need for the await. So I'm
just going to remove it.
Let's just put it there.
So here we're going to say row
user
then part.
So for the part we're going to set a
type. So this is we're constructing a UI
message. So the type is going to be
text. You can see we have different type
here. We have the step step text source
source document with a file dynamic to
so I'll select text and I'm going to say
text here is going to be the input of
the user
and then
here we're going to so sorry after this
after the part
let's add comma Here
let's pass in body
and we say selected model ID is going to
be selected model ID then we can say
selected
to name
is going to be selected
to
do name.
So let me copy this on them. Let me set
this here
and then we can say set impute.
So let me remove this arate here.
We don't need it.
And then I'm going to copy set impute.
I'm going to add it here.
What again?
Okay. Select that. So,
[Music]
okay. Selected model ID.
I think that is it. So, the last thing
we're going to do, we're going to once
the user send the message, we're going
to um update the URL of the um app. But
we're not changing the actual page
itself. So just only replacing you the
URL with the actual chat
ID. So we're going to replace it with
the page this page ID. So I just say RFC
page
this single chat page. So this is where
the user should have been redirected to.
But because we want to allow the user to
see the streaming, we're not going to
redirect the user here. the user will be
on the actual page is on the chat page.
If it's inside here, this is going to
only show you. But once the user refresh
the page or below the page, the user
will be moved to this single page. So
that's the reason we want to place the
URL. Once you send the first message or
send the message, the user will be on
this um chat ID and page.x.
The user will not be um there. The URL
will only change this um part. But once
the user try to refresh then the user
will be navigated the user will land on
this um chat ID page. So I'm going to
use instead of using the NexJS router
I'm going to use let me go back
I'm going to use window history replace.
So I'm going to do that here and we say
window
do history
dotreplace state.
So now let's pass in the um the part you
want to replace the um the URL to. I'm
going to slash chat slash chat ID
like this. So we don't want a situation
where if the user is on the chat page
once user is starting sending message to
the to send a message and the AI respond
and eventually refresh the page the user
will not see any chat user will be
brought to a new page again. So that's
the reason we are replacing this without
the user knowing they've not the state
of the URL has changed. So once the user
page refresh or anything happened, the
user will still be in that same page. We
we we look the user will still be in the
page where it feels like it's still on
that existing page he was chatting with.
But instead we have moved the user from
that page where it was chatting the chat
to the chat ID page single chat page. So
that is it. So that's the reason we have
to replace the URL this but we're not
replacing the entire page.
So we are done with the chat impute. So
we going to go ahead. Okay. Set message.
I don't think we going to. So let's
remove this set message making use of
this.
So let me open this. Let's go into index
and let's remove this. So let's also
copy this here.
and let's paste it here too
like this. So now let's go ahead and
then work on the chat conversation page.
So, I'm just going to say chat
messages.
And then let's create this component.
Chat messages
tx
c.
And then let's go into index.tx and
let's import this.
So, we're going to pass in the chat ID.
Going to pass in the messages
status
error.
And then it's loading
like this.
Um it's disabled. We forgot to pass is
disable.
So let's pass this is disabled to um
impute disable. Let me just say
disabled.
Yeah. So I'll copy this past it here.
Let me just move it to the top
and then let me go into the chat impute
and let's um let's disabled option
booian.
So if disabled
we can just scroll down to where we have
the uh unsubmit
and we can say all this
and then
we can also add it here.
Let's say um
if no input, if not chat ID, we can just
say if disabled
return.
So let me copy this. Let's pass it here
like this. So let's go into the chat
message. Let's set the props for this.
So let's say a prop say interface
props
the chat ID string.
We have messages.
UI messages.
We have error.
Type error.
And then we have status
which is um
of type chat status.
It's loading
a boolean.
So let's import FC
and then let's open this
and then we can get the messages
status
is loading
and error.
So now here we're going to import.
So let's set the first
and this we're going to have a class
name of overflow
y2
it auto
and let's import conversation
from AI element conversation
here we have the class name
and this class I'm going to have height
auto
minimum height
Let's give it a minimum height because
this conversation has it own scroll bar.
So we're going to give this a minimum
height. And then we want the div to
scroll.
So let's give this a minimum height. So
it does not uh it has a large space. It
takes up a large amount of space than
the impute. So the impute does not come
to the top. So I'm just going to give
this calculate
100 height screenous
157 pixel.
So let me add this here.
Okay, we need to add the conversation
content.
Let's also have class
name. We a width full
height auto.
Let's give this a padding bottom of 30.
So it gives us space. Padding top 15.
And then flex and then flex column
gap 5
px large
sorry px
large px
zero
um uh we're going to give a max width
of 3 x
and mx
So inside here we going to set is
loading.
So we're going to we're going to create
a component for the um loading message.
So it's going to show the loading
message. This is only going to show when
we on the single chat page and we are
fetching the previous or the history of
the chat. And then this is going to show
the loading states here. So let me let's
define the component here. So I'm just
going to say function
loading messages
and let's just return
if last name
waitful maximum wful
MX auto
MT5
then let's Give a div last name
and then we're going to say flex item
center
no item start
space
horizontal tree
and let's set
let's import that from UI skent
let's give this a class name of height
with it the rounded for
then let's give this a div sorry not
there inside
and this we have a class name of witful
flex flex column
space y2
and let's copy this currently Okay.
And duplicate it again. It's going to
show two. So we have our width. Um we're
going to 66%. And then this is going to
be large.
And then for this we're going to say
widthful.
And then we're going to give this large.
So let's copy this and then pass it
here.
So we're going to also check if
messages.length
length is equals to zero.
Then we're going to show a greeting
message. We're going to show a greeting
component. So let's create that. Yeah,
I'm going to call it greeting.
Let me just remove this and then just
return
a div
class name.
Wait for
uh medium.
Let's give it empty
px2.
Let's also give this heightful
so it takes up the height. Then flex and
flex color.
Let's also give this a div.
And then say text to Excel
font semip
and then opacity use opacity of zero.
Then we use the amination
or the transition fading up. So fading
up is inside the global CSS.
I see it here the key frame and this is
the class. It's a class name. So I'm
going to remove it. So, let me go back
into chat messages and then we can give
this
animate
delay
200 m.
And here we just say hello
dear.
So, we can just copy this and then paste
it here.
And then we're going to say this is
going to have let's say text
zinc 500.
And then here we're going to just give
this 400. So this is this start of first
before this. So this should be amination
animation
delay and 400 milliseconds. So now we
can copy the greeting
and then let's replace this
with this here.
So yeah, we're going to also um we're
going to also check for error here. So
we're going to say um if status
is equals to
error
and error
then we're going to we're going to show
an alert error. Let's define we're going
to create the component
here. We're going to just put title
chat error
and then let's say message
error message
something
something went wrong.
And then let's paste the component for
that. So I'm just going to collapse all
of this a function.
Let me just paste error alerts. And here
let's define the type title of type
string
message of type string.
And let's get the title also the message
here.
So yeah, I'm just going to say alerts
from UI alerts.
We're going to set the variant to
destructive.
And then let's put class nameful
BG destructive
0.2 So
border and destructive
0.5 is 50
and then let's import that icon
last name
right for
so here we're going to also say save
and set the alert title
and then alert description.
Then class name is going to be white
white space
break spaces and then let's say P tag
message. Yeah.
So now this error should stop.
Oh,
let's return this.
And then yeah, we're going to show the
um the actual message.
I'll just say preview.
message.
So let's create the message component.
So I say message
txx.
Then let's copy message inside the chat
messages.
Then let's call the components here.
So this one let's change this to preview
message so we don't have issue
the message component.
So let's pass in we're going to look
through the messages
and then we're going to pass in
a
message do ID
message
and then it's loading
is going to be status.
This status is streaming
and
messages.length
minus one
is equals to index.
So let's just get the index here.
So now we also want to show when the
user submit we should show some loader.
So I'm going to say status
is equals to
submitted
and then we need to check the
messages.length
is greater than zero
and we need to also check messages
messages.length
length
minus one.
Then we're going to say
dot row if is equals to user as a last
message. And then
we can show a loader.
So let's say circle
last name
with four height for
animate
four.
Then on dark mode we can set this to
white.
Let's
close this
like this. So we need to also show the
loader when the streaming. So I'm just
going to copy this and change this to
streaming.
Then instead of row we're going to
change this to assistance
for this.
So let's go ahead and and implement the
message.
So I'm going type here interface
cross
message is going to be UI message
then it's loading
of type boolean.
So let's just copy this
and then
let's also uh let's pass it here. So we
see
let's also call react
memo
and then I'm just going to say
review message default display name. I
mean, let's pass this here.
So, inside here, we're going to um call
the message component from AI exe AI
elements
AI element.
And then we can set the form.
It's going to be message.
So, let me get the message.
And then the is loading.
So we have message dot row. We have key
is going to be message dot id.
And then we have the class name. It's
going to be um
let's say like this C import from
YouTube
and then we say message
dot sorry dot row
is not equals to
user. Then we're going to set the
message width to max width
max.
And then we have the message content.
Let's add a class here.
Let's also add the CN. Let's import
this. We've already imported this. So,
I'll say text. I'm going to give this
15.5
pixel. And then dark mode
text white.
Then now we say if message
row is not equals to user
then we can say wful
max width for
px1
adding bottom
zero.
adding bottom zero and BG transparent.
And then we can just imagine zero.
And then we have minimum
height zero.
So for the user, if it's a user, we say
PG muted.
And then we have padding 2.5
text
14.5 pixel.
There you can see text forground.
Sorry.
So if you did not add this color, this
will use the primary color for the user
message um bubble. So yeah, we then
we're going to we're going to switch.
We're going to look through the message.
We're going to look through the message
part. So we're going to say message dot
part. Remember the part is an array
map
part then the index.
So we're going to use a switch statement
and then
for the switch statement we're going to
use part dot type.
So here we're going to say text. If the
type is of text, then we're going to
return.
So, let me just use
say return
response.
Let's import that from AI element.
And then let's say part text
like this.
Let's also um let's also set a key.
So I'm just going to say key is of a
message id
dot id and let's just give it index of i
like this. Then I want to modify the um
this response is a markdown string
markdown. So I want to modify the the um
code team which says
the team. So I'm just going to import
constant team use team
and let's import team here.
And then here we're going to say
if team is equals to lights
then let's use lights
light plus
else we're going to use um J cooler
I see trans.
So let me check responses
response.
Okay.
It's same same. So
Sorry, this is not working.
It's not showing any.
So, let's just leave it. Let's also um
copy the case for this. And then let's
set another case. And then the next type
is reasoning.
And for reason we are going to let me
just remove this. We're going to import
reason
and let's copy this
and pass it here.
So here let me just set reason
And then inside here, let's remove this
part.
And then let's call reason
trigger.
And then reason
content.
I say part dot
dot text here. So here I'm just going to
set this to return.
No. So for the tool call, let's go ahead
and look at the documentation and see
how to handle that. So if you go back to
the documentation and you click on the
chart boot tool usage, just scroll down
to where we make use of the use charts
and then you can see if you scroll down,
let's just scroll down and you can see
uh this is how to call this is the two
type. You can see we have the two the
two name two and two name. So each of
these two has a state and this state one
of the state is the impute streaming
impute available impute u output
available then output error. If you look
at um you see example here with the
weather get weather info. You can see
once it's input streaming um this shows
like this
then input available getting the info
getting weather information then the the
input um out output available then
displays the output and if there's an
error it shows the error. So we're going
to make use of our own um two ID
mean the two type. Yeah. So let's go
back to the code and let's implement
that. So inside the code you're going to
come down here. We say case
let's just copy this.
I'll paste it here. I'll just remove
everything here.
So yeah let's say two
let's import two name no two type enum
create two create note like this then we
can also get next to search notes let's
copy this
and then we have the web search
and then we have the extract
so we have the Now the two this is two
type two type two type for this and
we're going to create a component which
is going to be called the two um we're
going to create a component that will
handle two of them but you can use if
you go over to um a SDK elements the AI
elements we have the two two components
here but I don't like this um two
components you can see it here can can
you make use of this is shown in the
documentation I want to actually create
my own um two components and which we're
going to use and display in this
section. So before we go, let's test
this out. I'm going to reload this page.
Let's confirm the server is running.
So while it is loading, let's just
create the components. We're going to
say two core
txx.
And here I'm just going to say um
we're going to um implement this here
to
4.
Let's copy this inside the message where
we have this two type. We're going to
just return.
Let's import this.
So, let's just let me just copy all of
this here
like this. So, we're going to get the
states and pass from this. So, let's
just test this. So here I'm just going
to say let's try let's say since we're
using high let's click on send
okay
invalid message
and error message to name invalid impute
string receive undefined.
So let's check the empty chat impute.
Okay.
Okay. I think the problem is coming from
um let's go into chat
the chats API
let's scroll up where we have this I
think this is where it's having some
issue so I think if there's no just set
this to nullable
we can actually set the type of this to
custom um to custom um to name I mean
the custom type name to two name type
I'll just leave it nable and then I'm
going to just um come over to where we
have the chat impute and let's say if
there's no chat name just set this to
none
because we are using this in the U we're
passing this to the system prompt and
inside the system prompt
we have we set this to know you can see
it undefined
this and available to I'm just going to
make sure this is similar to what we
already have
search not.
So let's just go ahead and test this
again. So make sure your server is
running and let's set hi
and let's see if it's going to respond
and then we can see in the URL this has
changed.
You can see the ID here and then we can
see hello how can I help you today? Um
what
model are you?
I'm Gemini AI language. So you can see
it is working. So we need to also modify
the scroll bar. So this should scroll as
we as we are chatting.
What can you do?
You can see that it's not scrolling. The
scroll bar is not moving. You can see I
can create no search to extract
information from web pages. Just give me
a URL to get started. Tell me what you
would like me to do. So it's working. So
um let me just go back to the chat uh
message
need to also
is it chat message? Yeah the chat
message we're going to um use use effect
to check if um the message either submit
or streaming to scroll scroll bar should
be moving down. So here I'm just going
to say use effects
and let me just import the use effects
and there we are going to also import
constant
import use stick to bottom component. So
this used to stick to button component
is already added to there's a component
installed
when we are adding the AI SDK. If you
come over to conversation from AI
element AI element you can see the
component is already in was used here. I
want to use it because I have a
different div that we scroll to the
bottom. So I'm just going to say scroll
ref content ref and then scroll
bottom. So here I want to say if
messages
or status
is equals to
submitted
or status
sorry
is equals to ready
scroll
to bottom
and Then let me just pass messages
status
and then scroll
scroll to bottom.
And then here we can see ref.
And then for the content we can just add
that here.
Should we put it here? Yeah.
Let's
see
content R. So now if you chat now let's
see
thanks
you can see the scar is moving as um as
we send a send a message.
Okay so it's working now. This is
working. So what we going to do now is
to let's go and implement
let's go and implement the two code. So
let me go into message component and
then inside here let me go this team.
So here we're going to pass in we're
going to get the path. So I'm just going
to get that from constants um from the
parts. If you look inside the parts, if
I hover over the parts, you can see we
have the type the two core ID the states
the impute output error text. So we can
get the two core ID the states and you
can see the state we have the impute
string impute available output available
and output error. Then we have the error
text which is a string undefined. Then
inside output this is unknown. This can
just be a this is unknown here. So the
main thing we we want here the main
important thing here is the state which
is going we're going to use once it's
streaming we're going to be showing a
loading indicating the the AI agent is
trying to access the two.
So here
we're going to pass everything here. So
I'm going to say key is going to be um
the two core id then two core id
is going to equals to two core
id let's pass in the type
we're going to pass in the actual type
which is um the pass type here we're
going to also pass in it's loading so I
want to get let me bring back that it's
loading Here
let's pass it is loading.
Then we can see states.
Let's pass in the state
output.
Let's pass in output
and then error text.
Let's pass in error text here.
So, let's just copy of this it here.
Just copy this
and just replace it here.
Replace it here.
Then let's replace this one here. So,
just copy this,
paste it here,
paste it here.
So, now let's go ahead and start
implementing our our two core
components. This is different from the
AI SDK. So inside we're going to set the
interface. So let's say interface
two
two core props.
We're going to pass in two core
ID which is of string.
We have the type which is of type two UI
UI part
type
and then we have the state
which is um of two
two UI parts
states.
We have the outputs
any
let me check we passing impute
sorry inside message
let's see impute okay we didn't pass in
the impute so let's just get the impute
here
uh impute is going to be impute.
So let me copy this and let's also um
pass it here.
Let's get impute.
Let's so paste that here.
I space it here too.
So let me just copy this and let's add
it here.
Stop. So I'll copy this and just change
this to impute.
Let's add the error
error text is going to be string
and then
we have the it's loading
boolean
like this. Sorry.
Like this.
So here we are going to let's get all of
them.
We're going to get the type
and then for this type we're going to
get the two name.
So we're going to format. We're going to
create a component that format and get
the tool name.
So I'm going to pass in type here.
So let's create this component
here.
I'm going to say instance let's paste
this here.
Type string
say type
replace
with empty strings like this. And then
now we can get it to So now we're going
to also create a method that is going to
handle the state the MP streaming. So
once it's input streaming it will show a
text like preparing requests or working
input value it's going to show a
different state and then once it's
output value output available is going
to show a different uh text then output
error is going to show a different text.
So we're going to create a uh we're
going to call that two status. So let's
create a component here. Let's create a
uh let's create two status here.
This is going to just have a method we
going to call and then
why is this error error text? So let me
copy this. So let's go into two.
It's complaining
undefined. So let's just set two text on
different
error text the error stop. So here I'm
just going So here let's also console
log.
Let's console log output.
Let's console log.
Let me get output here.
and then states
and impute. So let's consider all of
them so we can see them once we ask the
AI agent to create to search for not or
create a new note. So I'm just going to
so let me copy this paste it here
then paste impute.
Then I'm just going to get the pipe.
Let's also console the pipe here.
So let's go ahead into the two status
and let's create the status. So let's
say export constant
is going to be get to
status.
So here we're going to get pass the two
name
string and then we're going to say state
string
say output
any. So let me just import the output.
So let me just import any uh sorry not
import to fix the um the error display
here. So yeah, we're going to say if
a state
is equals to
a state is equals to the first thing is
mp streaming. So let me change this type
so we can be able to see the state. So I
just copy
two UI parts.
So let me import this from AI.
So now say if this is import streaming
then let's return
then let's say two name
is equals to create not. So let's change
this to um
to
name type.
So if is equals to create not
then
I'm going to return
a text saying creating not
sorry not creating not
let's just remove this
should be this should be um this should
be for impute
available not impute streaming. So
impute streaming will just show um let's
just remove all this check
in this I just preparing or let's say
working
like this and then we can just give it a
icon
say lights.
So let me just
like this. So then if it's impute
available then now we can say cing not
let it pass the impute stream in now
available. Then we're going to set the
icon here. I'm going to say and file
text.
So let me just
let's just collapse this.
Now we're going to say else f2 name
is equals to search not
let me copy this
and instead of creating a searching
searching not and then let's give this a
search icon
and then we can say else
let me Just copy all of this,
paste it here. So now instead of
searching it, we're going to say if it's
web search, then we're going to say
searching web.
And then we're going to just change this
to globe
globe icon.
And then the last one is else. Let me
just copy this.
Let me copy this and then paste it here.
So if extract URL
you can just say extracting
um content
icon. So, let me just change this one to
preparing
a request.
And then on here, I'm just going to say
else
text
working
icon. I just set the icon to this.
So now we're going to just display this
the text and then the icon in different
states. So what of the um we also need
to also check if
so I'm just going to paste this here and
I'm going to say if it's uh sorry output
available
then we're going to say uh if it's
output available we're going to say
we're going to give the result of um the
heading of um or the text of the result.
So what I'm going to do I'm going to say
um for create notes um what I want to do
I want to show result from I say results
let's just say
name
and Here I'll just change this to
let me change this to light bulb here.
And then for search not I'm just going
to um say here
we can say um search note result or we
can also get the length of the note. So
we can get the length of the note from
here. So yeah, I'm just going to say
constant note
is equals to if it's array
is array
output
dot not
then we can say
output
dot not
else empty array
then we can say constant length
is equals to not length
So you may ask where did I see where did
I get the note? If you go over back to
the search note two remember in the
response we we passed this note here. So
this is going to be the output of the
two. So I'm just going to remove this go
back to our two core sorry two status
and then here I'm just going to make use
of it here. So what I'm going I'm just
going to set like this. I'm going to say
um let's say length if length is greater
than zero
then we can say
length
not found.
Then we can say else
search
results
like it is. So for website results
for extra let's say extract
extracted
results
or let's say extracted contents
and for the last one we can just say
gone.
Then the last um check is if state is
equals to output error
then let's return
text
error occurred
icon
alert
circle icon Let's import this.
Then we can return X
or
icon. We can just give this um
slash cycle.
just circle slash.
So we've defined a get two status. So
let's go ahead and um go over to two
core and then here
we can just say constant
is equals to get two status
and there we need to pass in two name
state
and then output.
So let me just copy two name type
and uh
let's say return
So I just change this to drink.
So here we can get the text and icon.
So here we're going to define the header
and two header. So it's going to just be
like the AI two in the AI element. So
the element has the two the two header
and then it also has the u the two
content. So we're going to also create
our very own two header and then we're
going to use this collable content also
as the content that displays the output.
So let me just uh let me go away from
here and then inside here let's also
create let's create the um the two
header components here. So I'll scroll
up here and then here. But yeah, we're
going to just say export
not making export constants to header
is equals to react dot memo.
So let me just return.
So let me just say to header
dot display name is equals to
and two header here. So since we're
going to be making uh this collapsible
like the AI elements. So I'm just going
to we're going to use the collable
trigger for the two header.
So yeah, we also want to not use
collapsible header when we create a
note. So we don't want the the create
note component to be inside the
collapsible. So inside you're going to
only show um collapsible from only the
search note and extract URLs extract
URLs and then search web. So what I'm
going to do to handle that and we can't
just define the colass here this
colossal trigger must be inside the
collapsible component. So what I'm going
to do, I'm just going to say constant
here. I'm going to call this wrapper.
And this is going to be equals to
collapsible.
So I'm just going to set um let's um
let's set this here. We say collapsible.
I'm going to set this to boolean.
So if collapsible is true,
then we're going to use collapsible uh
passible trigger. So imported from UI
collable. So I'm just going to remove
this and s we're just going to use
button.
So let me just copy the spaces here.
So now we're just going to wrap this
depending on the depending on the
collable depending on the components
that is selected
that become the wrapper. Yeah.
So let's add the class name.
So I'm going to say flex item center
justify between
weightful
medium.
Um hover bg muted
let's give it muted opacity of 0.5. Then
padding Y2
X2
X muted forground
transition uh transition color
like this. And then let's give this
border of zero.
So let's give this a div
last name.
get item center
drop to
and there we can give this an icon. So
I'm just going to going to get the text
and the icon.
So let's set the type here text
string
and then icon type of Lucy
icon.
So here I'm just going to say um this is
going to be icon like this.
So import I mean copy this and let's
paste it here. Let's say class name
size four
like this then text muted.
Let's give the span
text.
Then below here, if it's collapsible,
we want to show the uh
want to show the arrow icon. We're going
to use the chevron chevron down icon.
Then we're going to set class name
size four
then text muted forground
then transition as transition
transform
and then we say uh group
data
state
equals to open
rotate
180.
So this is just copied from the um if
you go over to the AI element
the onto
AI element. If I scroll to where we have
so this was where I copied it from
like this.
So I think I made my own mistake here
like this.
So now we can make use of this header
header here. So we also want to show um
loading remember in the two status um we
have if it's streaming we showing
requests creating not. So to show loader
that is actually loading. So I want to
show like a progress infinity progress
bar that keeps on uh moving until we
pass this um state pass the state of
uh impute streaming impute available to
output available. So I'm just going to
come up here. Let's um let's create a
component here. So I'm just going to
call this let's say constant
and two
indicator.
So let's say loading indicator
and let's say react
and that's me.
Let's say downloading indicator dot
display name.
Let's just paste this here. So, here
we're going to get
I'm going to get the loading text and
then also the um
a icon. So, let's just say icon.
Sorry. Yeah,
icon which is optional.
It's going to be Lucy
icon.
And then we can have the loading text
here.
Or we don't need the icon. Let's just
have on a loading text.
This is going to be type string.
So inside here we're going to say return
um div
last name
waitful
adding for
100
medium
BG and background
opacity 50 0.5
shadow do small and relative.
Then let's have a div. Yeah.
And then here we're going to have flex
center
to margin button to
then let's see loader icon. Let's just
import that I confirm
and let's give this a class name of
height for weight for animate
spin
and then let's give this a span
um
front light
text small
and then let's just say
loading text
and then below here we're going to show
the actual um progress bar
nameful
height one BG background
opac 0.3 rounded
[Music]
overflow hidden.
So yeah, this is going to be the this is
going to be the bar, right? This is
going to be the um
the actual
actual progress. This is going to be
have height of full b and primary
grounded full
and then we're going to create a class
animate
progress
progress bar.
So we also want to give this like a time
that just make this look um
look engaging. So I just say class name
I'll say absolute
like an interval. I say top two. It's
not it's optional. If you want to add it
if you don't want you can leave it out.
X small extra small and text and
primary.
And there I'm just going to say constant
time I am
set time
use state
let's just say zero and we can use use
effects.
So just import the use effects. Um
let's say constant interval
is equals to set interval
and then let's just say let's copy this
and then let me just remove it like
this. I say set time
t
previous time is a t
one
like this and let's just give it um
the error should stop.
Okay. So now can just um sorry.
So let's just return
clear
interval.
Let's pass in the interval
like this. So I just copy time then come
over here and let's just paste it here.
And then let's just add S here.
So now we've done the two um loading
indicator and the header. So let's um
combine everything inside here.
So here we're going to say if is loading
and state
is equals to impute streaming
or state
is equals to impute available.
Then we can just say return
Sorry to
two loading indicator
and then we can pass in the um loading
text which is going to be actual text
here from the get to status here. So let
me just get this is loading here.
So this is going to show first then once
the status has move over from impute to
output available then we show the
header.
So now we can show we can say if type is
equals to sorry
type
to type in dot create note.
Then remember we don't want to show
collable for the uh
for the create note. We're going to say
two header
and we're going to say collapsible.
Then we can pass in the text which is
text and the icon which is icon.
And then for the content we just say div
class name.
just going to say uh
I just keep this um
but let's just say div here
like this here we're going to just
output we're going to render the output
here
and then let's just also implement this
here. So here we're going to have the
collapsible
from UI collable
you can say default
open true
and then let's just copy this to header
here
and here we're just going to set this to
true
then collapsible
content.
We're going to also output
we're going to render the output here.
So to render the output, we're going to
come over here and let's create u
let's create the method to get the
output here. So um here
so each of these two are going to have
their own separate components or display
on the um UI for the uh create note we
going to show um the card component that
shows the head the title of the um note
and also the a little bit of a
description of the note. Then for the
search notes, we're going to show um a
list of the notes that was searched. For
search web, we're going to show the text
uh the impute query that was passed and
also the links and the website or the
website that was searched, the names,
and also the five icon. Then also for
the extract URL, we're going to be
showing the URL that the URL that was
extracted. So let's um create a um a
method here. We're going to just say
it's going to be constant
to render like an object
and we're going to give this a type of
um record
um two
UI parts
type and then
we're going to return
react
node
And then we're going to pass in the
output
which is of type any
and then input just of type any here.
So now let's just say equals to this.
So now the first one is the two
the two type of just create not if this
we're going to output
um let's create the if
class name
MB 1.5
and MT1
to create a not component here
the note preview
component here.
So yeah, we're going to just take in the
output.
So that's for the note. We can copy this
and then we can do the same thing for
the search not.
So for the search not we're going to
let's just change this to um let's
remove this
and say wait for
border
border border
opacio 0.4 rounded
large py3
and then px 1.5.
So let's just remove this and there's a
bit dark.
You have the class name
and there is a text small
adding left to and then we want to show
the input here. We say search
for
let's just um
impute
query.
So let's just get the impute here.
So remember the impute if you go over to
search not so remember we pass in our
impute here query. So this is what we're
getting from the impute.
And now we can see you um list. We're
going to loop through this last name.
It's going to be wait for
space none
um padding left zero
ping bottom four
padding top two space Y1
then maximum height
48
overflow
um so overflow Y2
And here,
let's just um let me just copy this out.
Let me just say return.
And then here we're going to say
constant note. We're going to get a note
from the search note too. So this not
is going to be equals to if output
then output
do not
an empty array.
So we're going to check this if array
dot is array
not
then you can see note dot map
then we say li
key
not do ID.
So yeah, we're going to also create the
notes
item.
Yeah.
So we're done with this. Now we can also
create the Let's go ahead and create the
note preview and note item. So I'm just
going to come over here and let's say
two note preview.
txx here.
So the first way to create is the one
for the note preview. I say sorry export
constant
note card preview.
Um I also said the type here the
interface.
props
not cards.
It's a note ID string
to string
and content string.
So let me copy this
react.
Let me just import. Okay, let me just
import FC direct.
So let's import memo.
So just a not preview
display name is equals to
like this. So here we're just going to
return
a div.
We're going to give this row of button
first name.
Let's flex column
grab two to
adding um four B muted
rounded
and the shadow
small border.
Um border
then hover
shadow MD
transition.
Let's give this all then cursor pointer.
So now we also going to let's just get
the title
content
note ID
and remember we need to also get the
the constants note ID use
note ID
book hook let's import that so we're
going to get the set note ID so now Here
once we say on click
is equals to set note id
not id.
So you see h4
you're going to pass in the title
and ping we're going to pass in the
content.
So you say class name
font semibold
xxl
line
one.
Let's also add class name here
x small
text x muted foreground
and line clamp three
like this. So we done with the cut
preview. Let's just go inside the two
call and then we can pass it here.
So I'm just going to pass in the out the
not ID. It's going to be equals to
output
note ID
title
output
title
content
output
content.
So let's go back to the um note preview
and let's also create the other
component.
Uh let's also create export
constant note
item preview.
There's a memo here
display name
and let's paste this here. So yeah,
let's just return
button.
So let's also copy this interface
and let's paste it here.
So we don't need the content here. I
just say not add them
and then just say SC
and paste it. So yeah, I'm just going to
say let's also
copy this
here too.
So note ID
sorry
note id then the title.
So here we just say um spam
title
and let's call the icon
u
sorry f test line.
SQ is a class name of which
five kite five
and then let me just copy this and click
like this.
This case is a class name.
I'll just go to recent notes. So stupid
glass
like this
flex with um hover um rounded and this
size.
So that is it. So let me just copy the
note item preview. Let's go back to two
core
and then here I'm just going to just
let me just um I'm just over
I'll say um the not ID
not do ID
by 2
not dot I2
So we have done we are done with this.
So the last one is the search web search
and um the extract. So let's um
implement this for the search. So I'm
just going to copy this
and there search web search.
So for the website, I'm just going to
remove everything here.
I'm just going to remove everything
here. So let me just empty
and then let me just copy this. The web
search and the extract URL is going to
have the same
um the same component. So what I'm going
to do, I'm just going to create a
component. I'm going to call it search
extract
preview.
And this will take a pipe
web search
and impute.
Impute
um output output
request to output.
So let me just copy this and also do the
same thing here. So instead of web I say
extract
web you heard of
like this. So let's just copy this and
let's go ahead and create a component.
So I just say to
touch
extract
xx
review.
So I say R A S C E or let's say export
constant
search web sorry this should be capital
and then let's say SC import FC
and let's set the type here interface
type is going to be to web search
or extract
web URL.
Impute
any
output
any.
So I just copy props and then paste it
here.
Let me just uh quick fix this
and then
here.
So copy this
dot display name
and let's paste this here. So here we
can get the uh type input
and then output.
So yeah, I'm going to say constant
result
is equals to output
dot result
or empty array. So the result if you go
to search
web search remember we return results
here you can see it also in the extract
URL we also have results. So both of
them has results.
So that is it here.
So let move this up here.
Now we need to define the head text.
header text
if it's um type is equals to a website
then I'm going to say
query
I say impute
That's W.
I see your ass
in
your
train.
like this. So if you check extract URL
remember the impute is URLs and website
impute is query.
So I want to say count
count text
is equals to just copy this
paste it here.
So I just say use
um the res length
length.
So there's no need for this
source.
So the website use how many um how many
URL how many um
the result length. So you use the
sources how many sources you got the
content from. Then why this I just say
found
pages
I'll just say result length
is. And the last one is the item.
The item text
is going to be equals to
we say um if
type
is equals to web search then we can say
um
item dot title. So I'm just going to set
the item here for now. Let's say item
here and then item URL
like this. So yeah, let's have our
to say P tag
and we'll pass in the header X.
Let's have a class name.
I'll wait for border
border um border
of 0.4
rounded large
then padding y3 padding x 1.5.
So let's have this here again.
It's a class name
to have empty
left two
and then P tag we're going to have class
font normal
text small
and then text blue
500 here
and then yeah I'm just going to pass in
the content of the pound text.
And here we can have the URL. We're
going to look through the results. Say
class name
say um
X
left Z button four padding top two space
Y1
and then maximum height 48 overflow
Y2
and then let's say array array
dot is array
result
map sorry
we need to say result
do map
we can get the item and also the index
and now we can say I like this.
Let's pass in the key
index
and then we have the a tag
and then dot URL.
blank.
Let's have a class name here. It's a
flex item center
graful.
over on the line.
X
blue 500
over text blue
let's say 400
then if item do five icon
let's display an image tag
This see
five
icon.
Let's have a class name.
Yes. the weight or height for
bounded
small.
So yeah, we can just say span
and then we can just say item you can
get item text and we just pass in the
item here.
Let's also let's just close this tag.
And let's add the class name
text.
Let's give this 13 pixel.
And the last we're going to also set an
icon here. External
external link
class name.
Wait for wait for
So we are done with this.
So let me just copy this. Go over to two
core
and let's import this.
So great we are done. So now let's
render the output um here and there. So
I'm going to do that here.
So I'm going to say constant render
output
is going to be equals to
if state
is equals to um output available.
There was a constant render
renderer is going to be two
renders
render it's going to be we're going to
set a type.
So if you pass in the type is like an
object we just get the particular output
it is. So for create not we just get
create not search web search or extract
URL.
So
we're going to just return
render
else
say if
if there's a render then can just say
render. Let's just change it to
renderer.
And then we can just pass in the output
and then the input.
There we can just say JSON stringify
output
and then let's give this a class name
MT2
like this. So you can say if
state
is equals to output error
let's return
Save
our text.
Just say class name
X red instruction instructive.
And then let's say return.
No.
So, let's just copy this.
Come over here.
Then let's copy this.
Let's come over here and paste it.
So, we also forgot something in the um
to indicator. We added a class called
animate progress. So let's go to global
CSS and add it here. So I'm just going
to paste it here. So now I've pasted it
here. You can see the key frame progress
bar the and transform transform 50%
translate X0 and 100%. And then we have
this to set to infinity and the W side
50%.
So if you save that and let's just
remove this. So now we are done with our
two
core. So the last we're going to work on
is the message action. So I just create
a component
action tx
message action.
So I just copy this
from over to
to message
and then to action should be after
the actual message. So I just put it
inside there.
Let me just import this.
So let's test this out. So I'm just
going to go back
So, let's also add this to the um
homepage too. So, I just go into my
title and let me just copy this. Come
over to home
uh main section.
And let's just paste it here.
And let's set this to true.
Let me remove the key. Let me import
this.
And then inside the um chat, let's copy
this ID
inside here. I'm just going to paste it
here.
And let's pass key
ID ID ID here. Let's import these two.
Then inside the main section, we going
to just get the ID here.
See the um the drop down here the create
not select you can see create not here
and we can cancel this and this will
clear we can go over to charts AI chart
and if I click on charts
let Wait for this to open.
It has open. I'll just say create a
note. Create
a note
about
um
AI
and let's see if this is going to call
our create note to
so it's creating a note and we can see
the response. So this is working fine.
So if I click on note, we should be able
to see the notes. This is great. This is
great. So we're going to go ahead and
then work on the actions.
So now if you look at this now, we can
see that the page I try to save this
page again and it will reload this page
to render next year's call this page.
And you can see that we have moved to
the single page um single chart page.
And you see why the reason why we had to
add the recover chart input and I uh the
reason why we had to put this um replace
the state of the URL uh because
Immediately I save this page and it just
called this fun and related to this
page. So we need to be able to call the
endpoint to fetch the chat the message I
mean the message by this uh chat ID
here. So we're going to implement that.
But let's first of all complete the uh
the message action. So I'll just go to
chat me to message inside the chat
folder and then let's um handle the
message action. So I'm just going to
clear this.
Let me clear this so we can see this.
I'll just clear the ID. And if I clear
the ID, this will take us to this chat
page.
While that is loading up, let's
implement the action. So I'm going to
set key here. I'm going to set this to
be action
and I'm going to say message
id.
Then we're going to pass the message
which is going to be equals to message
and then it's loading is equals to it's
loading.
So let's go to the message action and
let's make use of this. So inside here
we're going to define the process u
interface
props
and then we say message it's going to be
UI message
let's import that from sorry message
let's import that from AI SDK so I just
say import
from
AI I I'll set type here
UI message
and then I think we pass the it's
loading. So I'm just going to set it's
loading.
It's loading. It's going to be it's
going to be boolean. So I'm going to
just pass this here and then let's just
say props
and then let's get loading and the
message
and then inside here we're going to
let's come down here and let's call the
action. So the action we're going to
have the copy and also save to note. So
let's import actions
from AI elements.
And then this is going to have a class
name
of um MT2. And then we're going to say
text space.
And then let's have action.
And then let's have a class name.
I'm going to say this height autom.
So if you don't want to add text in the
action, you can leave it like this.
Going to just set the icon here. And
this just give the icon. But I want to
give this a a text to like a button. So
this is going to be PM rounded through.
And then we're going to have pointer.
Let's give this title
copy.
And then we're going to set on click.
Let's just define a constant on copy.
Let us copy this and paste it here.
And then inside here we're going to have
the copy icon. Let's impose copy icon
for
and let's give this a class name of size
four
and let's give span
copy.
So let's just copy this action and then
paste it here again.
And then we're not same but this is
going to be save to note. Sorry. Save as
not.
And here instead of copy, I'll just say
arrow pick down.
Import that.
The picture icon.
And then here we're going to change this
to save
as not.
So we're going to change this to unsave.
And then let's copy this and let's have
constants unsave.
Now let's implement the copy first. So
for the copy I'm going to get the text
from the message. So remember the
message is message is of type UI message
which has the part. So we're going to
get the messages from the part. So I'm
just going to come down here and I'm
going to say first of all let's say if
it's loading
if this is then and also if message dot
row is equals to user
then return no we don't want to show
action for user messages only for the AI
message. So here I'm just going to get
the text. So I'm going to say constant
and get text.
Then we're going to say message part.
We're going to filter messages with
text. I say a filter
bit do sorry
bit dot
type is equals to text.
So let me drop this down
equals to text. Then we're going to map
this
map the list to the array. And then
we're going to just get the text
here.ext
like this. Then we going to join this.
And then we're going to trim.
So now we can get the text from part.
Now let's set the copy. So I'm just
going to say let's set here constant
text is equals to get text.
I'll say if there's no text
then just return
to dot um
I just say to do error
no text to copy
and then let's say a navigator
let's add async here
navigator clipboard
dot write text
and let's pass in the text and then
let's say close
success
copied
like this. So we have implemented the
copy method. So let's implement the
asyn.
So um I save we're going to have we're
going to call our use
uh let me do that here.
So if you go over to use not
we have the use create note here.
So I'm just going to say constants
is equals to use create note import
this. So let me import the use uh
use note and then we can get the uh we
can get the the mutate
and there let's just say let's also get
this
no text to save
and then we can say post
promise
and then we can just uh return
create not sorry mate
so we need to we need to use the
async
so I say mutate async
title is going to be I'll just say
untitled
And then content
it's going to be text
like this.
So now I'm going to
I'm going to make this here
loading. We're going to say saving lot
on success
on success.
Sorry, not on success. Success.
Yeah,
you can see not save
an error.
error is going to be filled
and to save not.
So like this. So this is uh fine. So we
done with this now we can test it out.
We're done with the action. So let me
also wrap this into memo.
So react
dome
and then by this and just say message
action
do display
like this.
So let me go into our message now. This
should work.
So let's test this out. Then we can go
ahead and set up the endpoint. So I'll
try and send a message now.
on high what
um what is AI
for
okay server is let's check
the chat page so let's go into chat page
error occur
function
Okay, this works. Let me just try and
reload this page.
You can see that this is actually the on
this. So, let me try again. Let me
remove all of these charts.
So why this is still working? Let's just
go. Okay, let's try it now.
Hi,
what is AI about
work now?
So let's wait. This is still loading.
And now we can see the icons the actions
are showing.
Just tell me
let me make copy and we can see this as
copy.
Let's use let's um
what is llm? So it should give us a kind
of like an information so we can save.
So this one works. So stop. Let's click
on let's click on save not.
And now is saved and this has open. Then
we can see so you can see the not here.
You can go ahead and change the title.
If you want you can use gen the title
but just leave it like this. And we can
just basically change it.
What is them?
I'm going to just save this.
So this is working. So now let's just go
ahead and then fix this. Copy this.
Let's go back to a single page chart.
And then let's just
let me call this a single
charts.
Let's just leave it as page and then let
me paste it here.
Copy this
and let's uh let's get the chart from
here. I'll save this. So we're going to
get it from the use param. So I'm just
going to convert this to use
point.
And then here let's move this up.
Let's say constants params is equals to
use params
and then we can get the chat ids
dot chat ID
as string.
Okay, it's not much we can get. We can
guess the pars from here from the actual
page. You can get the ID. So, oh, let's
just leave it like this.
And then I'm just going to just change
this to chat ID
like this. So, u we going to go ahead
and um fetch the initial messages.
We're going to initial messages and when
we are loading the initial message we're
going to show we're going to set this to
true. We're going to set this to the um
is pending or loading state. So if you
save that this will just take us to the
single chat page. You can see next is
going to um it's going to compile this
page and this should us from here.
Okay.
So let me just if I try to refresh now
you should should land on this single
chat page
single chats
and now we in a single chart you can see
the you can see the ID here. So now if
you refresh this you'll be seeing the
history the uh chat messages. So let's
just go everything out and then inside
the futures let's create and use chat.tx
CX
then we're going to say export constants
use chart by ID
and then let me just we're going to pass
in the ID and we're going to pass in
anybody.
So I'll say ID string
ID string
some error
then you can have the enabled
audience.
I stop. So let's return use query
from stock create query.
So let me change this to use query not
use query client.
And then we're going to pass in the
query key.
We're going to call this chat and then
pass in the ID.
And then the query function
async
and then constant
response
is equals to await API. Let's support
API from
from H RPC charts
charts
and then this require ID
then say get
arms
param ID.
So if response
okay
let's throw a new error field
to fetch
chat
then we can say constant
is equals to our
response
JSON
and let's get data
Let's say our return
data
and there we can say
enabled.
So let's also do for the all charts
constants use charts.
I'll just copy everything here.
Paste it here. And then instead of ID,
I'm just going to change this to chat.
Then I'm going to just remove this.
Remove this ID.
Remove um this
and then remove this.
Okay, now this is working now. So we can
make use of this inside the single C.
Then we're going to create a component
that display all the chat history. So
let's just go into uh the chat ID page
and there's a constant
is equals to use chat ID.
Let's import this.
And then yeah inside here we're going to
pass in the ID
this chat ID
and we're going to say enabled
true or we can say enabled
chat ID
then we can say data and it's loading.
So we can pass is loading here
and let's get the initial messages. We
say constant initial messages
is equals to data dot messages
empty array
one.
So let's pass this here.
And then let's pass initial messages
here.
Okay. Why is he trying some error?
That's error.
Okay, we're having some error here.
Okay, this wants me to show some show
the type here.
So, response. Okay, data is empty.
So let's show the uh the request and
then also the u the response. So I'm
just going to set here.
I don't know why it's not working for
the chat or it's working for the note.
So I just going to set this
save this and the error should stop.
So if I save it, you should be able to
see the chat message here to see the
loading. Then if it's loading, we should
not show the um get um greeting message.
So let me just uh go back.
Let's go into the chat messages
and then if it's loading
we can say um if um not loading.
Let's see. So now let's uh let's try and
um this is a new message. Let's try and
send a message. Hi.
and let's see if this will work. So I
just go back to the actual page and
let's see.
So while this is loading, we need to
also um Okay, it's working. So we need
to also have um a button here that shows
to start a new chart or also to click on
to toggle or to view the chat history.
So we're going to go ahead and modify
the header component. So let me just try
and reload this page now. Let's see.
So while that is loading, let's go ahead
and modify the uh the header component.
So we can have this component for and we
can see it is this is loading up and we
should be able to see the message.
So I'm just going to come over here and
let's add action.
Let's set this to boolean
and undefined. Then we can get it here
and say title
and then show action.
And then here we're going to just say um
if show action
then we can have a div
pass name
CN
import it and then we're going to have
wait for flex right center
justify between
and then we say if open
then we I say waitful
wait for
a maximum waitful
and let's give this a padding
zero
z
of 50 pixel.
So here
going to the chat
and below here we're going to have
button here.
So let's have a div.
Let's close this
and then let's give it a class name.
Let's
it center
to and let's have a button
replicate the button.
Let's import it. And here we can say uh
variant
ghost
size small
name
pointer
and then bg muted
opacity 0.1.
So I'll just copy this
and paste it here. And there we can give
it a new chest
and then icon of I
add line.
So let's also add the icon for this. I'm
going to say R I is three
line and let's give class name
size 8
and then let's say uh
statist.
So let's add our on click here
and this is going to let's import
constant router
equals to use router
from next navigation
and constant on
equals to router
output.
chat.
So let's copy this and let's just paste
it here. Then for the it will toggle the
uh chat history. Remember in the go to
use search sorry use uh local chart
remember we had the uh is history open
and then is this toggle on toggle
history. So I'm going to get that from
there.
So let's just go constants
use local charts
and then let's get to on top history.
Let's copy that and then let's come over
here
and click.
So we don't. So let's copy header.
Let's set here for by default here.
So copy header. Let's go into our single
page and chat. And let's uh let's just
cut this.
Create a div.
And let me put a class name here.
Relative
weightful.
And then let's call the header.
Let's say show action true.
Then we need to pass the title of the
chart. So I'll get the title here.
Data title.
So just copy this and let's uh paste it
here.
So, we're going to copy this. Go over
inside the single chat page.
And let's also pass this here.
For this, I'm just going to let's uh
let's import this.
I'm going to remove the title.
So let me also
if there's no title.
Okay, let's just leave it like this.
So now you should be able to see the uh
you should able to see the header here.
So let me reload this.
So let's say show I think we set it to
false. So it's not going to show the uh
the actions on the homepage.
So if you want to see the history so
let's also create the chat history.
Yeah. So I'll create a component. I say
chat
chat history.
A s
let me go back to the header component
and then let's fix this on mobile view.
So if open this
we have this list this here.
So wishful. Okay, I think I'll just say
this to large
like this.
So, it's working. So, I think uh this
can say width eight, height 8.
Let me see if it will work now. Yeah,
it's working. So, I just copy this
change to width eight, height
like this. So we can have the new charts
and then the chat history.
So let's go and let's go and work on the
chat history. So the chat history is
going to be if you click on it's going
to pop up like this sidebar.
So I'm just going to come here. So I'm
going to say constance router
is equals to use router.
Let's import from navigation.
Then we're going to also let me let me
make sure this is set to use clients.
And then we're going to also get the
the use sidebar.
And then we're going to set here to open
to get a side bar is open. Then we're
going to also get the
the use local tok
and then we're going to get sorry a
mistake here. So I'm going to So I'm
going to get the is history open and
then the toggle on toggle history open
and on to history
and here we're going to also get the
we're going to import the use charts.
So let's import the use charts. This is
where we're going to get all our charts
to get the data and the pending.
Then constants
chart history
equals to data empty array.
So now we have constant on routes or
handle
on routes.
We want to pass in the chat ID
and then we say router
push
chat slash
um id like this. So now we're going to
give this a class. So let's import okay
so not import let's say class name and
let's import cn
It's a fix
copy zero left zero
height for weight 80 white
on dark mode we're going to say uh bg
background
I'm going to have border right then bord
color border
I'm going to give this a Z index of 9
and transform
transition transform
duration to this duration of 300 then
easy
easy in out.
So now uh we going to have let's see
here
say if site if open sorry
if open
and let me add comma here
if open and it's history open
then we say left
64
else left
zero
then we
Um is history open?
You say translate.
So x
0
x -
x4
like this. So yeah, we're going to
define the header of the of the chart.
Say class name
item center
justify
or between bx3 by y 2.5
bordm and then color of border
there we're going to have inside here
we're going to have in these two tag
I say charts
history
and then let's give this a class name
X uh
is
B semi
like this.
So yeah, we are going to uh I'm going to
give this a button
and I'm just going to say I close
or let's just use X icon.
Let me give it a class name with seven
height seven or let's say height six.
Let's give the size of um icon
varants
post
and let's give a class name I say height
for yeah
on click
on toggle history.
So it's going to just close the uh
history. So after this if we're going to
have the list
uh the items so we say class name
waitful
one
justify center
maximum uh sorry minimum height of we
give is 40 maximum height
say cool
100 pixel so 100% minus 48 pixel
and then overflow
overflow y2
then ping button five here.
So now we're going to say if is pending
then we're going to show uh the loader I
loader
I feel
let's give a class name
with 10
height 10
animates
spin
text primer
So yeah, we're going to say else if chat
history
do your length
is equals to zero
then we can say uh let's say div
no chart
Then else
we're going to create a list
sq is a class name of width 4
space
space space y 2.5 p x2 and then padding
y3.
So let's um loop through the chat
history
chat
and let's call this item
key is going to be to chat id
and then sorry here we're going to say
button
let's give a small but a class name
waitful
adding X1 adding Y 1.5
and then say P Y3
sorry not P X center
to rounded large
hover from BG
then cursor pointer
Let's get this transition color
and let's say on
route
chat do ID.
So yeah, we're going to set the title
and also the icon. So give this anat
um AI
line icon. Let's give this a class name
of a width for height for the margin
1.5.
I say let's give this a test color too
new for
I'm going to give this a div
class name withful
text left
let's have a history which is going to
hold the title the chat title
title
and then a p
that will hold the uh the time so I'll
say Format
new dates
charts
doc created apps
um
a y.
So let's import and format from date
function.
We install this function. Yeah. import
format
from
date function
like this. So let's give this a a class
name
text small
on dark mode we have text white
opacity of 0.8 It's one semiode
and then say truncate
X
ellipse then white space no wrap maximum
width excuse me maximum width
270 pixel
then margin button one let's also give
this a class name
and I the text extra small
text muted
for like this. So, we're done with this.
So, I'm just going to copy this.
Let me just move this to the top.
So, move this. Come over to where we
have the main content here. I'm going to
just add it here.
So, this is really going to show for a
um the dashboard.
So now I think we are
we are done with this. So let's test
this out and we're going to go ahead and
I think I'm having some issue with this.
So let me just go back to route
chat simple chat.
Let's just change this to
and let this
because you can't see the
So, let's uh refresh this again.
So, I have some issues here. So, if you
go over into the use chats, let's go
straight to use chats. Sorry. Go to
features.
Click on use chats. Here I was able to
just get the data out of the response
like this and just return it like this.
So like this.
Then inside a single chat page if you
come over here um I was able to just get
a chat data like this and then just do
it like this. So this work. So I also
encountered some issue where um the chat
I sent is saving as the agent. So here
is the course. You can check that too.
Just go inside chat the API. Yeah, the
rout chat uh API and scroll down here
just add generated message ID and let's
import generate U ID. If you scroll down
you can see that instead of using M I'm
using the message from the user.
So I'm just going to change please
change it to M.
like it if not the agent will also the
assistant will also receive message will
also receive as the user text.
So
let me just remove this.
Okay. So I can try this now out. Let me
scroll down
and let's click on new chart.
Make sure you change make all those
changes and remember to add this. If you
don't add this uh you'll be able to
you'll be seeing um no ID for some
message and that's why we added this. So
since we add this
is going to use this fun to generate the
ID. So, uh let's uh
let's ask
what's your name?
Let's wait for the response. The
response here.
And we can see the reply here.
Yeah, we can see it here. We can see ID
set here. If you remove this, this will
not show any ID. Now, let me try this
page because I was having issue. My
message was saving as a so. So, I'm
going to refresh. So, it should take us
to the single page chat single page and
to make sure the single page single uh
chat ID is fetching.
So let's see if it's going to fetch.
See, we should wait for this to load.
Now we can see that it has returned the
response. So let's confirm the message.
What's your name?
And now we can you can see we can see
the AI message. So this is working. So
you can see what can you do?
And then this is going to
it's going to give us a response here.
And if you click on chat history, you
should be able to see uh the what's your
name the chat history.
So this is working. So let's u let's go
straight to home. So I'll click on this
and go to home. Now we want to make sure
on the home page when we chat we are
going to hide um some of this. Uh so
let's go straight to home. Let's click
on common clip on main section.
So remember we have this chat impute
interface. So when user type inside this
uh impute
we want uh
we want to hide this
this uh text here. I say everything from
here want to hide this
div. I want to hide this div. So the
user only see the chat interface
because if I if I okay let's open now
let's go to home if I type you you will
see the problem with us having this um
inside where we have the chat
like I mentioned earlier on this chat
interface when the user type we are not
navigating to the single chat page we
are still on the home page
So we just want to hide so the user does
not know that we still on the homepage
user make reload or refresh and then
user be navigated to the chat page the
single chat page. So to hide all of this
we're going to be using the uh state
sorry the URL we're going to use to
handle that. Um we can't get the chat ID
even when we if I go into chat input we
can't get the chat ID even when we
replace this because um next year
doesn't know that we have updated the
have changed the state of the URL. So we
can't use the use search parame
a hook that will help us to add it to
the URL. So once this submit it like
saying like this view is equals to true.
So with that we can get this we can get
it the if view is true then we hide in
the main section we hide the div and
then we hide this recent note. So let me
just try it out now.
So if I send a message I'll say hi
how are you?
And you should see if I click on enter,
you should see that this is still going
to be uh you can see it's loading. If
you hover, if you if you open this,
we should see that it's going to send
the message. Yeah, but we can't see
anything because we we having only to
true. So we need to toggle this to set
this to false when um the user send the
message. So let's go ahead and create
the hook to handle that issue. So I'm
going to go into my hook
and then here I'm going to going to call
this view use view state
and it's going to sim. So let's copy
from the note ID. So I'm just going to
copy this and come over to view state
and let's paste it. So yeah, I'm just
going to change this to um view use
uh view state.
Paste it here. And here I'm going to I'm
going to change this to um a chart view.
Just copy this.
And then I'm going to say underscore set
is chat.
I'm just going to replace all of this
with it.
Here I'm going to say view
and instead of string as string I'm
going say as string boolean
let's remove the string.
So just say it's to first I'm going to
say dot with option
and then shallow.
So let's change this to
boolean.
I'm going to say set is
chart view.
So copy this and let's replace this with
it. Then click chart view.
Let's copy this and replace this with
it.
So I'll change this to file.
So now you're done with this. So let's
go into let's copy this. Go into chat
impute
and then scroll up here. Let's call it
constants.
Then import it. Then I'm going to say uh
set
set chat view. Copy it and scroll down
to where we have
here. Let's just say true.
And then let's pass it here.
Then let's go into the main section,
main section in the home folder. Home
common folder.
And then let's just say constant. Let's
import it.
Sorry, not this. Use
use state.
I'm going to say is chat view
and then I'm just going to copy it. I'm
going to say uh
show action
and I'm going to also modify this. So
wait, just copy all of this here. I'm
going to import CN.
Let's import from YouTube
and let's paste it. Sorry,
let's paste the class.
And then I'm just going to say if not is
chat view.
So if it's not you then then we can make
use of these colors.
So now we need to hide this um div. So
I'm going to also copy this. If not
chart view then there's no need to show
this um div. So I say if not chart view
if not charge view then show this um
this text is this uh how can I help you
text and the and give yourself then we
can also do the same thing for the note
so I'll copy this then below here I'm
just going to also hide this two if not
view then this will show but if there's
no point showing
So I'm just going to copy this and I'm
going to set this.
So if not chat view then set this to um
if if is true then set to false. If is
false
and it will just set it to true.
So this should work. Let's see. Let's
test this out. So I'll go to my
homepage. I'll go to the home.
Let's go to the home.
So let's let's try it again. So let's
just ask someone and see
what's up.
And you can see that it work. So uh if I
check the state here,
you can't see the view, but this is
working. This is working.
I say what's the
news
about text? Let's try search. Sorry, not
tech.
No
tech.
Yeah. What's the news about tech?
Okay. I'm just going to say um latest
news on tech.
Um let's see. it to search.
Okay, it's as soon as you say yes, go
ahead and and search the web
there. You can see
okay let's see why is not working.
Oh, this is not this is not how it's
supposed to work. So, let me go straight
to
let's check the
let's check the chat API.
We have the web search to search notes.
Search notes.
Sorry, web search. Web search
[Music]
website.
Uh let's check prompts. Check the
prompts again.
Yeah, everything is set. I don't know
why it's not finding the search. Okay,
let me just search for
the latest
news.
Yes.
What is wrong with this?
Let me try new chat.
So let me try it again. I search for the
latest
news.
Yes.
Okay, it's working. We can see searching
the web and then it's giving us uh the
feedback summary results.
So this is um this is working this is
working.
So the search is working. So let's test
out the URL extract URL. So I say open
AI
open AI news.
I just find
let's just copy this URL.
I just say
extract your extra content
extract extract content from this URL
extract the summary extract summary
content
from this URL
and let's see
this is going to call the extract the
extract web URL
Yes.
So, it's trying to use web search.
Well, you gave it a new uh request and
it's searching instead of extracting
making use of the extra.
So I think something is wrong here.
So I'm just going to try it again.
Let's try it new chat. Let's see.
I'll click on home. Take me to home. Let
me paste this again. I take extra
content from this.
Let's see.
Yes.
Okay. It's working as I say um past on a
new chart. So you can see it's working
from this contents.
[Music]
So this is working. This is working
fine. You can see that it's working
fine. So, um let's try and then let me
try and select web search here.
Um
what will I ask? I'll say
what is MPC
latest
updates?
So I'll set the to web search. Let's see
if Okay, it's working. You can see it
went ahead and um it forced it to um
search the web.
You can see
and then it went ahead and find latest
information on MPC. So you can click set
website and this is going to so let's
find find not find not
of AI
let's see this is going to use the f not
or the s not too
I don't know why asking for you
separate.
So there's something wrong. This is
still um trying to still trying to work
on the previous message.
Okay, I think this is where the problem
is. Let me remove this.
I will save this and then
Okay,
I think we don't have any issue here.
Let me try and test it.
Okay, I say search for my notes. Okay,
let me just search
search for AI notes.
Let's
see if it's going to work.
So, this is still giving some issue
here.
Let me try it again. So, I just added
this um this part here. Let's see if
this is going to look the last user row.
Okay find
the im
just
in min.
Okay,
something happened.
Select trigger
use.
So it work find um where I have my I
don't know why this failed.
right component.
Let's check the chat input.
Let me reload this.
Let's also let me look at the prompt
again. Okay, something is wrong. You see
two status.
Okay, let's go to two
two call. Sorry, two status.
I say not length.
I see this going to try
search. I can see that he found the not
here.
So I'm going to try and ask you to find
the not
um I think um let's find out about LLM.
And this work. This work. It's okay.
Fine.
Loading video analysis...