Tejas Kumar

UI Engineering for the AI Age

React Day by Frontend Nation 2025 / 37:41

Watch this talk on YouTube

Transcript

35 paragraphs

This is an automatic transcript of the recording above. It is published in full and unedited, apart from correcting names the recogniser reliably mishears. It will contain mistakes.

00:07I'm Tejas Kumar and I've been building on the web for over 20 years at places like Marcel, Spotify, Zeta and more. Today I'm really excited to talk to you about the UX in in an AI world about how to create truly great user experience in a world that is maybe changing because language models sometimes can output really long series of tokens or words and um how do you handle that? Like do do your users wait a really long time? Um do you stream stuff? How do you do that? Okay, but then when you're streaming the output of a language model, what if it's structured out? What if it's JSON? JSON.parse does not parse um partial JSON. And so then do you just leave them waiting until you get a full JSON payload? But this can be really unpleasant. So in our talk together, we're going to look at how we can use UX, how we can create UX that is highly valuable for everybody um in in in in age of AI where topics like streaming and full stack applications are becoming more trendy.

01:08To do that, we're going to actually look at a full stack application like server, client, etc. We're going to look, this is the basic example, and this is the UI. So, I'm going to ask a question like, give me a list of 20 cheeses and nothing happens because this isn't implemented. Let's quickly open the console and just keep it open. And from here, you see me, how funny. But now, let's go to the editor and orient ourselves a little bit. So, we have this file, which is literally just called basic.tsx. And it's exactly what it sounds like. It's just a basic file. Um, we got a chat response is chat loading. We've got some use state. We have a function fetch chat response which is not implemented but we will. And we have, you know, the I can change things instead of ask a question, ask a query and it just works. So this is very much like real time. Okay. So now what we have to do is implement fetch chat response. But we also have a server. Um, and this server is just an express server. So like we import express from express we import n for some environment variables. We listen on slash and we say hello world in fact and we listen on 5374. So we can actually just open this just to show you the the server and um 5374 and it says hello world. Wow. But there's nothing implemented and together we're going to implement this. So what we'll do is we'll say hi world and just to show you that it's all live. So now

02:26we have it. Okay. So step one, let's implement our function to fetch data from the chat endpoint. And again, this is we'll maybe start with the UI and um quickly send our our query. So let's come here and we'll say, you know, um actually we should set is chat loading. We'll set all this error stuff and then instead of try catch, let's just do fetch. Um let's fetch from / chat, which doesn't exist. We'll make it exist. And we'll, you know, it's a post request. we have JSON and we'll send the body. Okay, so very straightforward. Um then we serialize to JSON. We'll catch the error and we'll set the loading false. This actually looks great. This is very very good practice. So now um let's go implement the server side of this. Uh in fact here let's just test it quickly.

03:14We'll say sup and okay well uh corores is the first problem. So let's go add corores. And to do that we'll just app do use and we'll just use course. just import cars from cores and we're good to go. Now we can say sub and we get a 404 because our route isn't implemented. So let's go add that. We'll do app.post/ chat and let's just return, you know, a nice JSON string uh of responses. Hello world. Let's try that. We should have hello world now. Um great, it says hello world. In fact, look at that. It always says hello world. But now let's include the question in the response to make sure we can actually read the question just like that. Okay. Um I have a typo in response but anyway um the answer is not the question. The answer is something um yeah the answer is sup. And let's now take a look at what we get.

04:07And so when we send the question um sup oh we get an error and it's a 500. It's a server error. So let's go take a look at what actually that error is. And uh it's cannot read properties of undefined reading question which means our JSON body is undefined which means why is this undefined? Well, we need to probably add express.json as middleware. And now we should get the question. Let's just double check. Perfect. It's in is in response to sub. The answer is sub. So it it totally works. Let's try other question. Perfect. It's working. Let's maybe fix this typo because it's going to drive me absolutely nuts. Great, it's working. But obviously there's no AI here. We should maybe add some AI. So let's import um OpenAI from OpenAI and like actually answer the question here. So um we can get rid of all of this. We don't need this.

05:02Instead, we'll just keep the question from the body and use AI here. So we'll um you know, we'll do something like const. We'll instantiate OpenAI and we'll make this async and um just call using the SDK and include our question in the messages and serve the response. Pretty nice. Um let's save this. Try again and let's answer. Let's enter a question. Let's open the network tab to see what's happening. Let's say hi, what is cheese? Click ask. And look at this. So just waiting now. Wow, that took so long. That was really unpleasant. It took like a whole Let's see how long this took. It took like 3 seconds of idle time. It gets even worse if we ask for like a longer thing like an essay, right? Like write me an essay on the history of cheese. Let's Let's send that and let's watch.

05:56Wow. Wow. It's just taking forever. And that's kind of the problem with AI. It's like you don't know how long it's going to take and you want to make sure your user is engaged the whole time. That took 15 seconds. I mean it's a long body of text but 15 seconds. That's that's wild that it would take that long and we need to create better UX than this. So how can we do that? That's the question. That's what So let's um maybe instead of creating like one big thing and sending it once as JSON uh or as the response, let's just stream it. Let's do stream. And now it changes because we don't get a response, we get a chunk. And so what we're going to do is for each chunk of the response and and it's an async iterator, so we can for away and for each chunk um we write the chunk to the stream. We don't resend. We don't just res.json. JSON it we write incremental chunks and then we end when the for loop is done. Yeah. So we're just like writing in a stream.

06:58Let's uh and and of course if there's no like if the LLM outputs like something undefined we just you know just u continue the loop and we'll just be like super defensive and add like question marks here just to make sure if anything's undefined continue. And now let's try that again. Let's keep the same prompt. Write me an essay on the history of cheese. And let's ask. And look, you can already see it's writing. That's so awesome. It's writing on the network. The UI isn't updating because we haven't updated the UI yet. But like it's a multiple second thing, but you can see it being written to the network, which is so great. And finally, we have unexpected token because we're trying to parse JSON, but it's text. And so, let's maybe update the UI. Let's start there.

07:39Instead of um like res.json to serialize, we'll do res.ext, text, you know, we'll we'll just serialize this to text instead. Um, and so let's yeah, let's just do res.ext right here. And we can maybe yeah, just set state. Let's try that now. Let's let's keep maybe the same prompt um history of cheese ask. And I love it. I love seeing data being like written um here to the network. It's already progress because it's something engaging. You know, the UX is already improving even if there's nothing on the screen. So, in a couple seconds, I guess, um, we're going to have or there we go. So, 16.9 seconds, we have text. It's great, but a user is not going to browse the network tab open all the time. So, we need to like put this in front of the user as soon as it becomes available. And it does become available really early. So, the res instead of serializing to text, it expose the body of a response is a stream. So, we can now read the stream. Literally, the body is a stream. So what we can do is we can let's get rid of all this and let's just do like res.body and we'll get the reader of the stream. Each stream comes with its own reader and we'll create a text decoder because the stream is encoded text encoded as a bite array and then what we're going to do is we're just going to read which returns a promise from the reader and when the promise resolves we're going to process the text. We have a function called

09:05process text and it gives us am I done and what the value of the current chunk is what the encoded value is. Okay. So, um, now if you're done, we just return. We want to just stop a loop. That's what we want. We can actually get rid of this whole thing. Um, and just return. While we're not done, then first we decode the text that's encoded as a bite array. And we don't really need this like pipe pipe thing. So, let's get rid of it. Um, we don't Yeah, this is not really useful. And so, we decode the bytes in stream mode. And then as chunks become available, we append them to the state to the chat response. And then when we append the state, we call reader read. We call reader readad again. And we pass process text back into it. This is a recursive function call. We're calling process text inside. So we keep calling process text until we return and we don't call process text again because we're finished. Does that make sense?

10:02It's just a recursive loop. And so now that we're appending to the state recursively, we should have some great streamed chunks in the UI as well that are recursively written. And look at that. Beautiful. The user's immediately engaged. This is so much better user experience, isn't it? So much better. Wow. It's not even finished, but I'm I don't even care. It feels finished, right? It's perceived performance. Um, and it's now been, you know, 17.72 seconds. Incredible. So cool. um the experience is better. But now what happens if you like want a list, you know, um well, what happens if we want like JSON? Um what happens if we're building an application with a list? That's really the question here. And so um we can still keep the parcels the pieces, excuse me, of reader read and process text and so on, but you can't parse partial JSON. So, what might we do? Um, the the answer is is is like pretty pretty fun, but I just want to make sure what what we've done. So, we've created this recursive reader um that reads a stream and then updates the UI so far. Okay, but now let's try for a list. Give me a list of 20 cheeses. And sure, we're going to get like text, but I don't want text. I want JSON. How can we do that? Um, well, let's maybe address the prompt. This is where you could literally say this is where prompt engineering becomes a thing. So let's go here and let's add like a message

11:38instead of the user let's add a system prompt which gives identity to a language model and instead of you are a helpful assistant let's say you know you always only respond with perfectly valid JSON right and let's let's just see what happens there. So let's save and um enter this and let's ask. Okay, cool. It it's kind of nice. you get an array of cheeses. Um, and that that kind of works. It's it's it's pretty decent. The problem is cheeses is an array. Um, and so what can we do about this? Well, let's just try and parse it. In fact, let's add some state cheeses and set cheeses. It's an empty array of strings because cheeses are strings as we can see here. Um, so now where we set the state incrementally, we can also just console log. Let's say we got this chunk and uh we can yeah we can then maybe even um JSON.parse the chunk. Let's do it in a try catch so it doesn't like blow up the whole thing. And if it's valid JSON then set cheeses and then let's go render cheeses in the UI as well. We're making a cheese apparently. So now we have response and cheeses ask for a list of 20 cheeses and okay so that's incrementally coming the text. Um, sometimes language models can just pause, but okay. But we don't have cheeses. And even worse, um, it's it's like let's let's do a ul. Let's do a nice list. We we all like lists here.

13:06Cool. Um, but where is it? Well, in the console, we see unexpected token e in ectar. And uh, we're trying to pass partial json. It doesn't work. And that's because cheeses is an array. So, it's never going to be valid JSON until that final curly bracket arrives, which means we still have to wait until the end before we can show a nice list to the user. And this is not ideal. Well, how can we fix this? There's multiple ways to fix this. Um, we can use NDJSON, which is new line delimited JSON, which is a format where you instead of like an array, you do this. You serve one element per line. We could do that. We could do that even just with like prompt engineering. So let's change our system prompt a little bit and say something like um you know we can we can just format this and say like but always respond um or always one list item per line because this is new line delimited JSON and uh and and let's see what happens now. So let's let's ask for the same thing and we still get an array. So this is this didn't work. We we don't get one per line. We get an array of cheeses. This is not the schema we want.

14:17And now we even getting a code snippet. So let's let's update this a little bit and say no code snippets. Don't don't do back ticks. Uh and we'll also enforce that schema. We'll say one object per line and we'll enforce uh with this. Exactly. We'll enforce the schema a little bit. We just want a name. We want one object per line with a name. Let's try this now. And okay. Wow. Everything blew up. And we don't really know what happened. But look at the console logs. We got chunk. We got all kinds of weird chunks and it blew up. And the reason for that is we're not really writing one per line to the stream. We're writing still these chunks, right? And so what we need to do is break on a new line when we have a JSON object and only write that in the stream. So we'll start we'll let's make a text buffer. It's empty. And when chunks are ready, we do a quick check.

15:10We check like hey um does this chunk uh does it end with a new line? You know we can maybe do that. So let's do if um like text buffer ends with new line then we don't add to the what? That's weird. But we we parse it because it's a finished JSON object and then we write that to the stream. We literally will say like res.right text buffer and then we reset the text buffer and then we continue. And so this way we're always serving one object since it's one object per line. That's what we're sending over the network. Let's try this now. Give me a list of 20 cheeses. And look at that. Um, we're still getting an array. This really sucks. Like I I don't want a cheeses array. I want one object per line. But let's try again. That's so annoying. Well, we need to do a little bit more prompt engineering. So let's update this a little bit. Instead of one list item per line, one valid JSON object. Believe me, this works. Okay, it's a bit silly, but we're incrementally cooking. So, no arrays, just one object per line. And now, uh, let's ask list of 20 cheeses. And okay, okay, it blew up. But look, we're getting one object. That's awesome. In our stream. Now, we just need to parse these objects and set them into state.

16:26Even our error cannot read properties of undefined reading map is a different error. It's not a JSON parse error. So, the the the problem now is in the UI, not the server. So what do we do? Well, um, we got chunk text. We can now JSON parse text confidently because as we see in the console, it's actually valid JSON. So let's do that. Let's say cheese is JSON parse. And then we incrementally set cheeses exactly like that. Um, this error means that what we're calling map on is undefined. So cheeses is undefined. And that's because we're doing some like weird stuff. So let's just watch this fail one more time just to make sure. Okay, it's it still didn't work. Um, but if we go investigate, it's because indeed cheeses is undefined and it's because we're doing this weird set cheeses and you know all this stuff. Let's get rid of all of that and save. And now we should have our Give me a list of 20 cheeses.

17:19We should have Look at that. Look at that. Let's get some reactions in the chat. That's incremental partial JSON rendering with NDJSON. Let's start 200 cheeses and look it just works. It just that's so incredible. Um we're serving the user instantly as data becomes available creating better user experience. That is so much better. Um so cool and it's just going to keep going. So that that's how you do it. Some prompt engineering. Um you get the right JSON and and you go. Now of course there's many different things we need to do, right? because we don't know if we're going to get this back every single time. So our schema, we need to validate that. We can actually maybe do better with ZOD. So ZOD is a great schema validation library. And so we could say, hey, I want an object with the key name. Let's just import ZOD. And we can just put it here. We can serialize the schema in our system prompt. And uh it will always Nope, that's some weird autocomplete. Let's maybe use um two string, I guess. And so uh there that's already better. And even you know like down here we can make sure that the JSON is valid before sending it even from the server and we can have multiple layers of validation here. Um and finally it just works. In fact like all of this happens um under the hood of powerful libraries like the Verscell AI SDK. Okay. In fact you should probably just use that. In fact let's look at

18:50that in just a minute. Um and and let's yeah let's let's do it right now. So if we um let's get rid of all of this. Let's delete everything. Let's keep maybe the question or the query, but let's delete all this stuff and rewrite this with a library which is the Verscell AI SDK which you should be using cuz you're not the first one with this problem, right? Um there's an open- source library. So let's do stream object which we just implemented that from scratch. But now let's use the abstraction stream object from AI which is the AI SDK and we'll import open AI as oi from AI SDK/ OpenAI. and let's just use it. So what we're going to do is instead of this which is a poor suggestion, we're going to instead say the response is stream object. We're not awaiting it because it's a stream and we give a model. We give a schema which is an object with a name and we say I want I'm a user and this is my question, right? And so we get back a stream object. We get back like an actual stream and from there we process the stream. But let's say I want an array.

19:50So I want as an output I want the type to be an array. Okay. And now it's exactly the same as processing chunks in a stream. We just like 408. Um it's response. It's response dot stream element stream. Yeah. Exactly. And that's it. It's the same. And now this should just work. Let's go back and try. So we reload. And look, it's like there we go. It's exactly. So the UI doesn't change, but the server implementation got so much better. And the cool thing is this works like with not just cheese, it works with everything. Um because it's a generative AI, you know, it doesn't like lock you into one thing. So, for example, we could do like, hey, give me a list of 20 um oh, I don't know, or 18 uh, you know, like types of cameras, you know, and um look at that.

20:39It just works. Incredible. So, this is the power of the Versell AI SDK and of abstraction, right? And this is how you do incremental JSON and so on. Again, um our UI hasn't really updated because it does what it's supposed to get super creative with how. But let's take all of what we looked at and look at a more complete example, a more complete example of marrying great UX and UI with AI. And and I want to show you a project that I built uh to illustrate this that it does use the Vercel AI SDK. It uses streaming. It uses React server components and so on. So, I'm just going to open it here. Um, I'm just going to npm rundev real quick. And what I want to show you is a movie search app. It's called movies++. And I built this to showcase generative UI. Oh, I think this other thing is listening on port 3000.

21:31So, let's quickly um kill all this and reload. And uh yeah. Okay, cool. We have it. So, this is movies plus+ and you can search for movies by natural language. In fact, this is just a better movie experience cuz like if you go and search on an existing site like IMDb or actually um let's even let's use like Netflix and you go on Netflix and um sure whatever and you type in some natural language way to search for something like um movies about superheroes like you get nothing you get like try different keywords but I don't think in keywords I think in like feelings and vibes you know and so I built movies plus let's just try that exact same uh query that uses AI and natural language to give you the movies you want. So we'll do movies about superheroes. And I'll hit enter. Um, and what's going to happen is going to search for movies. Gives me a list.

22:21Cool. And now this kind of looks like a chatbot. And I think chatbots kind of suck. So let's let's do a little bit better better UX in AI. Let's do what might this look like as UI. And um, look at that. Look at that. We have streamed UI and server components. So awesome. Um, in fact, we could take this a bit further and say, "Hey, show me the trailer for Spider-Man: Into the Spider-Verse, right?" And, uh, look at that. It just like starts playing. What? Incredible. This is what I want more than chat bots. Like, it's so much better. We can even say something like, "Where can I go watch this uh, or these movies?" And like it asks for my location access and if I allow it like shows me the nearest movie theater. What in the world? And so this is the future that I want to see. I can say I forgot my password and it just gives me a password reset form instead of like gives me instructions. Do you understand the value of great UX and UI in AI?

23:24Well, let's look at how this works at a code level. I would love to actually show you how you can use the Verscell AI SDK and React um to create some great UI. So, let's go to the code. In fact, let's actually go to our terminal and um start the the code editor from here. So, I'm going to quickly um open the thing and just code dot. And so now uh yeah, let's there's a lot of files that were open from the last session. So, I'm just going to quickly um close them. Um, this this is where I feel really unprepared as a speaker because like I should have had all this closed before, but um, whatever. Okay, so now we're clean. We're from the beginning. Um, and let's walk through the code here. So, I'm just going to move this to the side and open our project. Let's reload. Let's start from scratch. That's not Scratch. Let's uh let's start from scratch and go to the root. So, let's go to like page.tsx.

24:19And what you see is um very basic main header logo search form. Let's delete search form and search form goes away you know and inside search form we have an input and suggestions. Let's delete suggestions. Suggestions go. Let's delete input. You know suggestions are back. And so this is dynamic. This is like an actual app. Um let's uh continue to look at how it's built and how we can create generative UI. So we have these suggestions. In suggestions there's um in a single suggestion there's a hook. It's called use movie search which has a search function. In this you have use UI state and use actions that come from the AI SDK RC which is react server components. You also have um this like continue conversation or set conversation. Continue conversation comes from use actions and use actions comes from AI. So our entire app let's go to like um the the layout. Our entire app is wrapped in AI which is a context provider. Let's go look at AI. So in AI, it's a server component. Literally, it has like use server up here at the top.

25:25And we import a bunch of stuff, but I want to show you create AI because that's what AI is. AI, the context provider comes from create. So this context provider comes from create AI, which takes actions, initial AI state and initial UI state. And both of these are empty arrays, but they're arrays of messages, you know, like objects that have like ro um you user and content. You you get the idea. So actions is where it's really at. And we have this action continue conversation which we call here which we call um here. And what it does is it it takes as an argument like a message and it returns a response and then we take that response and put it in conversation state which is just an array of messages. Okay. So let's try hi. So what's happening is that now is in this is the response that's in our big array of messages our conversation state. Okay. I hope that's clear. So now uh finally we take the whole UI state and put it in the UI. That's what you're seeing here. Okay.

26:30So yeah and of course if we have more messages then we we show them. So you might be wondering okay cool but like how do you get the movies and stuff? Well let's walk through that. So we have this function stream UI which is exactly like stream object. Um in fact let's go look at stream object from our previous streaming JSON thing. Um and you know the signature is very similar right there's the model schema um the messages and your output type right and so look it's all very similar. This is a model messages and here if I get back text I want you to do this. If I get back text then you if you're done mark history and then return markdown. In fact here I can I can change this. I can say let's return subb bro and the content. The markdown component doesn't like it because it expects a string. Um but let's let's do it like this. Sub bro and content. Um and now anytime text is generated um let's well that gets movies. Let's just say like, hi, look, we have subpro. So, we're like rendering um the text because it's text. Does that make sense? And so, you might be thinking, okay, but like how about visual stuff? Well, that's tools. Tools are functions. And these functions have parameters and things like that. Let's look at actually some tools. Let's look at um let's look at the tool that uh that gets generative UI, but that's the one that gets posters and stuff. Um but each tool let's look at it. So create

27:58generative UI has parameters. It's just input schema. So this one it gets a string which is um let's look. So if we choose movies with a strong female lead or something like this. Um did we break it? What's happening? Let's uh yeah let's let's click on this and uh weird. Let's just type movies about superheroes and hit enter. Uh yeah. Okay. I think we may have broke that. So we get back this list. That's the input parameters. It's a So get movies is the tool that gives us this list. Um and it gets a query. That's what we just wrote. Movies about superheroes. And it gives us a commaepparated list that we then render as like a list um a line separated list. And so then for create generative UI, let's look at the description. A tool used to generate UI in response to a user explicitly asking for UI. That's what it's called. So let's explicitly ask for UI. Let's say um I want explicitly UI and so it's going to call the create generative UI tool like that and it's because of the description that's how it knows to call the tool. The parameters are the input arguments. So movies from context is just a string which is a commaepparated list of movies which are those movies you know so that's how it gets it. So those that's the input props you can say. And then finally um generate is an async function which is a generator function. You can tell by the star which means you can like yield many times. You

29:24can yield asn't like return but keep processing. So we'll return a spinner and all of this is just network stuff to get the movie posters. We just fetch the posters here. Promise.all and then we return um the movies component. the movie and this is very important to show you the movies component is a component that I wrote like this whole component AI didn't generate this component I wrote this compon we can even confirm if I say sup everyone here and save we have hot reload look it says sub every I wrote this whole component this component was not generated I wrote it so what did the LLM generate it just generated the props movies this array this JSON array of objects title poster path etc that's generated by the AI But I wrote the component myself. And this is so important because you should be able to trust the components. And of course, if you write them yourself, you trust them way more than some like AI model creating it, right? It's guardrail and safe that way. Um, again, just the props are generated by the language model. If we and the other thing is this is like fully client ready. So, for example, let's go here and on click.

30:32Let's add on click. Let's do like on click equals um you know something like prevent default. And so we'll prevent the default and we'll alert we'll say like hello you know um and look at that. It's wow how cool. Um it just it's fully interactive. That's the power of React server components. And this is how you can create generative UI that is so much better than a chatbot movies. We can also look at like other tools. They're all the same. It's just a standardized schema. For example, we can do maybe um the forgot password. Let's let's look at that. So, um let's yeah, show forgot password this one. And what we can see is it's the same description. When the user says they forgot their password, use this tool. So, we'll just say I forgot my password, right? And the language model just maps tools to components like that. And what is the tool? Well, there's no input parameters, but I just generate a component or I use a generator function to return this component that I wrote. Does that make sense? Um I can say please do stuff and look we have hot reload. So this is how like React server components um can be married to great UI in the AI world where you stream because React is a full stack or Nex.js is a full stack framework. You can stream from the server to the client and create much better UX. And I hope this is helpful for you in the age of AI to create truly better UX than chat bots. Let's wrap up.

31:57You can come follow me on X. That's tiskumar if you have questions I'll obviously take some questions now as well but um if you have more questions then I'd love to answer them and also I have um I I do host a long form podcast with a lot of deep dives on AI. I highly recommend if you want to learn more um go to t.aspodcast and this episode particular catchup AI in 2025 is just it's like an hour and a half long lecture um on everything you need to know to get up to speed with AI. It's super helpful and quite valuable and if you're feeling some type of imposter syndrome or if you want to know more in AI, I cannot recommend it enough. With that, I want to thank you so much for your time and I look forward to answering your questions. Thank you.

32:41Your talk was really amazing and I will start from the last thing that you said. I know that you have this amazing podcast. So yes, people that want to know know more about AI, go and check out that podcast. So, we have some questions for you. Actually, we have quite a lot of questions. So, let's get started with the first one. Hey, Tedas, what's the current state of building and using AI browser agents? How are you using them to interact with websites? Yeah, that's a good question. There's actually a podcast episode with the founder of a company called Browser Base, uh, where we talk exclusively about that for almost two hours. Um the current state of building and using browser AI agents is is good. Uh it's a good state.

33:27There's tools like I mentioned browser base. U also there's a tool called agentQL. Um they do exactly what you think. They give tools to um AI assistant to browse the web um and extract data or even take action click on buttons and so on. How am I using them to interact with websites? Um I'm using I built a tool that helps companies with marketing. Uh it's it's soft launched or unlaunched and I use I use it I I use browser agents to discover um like mentions you know like if you want to know like hey what did people say about my company um you formerly you would write a big algorithm to do this now you can just tell AI agents to um use a browser go search find what people are saying and give me a report and they do that quite reliably so perfect the Next question is generative UI. Love it. Do you know production sites using it? Yeah, my movie search my movie search that is in production. Um, if you're talking about like big companies using it. Uh, no. It's also not the most stable. I will say that you have to be kind of brave to to use it.

34:40Uh, it's not unstable in the sense that you're going to get problematic components because as I mentioned in my talk, I wrote those components. it's more unstable in the sense that um the feedback loop is not there. So once you say you generate a component or you post um you you your LLM surfaces a component that you wrote then giving that component's data back to the LLM is the challenge and you'll even see that like I'll ask for movies I'll ask for movies as posters but then I can't reference the posters themselves. I can't be like hey what's that red dot in the poster? it will not know what poster I'm talking about because LLMs fundamentally can only read and understand text. Uh at least right now that's the state with the Vercel AI SDK. So um you can use it.

35:23It's just I don't know how useful it is. Amazing. And we have a question that more than one people asked. Is there any chance that you will upload source code some repo? Yeah, there's actually um I'll put it in in the chat. Maybe you can get that to people somehow. This is all of this is open source. It's just github.com/datastacks and uh the code is there. Yes, we'll do this. Thank you. And last question is I'm new to all these. How do I start and where podcast? That's that's the best one. The the that episode that I highlighted the reason I made that was because I was not people asked me this a lot. Uh and I had no answer confidently that I could give them. There's a lot of great resources like latent space. It's a fantastic podcast by my friend Sean. Um, but you have to you have to have a baseline understanding to listen to that where what gives you that baseline understanding doesn't exist. That's why I created this podcast episode because honestly like there was nothing else and I think to this day there is nothing else that that is that starts you with AI and once you listen to that episode then you'll know then you can go explore your own way. You can go listen to late in space. you can use cursor maybe more fluently. Um, but I would definitely suggest starting with that podcast episode.

36:45Amazing. And that was our last question. But before we move on, I would like to mention that Telas is not only an amazing developer, not only an amazing speaker, but he has an amazing story as well. He's an amazing person. We did mention in his biography that he has over 20 years of experience. And this is true. Although he's very young, this is true. So go check out his backstory as well maybe on YouTube. I know that you have this story uploaded on YouTube. I think it's amazing and it's also very inspiring. Thank you very much for your talk and hope to see you again soon. Thank you as well. Hope everyone enjoyed it. Take care. Bye.

Elsewhere

There is every talk I have given, all 69 of them, ConTejas Code, the podcast, and Fluent React, the O'Reilly book on how React works inside.