Tejas Kumar

The New UX

CityJS London 2026 / 23:08

Watch this talk on YouTube

Transcript

26 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:36Please welcome Tejas. >> GOOD MORNING. GOOD MORNING. IT'S GREAT to see you all. Wow, what an introduction, what a great venue, what an amazing audience. Upstairs is packed. Woo, I'm so ready. Hey, it's an honor and a privilege. As introduced, my name is Tejas. Uh, that's pronounced like contagious. Don't worry, I'm not. Um, hopefully my joy is contagious. You know what I'm saying? And I have had the privilege of learning from and working in a variety of teams in a variety of settings in various capacities and learning from truly remarkable people. And I'm here today to talk to you about things that I've learned from really amazing people, not from myself. This is not my opinion, but this is this is value from everyone, okay? Uh, today I I'm an AI developer advocate at IBM. That's where I work. I work at IBM uh, on things like data and AI. You may have heard of Watson.

01:25Actually, we train our own models and we do a lot of um, really fun work. But I'm not HERE TO TALK TO YOU ABOUT THAT TODAY. INSTEAD, I'm talking to you about the new UX. The new UX is changing. UX is changing in a very profound way. Uh, we used to use the web a certain way with JavaScript and it's slightly different now. My clicker doesn't work. Let me move over here. We it's slightly different now and so what is the question on our minds at a JavaScript conference? When Aris was opening today, he said it really well. He said, "Whoa, it's 2026 and we still do JavaScript conferences." And so, you may be here with this question on your mind, uh does JavaScript still matter? Right? Claude, thank you. That's the right answer. The the Does Does Claude write better JavaScript than me? Um and you I'll be honest with you, he writes better JavaScript than me. And so, I I've moved from writing code to supervising code. And oftentimes, I have no feedback. It's all LGTM from me. But, I'm here to deliver to you um good news.

02:26I'm here to deliver to you gospel, which is does JavaScript still matter? Absolutely, yes. It does. And that's what I'm going to convince you of today um in our time together about how JavaScript is changing um the way we experience the web in a very great way. In fact, I'm going to do you one better. I'll give you three ways that JavaScript matters, uh and we'll just get We have not a lot of time. So, let me just get into it. Number one, um things are moving to streaming. Previously, we do like network requests, right? And we would we would wait for the response and then res.json. How many of you do this, yeah? We we deserialize the JSON response and then use it in code. Um there's a lot of awaiting.

03:04Whereas nowadays, thanks actually to AI, um things are streamed. We don't wait for a long list of text from a language model, but we do word-by-word streaming, which has then led to now some user interfaces with JavaScript have components that stream in. It's so cool, right? Component-based streaming. So, JavaScript still matters, but it's it's moving now more in the streaming direction. Number two, um you may have heard of Model Context Protocol. Uh it's a server like HTTP, right? HTTP is a client-server protocol. MCP is a client-server protocol, also. Let's Let's use a very basic example like your browser is an HTTP client. And when you go to something like cdnjs.com, that client talks to a remote server and says, "Hey server, give me context," right? And the server sends what? It sends HTML, right? MCP is the same. It's a client-server protocol where a client is some AI app, ChatGPT, Claude, whatever, and it talks to a remote server and says, "Hey, give me context."

04:00And the context is usually things like tools and other things that it can use. Okay, so MCP servers, just like HTTP servers, are implemented in what language? Python. No, JavaScript. JavaScript. And third, you can now use J- JS, JavaScript of course, inside of popular AI apps like ChatGPT and Claude and so on. And so this is where JS is moving and we'll talk about this with some demos. Let's let's say it like this. The web is an interesting concept cuz you you open your browser and you go to a web page, but when you go to a web page, it's like you're going to someone's house. You're you're leaving your home and your computer and your beautiful little environment and you go to some foreign environment, some other house where the developers of that website have made decisions for you. Right? They say, "Hey, we should do a carousel here."

04:49Uh with like little dots, but the dots don't work when you click on the dots, so you have to swipe, right? Or um developers also make decisions, "Oh, we need an accordion here." They make decisions which are fine. It's to the best of our ability, but often more often than not, these are not accessible to everybody. And then you run into like screen reader problems or maybe you're color blind and they don't quite get the contrast. There's just so many constraints. THAT'S HOW THE WEB is today. We leave our house and we go to other houses on various other domains. Um the way UX is changing is in AI apps like ChatGPT. Um the content comes to you. So you don't go to some house, the content comes to you in an environment that you're familiar with, which is your whatever AI app you're using, Claude or ChatGPT or so on. And so that's what I want to talk to you about today, how this UX shift is happening and JavaScript's role in it.

05:37But I've already spoken too much. Honestly, I'm tired of the sound of my own voice. So let's look at code instead. Uh and we'll we'll look at some demos. So we're going to demo those three things. Number one, the streaming pattern. Number two, um the MCP server and number three, MCP apps, okay? And so, let's dive in. I've got everything preloaded here. That's the schedule for CityJS London. Um that's going to be our case study today. And so, what I'm going to do is I'm going to start an HTTP server on my streaming example. And then we'll also talk about the code. So, this is what we have. If I open this up, we've got legacy, which is the prior art, and client. And I'm just going to maybe side by side them a little bit here. So, we've got the old way, we've got the the it's not so new, it's more the modern way. And what I'm going to do is paste in my API key in both cases. And we have a prompt, write a short poem about JavaScript.

06:28Now, the old way with synchronous network IO, you submit this and then you just wait for a response. Um and you may wait a long time. And then that was nice, but it took kind of long. Um and it took yeah, 4.9 seconds, which kind of sucks. Let's do it the modern way with streaming. And so, I sent it and look at this. The time to first meaningful anything is a lot faster. And it took between 3.2 and 4.9 seconds, that delta is maybe like 1 second faster, but it felt even more faster because it's stream, right? Um what does this look like in code? Well, we have here um the code of this. So, if I open streaming, uh previously it used to be like this. Is that font size? Let's bump it. And let's maybe use light mode. Let me blind you a little bit.

07:13Uh light mode, light plus. Okay. So, yeah, you're welcome. Um So, this is how it used to be. So, we have just a button and a form, yeah? Write a short poem about JavaScript. Button ID submit. We get the submit button's reference. When you click on the button, get the prompt, get the API key, and then send a network request to ChatGPT, whatever it may be. And then you await res.json, and then you populate it in out, which is our div that contains the result. This is prior art, we've all been here. With streaming, it's a little bit more complex for a bigger UX benefit. So, same thing, you get the submit button. When you click the submit button, you get the prompt and the key. Um and this is important at click time because the prompt may change and so on.

07:55Um and then we fetch the API, we stream as true, this is important. And then the stream res.body in the HTTP spec or in the fetch spec, excuse me, is just always a stream. In fact, if I hover here, you will see that it is a readable stream that returns uh uint8array, an array of binary. And so we pipe that stream through a text decoder, so we get text chunks. We get the stream reader. And the reader has a method called read. And every time you read it, it says, one, am I done? And two, what's the current value of the stream? And so if you're done, well, we don't need to do this loop anymore, we're good. If you're not done, we increment the buffer with the value. What is the value? Well, these platforms, they send you something called NDJSON, new line delimited JSON.

08:40Which is you've got a data colon, a big JSON object, and then end at the end in square brackets, and then a new line for the new data. So, we need to break on lines in these in this buffer. So, we buffer.split on new line, and then we get the last line. And if the line starts with data, or if it does start with data, we continue. If it does, we get the delta, and we increment the text content of the output div with each chunk. Okay, it's just it does look more complex, but the UX benefit is clear, right? We process a stream. Now, of course, there's libraries and abstractions for this, you probably should use one because it handles a lot of other cases, but this is literally how ChatGPT, how Claude, how everything works. Um and it gives you better experience there. And this is, of course, JavaScript. Now, that's cool. So, maybe, let's say you want to navigate the CityJS website, you want to find out like whose talk is when. Uh let's let's go check that out.

09:34So, this is the CityJS schedule, right? And you this is maybe hard for you to use for some reason. You don't get the scrolling patterns or whatever. Or maybe worst case, you're in an environment where you don't have where you don't have JavaScript. So, you're here and you load the page, no JavaScript, there's literally nothing here. Right? And and so, maybe the answer is a chatbot. We use a chatbot on the page and we stream UI. Cool. But we can do better. Right? Um what if there was an MCP server for CityJS where you could just ask like your your favorite MCP client, Claude, ChatGPT, Cursor, "Hey, when is this this talk?" Right? Well, MCP servers are implemented in JavaScript also and let's take a look at the code for that now.

10:16It's kind of similar to what you know. So, this is an MCP server. You import MCP server from Model Context Protocol SDK. You create it by calling new MCP server. This is similar to Express or whatever it is. And then, you register a bunch of tools. What are tools? Tools are functions that your your ChatGPT, your Claude, whatever will call when it feels like it. This is what agents do, they have agency. Okay, but how does it know when to call the right tool? Well, we register a tool and we give it a tool name, get schedule. That's the name of the tool. And the second argument is some metadata. The metadata is a title, a description, what input do you expect, and some annotations. The agent, so ChatGPT, Claude, whatever, they know to use this tool based on the language in the description. So, if you send a prompt, "Hey, when is this What is the schedule for CityJS?" It will read the description and it will call this tool, right? That's kind of how it works. And then, the third argument is just an async function to actually get the data.

11:14You might as well call fetch from the CityJS API here and return that in this format. This format is called a message envelope for chat applications. It's just content, which is an array of type. It can be a system prompt or a user message or just text and the actual text, right? So, this is how you register a tool with an MCP server. At the very end, there's also something called a resource. And the difference between a resource and a tool is who gives it to the model. A tool is when the model itself pulls the data, and a resource is you, the user, saying, "Hey model, here's some context." It's just who gets there. But in essence, the same thing. They give context to a model. And again, all of this is done with JavaScript. Is this clear so far? At the very end, we just create a transport for our server, and then we server.connect. This is all It's like less than 150 lines to make an MCP server. And now we can consume this. So, I'm going to open Claude right here, which is a very popular MCP client. Anyone using Claude?

12:13>> [laughter] >> Yeah, everyone. Okay. Um and I'm going to open Claude. It's God help them. They need to use like Rust or something cuz this application takes like at least two decades to open. Um look at that. That's wild. Claude. What? Do I quit? What? You said maybe it's down? Force I Let's just try again. Um there we go. Okay, it opened. It opened. Relax, everybody. This is fine. Um and now I'm going to add my MCP server. So, I'll come here to developer, edit config. Believe it or not, this is how you add MCP servers to Claude if you're a developer. So, I'm double clicking on this, and now VS Code needs another decade to open. Perfect. Um and we paste a little JSON configuration here for the MCP server. It's just I'm invoking the node command, node, and then I'm calling my server.js. That's all, right? Save this, quit it. We quit Claude. We'll wait some time for it to open again. Oh, that's fast the second time. And so now, you can see if I click on this plus, I have in in in connectors, I've got City JS. Cool. And so now, I Let's turn this off. And so now, I can ask, um who's speaking at sit at City JS, right?

13:32And so now it's going to use the Node.js MCP server that I wrote uh in So you can see loading tools, get speakers. That get speakers is my tool that I wrote in JavaScript. And so there you go, City JS London has a pretty packed lineup. Here's the shape of it. You got Douglas Crockford. Where's Douglas? Is he here somewhere? There he is. What's up, Douglas? Um Tejas, that's me. Rich Harris, Matteo Collina, he's over there. Matteo, what's up? Uh And so it gives you this. It just knows this. It didn't search the web. It used my tool. So this is cool cuz like the UX is fundamentally different. I don't have to go to some foreign website. I'm already there. I'm probably using Claude to book my flights and give me context about London and what's Brixton and all of this, right? And right there, I'm like, okay, by the way, who's speaking? It's extended.

14:16JavaScript facilitated that. It's so cool. But the problem with this is we lose branding. Like a big part of the web and websites is beauty and brands. You know, like Nike sell shoes. I want to go and I want to have the Nike experience. I want to go on Apple. I want to have the Apple experience. You know, I want to brand Coca-Cola. Wow, red, you know, or black and red. Now it's Coke Zero. Coke Zero, anyone? Yeah? Greatest drink of all time. Amen. Okay, so I want the branding. How do we do that? And this is where MCP apps come in. They give you that that branding as well. It's your UI, your JavaScript inside ChatGPT. Right? You can do that. And it's all based on MCP. There's a reason I explained MCP so much to you because if you just tweak your MCP server a little bit, you can send your components inside ChatGPT. Right? All you have to do is decorate it a little bit. Let me show you. So um I'm going to come back to this code.

15:15We already have our MCP server, but I'm going to extend it a little bit. So I'm going to create an HTTP server. This is just native to Node. It's nothing. It just listens on 3003 and console logs. Uh this is my server I created. I include some course headers here. Just Anyone bit by course before? This options is for course. Um if you get on {slash} I say, "No, no, go to {slash} MCP." And if you go to {slash} MCP I well then I create an MCP server. I connect it to a transport. And when you close the connection, I close it. That's all I'm doing here. Okay, but what's the MCP server? Well, it's this. It's exactly what we saw. Register tool, register resource. So we'll create a resource. And again, a resource just gives data to the context, to the model.

15:58Our resource is called schedule widget. And it has this URI, which is this type of It can be any string you want, but I just follow this pattern. The URI will come to in a minute. It also has a mime type. And notice it's HTML. So I'm saying, "Hey, MCP client ChatGPT, I'm sending you HTML." Okay? And then I trust the client to render it. And finally, this function is called whenever somebody um uses this resource. And what we do is we return text, which is schedule widget HTML. This is the magic. What is schedule widget HTML? It's literally node read file, right? Of an HTML file, which is here. It's just HTML that will be embedded inside ChatGPT, okay? And so that's my resource, but how does the agent How does the AI know when to render this?

16:45Well, there's a tool for that. So we have a tool. The tool is called get schedule. And again, tools have metadata, right? So title is get schedule, description is get the schedule. This is how ChatGPT knows when to use this tool. The only magic here is this meta. This So meta is kind of a grab bag in the specification. And if you have a UI property, it says, "When you call this tool, render this resource." What resource? Our resource at this URI, the schedule HTML that I just showed you. This this so far? Um so we have a resource, we have a tool, and the bridge between them is the resource URI, okay? And we have a UI field. This is actually the specification, the standard, but this open AI {slash} output template is open AI's specific implementation of this. And we have both of these just for maximum compatibility. Uh, normally you just need UI if open AI follow the spec, okay? Um, and so that's it. And then of course the third function is actually like fetch. We we get the actual data from somewhere, we fetch, and then we return structured content, which is our JSON of days, scheduled by days, and content, which is just text. And this is again that message envelope we talked about. This is all it takes. It's just a glorified MCP server with a UI annotation.

17:59You want to see it in action? Yeah, let's do it. So let's see what this enables. So I'm going to um, run this locally. So I'll kill this. NPM run demo chat GPT. This is running on port 303. Normally you would host this on something like render or relay or whatever. Uh, I'm just going to expose my machine to the internet, okay? Uh, and to do that I'm going to run Cloudflare. Anyone using Cloudflare? It's fantastic. Cloudflare people, where you at? I saw some shirts. Hey, what's up? Greatest service on earth. So, Cloudflare, I'm just running a tunnel, and this will give me a domain. So in in a in a couple minutes or seconds, I'll have There we go. This is my now port 303 on this address. So now I can go add this to chat GPT. So let's go to chat.openai.com/apps.

18:43Um, and we'll see a bunch of apps. Cool. And what I'm going to do is add mine. So I'm going to come here and add more. And it's going to disappear. Uh, create app. And I'll call it city J JS JS London. MCP server URL is my thing {slash} MCP. There's no auth. And yeah, yeah, I know it's very dangerous. I don't care. Okay. Um, so we're going to add this now to chat GPT, and it's going to chat GPT's going to check like, "Hey, is MCP server valid? Like do you have all the headers? Cool. This has eventual consistency so it's not going to show up even though it should. Uh I don't know if they're using TanStack Query but maybe they should. Um anyway, so now I'm going to start a new chat, right? And I'm going to just ask who's speaking?

19:28Um and right now it's me. Wow, thanks. Um let's try again but this time I'm going to app mention my app that I made at CityJS London who is speaking? Speaking speaking speak spacking. Who is speaking at the conf, right? Um what is the conf? Who knows? Well, CityJS London knows and so it's going to now um use my MCP server. I'm checking the conference speaker lineup and thinking. And so check this ABSOLUTELY LOOK AT WHOA, LOOK AT THAT. UM main stage MC. Incredible. In fact, here I could do you I could do you one better. I could do when is Stages talk, right? Um then I send this send it off and now I can even get talk details in my branded way. It's incredible. Let's have a look. So now pulling whoa, my face. My face inside chat G and it's it's right. It's 9:30 Great Hall.

20:32It's all there from my server. The Twitter link, does it work? Does it? Let's check. Whoa, it does work. Fantastic. So it's all this there. It's so cool, right? And I want you to pay attention. Look at this red. That is literally um the CityJS schedule. Let's go to cityjs.com. CityJS London, right? Check the brand. It's the same. Let's go to the speakers. Let's go to the schedule. Look at that. It's this red type card situation, right? And we've got exactly the brand here inside ChatGPT thanks to Model Context Protocol apps. Isn't that incredible? So I don't have to leave my house. I'm here. I'm querying for the latest recipe for strawberry cake, whatever, and I also then just say, "Hey, who's speaking at the spot?" And it's there, but with the city yes branding. Does it make sense? This is how JavaScript is facilitating the future of UX. It is so so incredible and I'm here for it because it also makes it more accessible to everybody. All it takes is for OpenAI to make a really great accessible experience and then it just follows, okay? So, we walked in here going JS Conference 2026, does it still matter?

21:40Uh the answer, absolutely unequivocally, is yes because we can create these experiences for everybody even if the vector changes a little bit, okay? Um let's wrap up and summarize. We're almost at the end here. In summary, point number one, JS is still highly highly relevant. As we saw, we create MCP servers, we create MCPUI, we we run our JavaScript in those runtimes. Um It it's always been about products. We JavaScript exists, React exists, all these tools, we Roll Down, OXC, all of them, they exist to make amazing products for people. Um that's the They were always a means to an end, but products are what really matter and then quality products at that. It's always UX. It's always UX because great UX is a great product that makes people happy, but even if we go one layer deeper, it doesn't even stop at UX. Even UX is a means to an end and that end is people.

22:39And so in in in in a world of AI, oh, I have an AI this and I'm an AI parent and whatever, um all let's not forget that all of it is a means to an end and that end is people. There's is Look around. It's everyone in this room. It's humanity. It's each and every one of us and it's supposed to facilitate that. It was always people. Let me say this, it will always be about the people. Okay? Uh and so, thank you so much for for coming to this >> [applause]

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.