LongCut logo

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

email

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

email

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

email

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...

Loading video analysis...