Connect Xano (@nocodebackend) to Weweb (@weweb_io) with real-time messaging

Ray Deck shows how to set up real-time messaging between Xano and WeWeb using WebSockets. He walks through enabling Xano's real-time feature, creating channels, building a sendMessageToWeWeb function, and listening from WeWeb with either Xano's npm SDK or a custom JavaScript listener that triggers workflows and updates UI variables.
Chapters
Let's talk about real-time, and that means being able to push information from your server to the client. One of the things I often hear is they want to have your front end be aware of things happen that just immediately happen from your server. Like, you know, your email does that, you know, chat systems do that, like, and you wonder why can't that happen for your app as well. And that's because those other technologies are using something called WebSockets. Which is establishing a persistent connection between your client and the server. And then the server is then able to use that open connection to send information back to the client whenever the server says, hey, I've got something new, and the server is able to publish it out. And then the, the web client is subscribing to that information, able to receive it and keep on going. See, sending information to the server is really easy, right? That's like what the usual web request is. The client sends something up to to the server, the server comes back, and we have ourselves a transaction. But how do the server— but the client can't do that when the server is ready to have information, right? Because the server just has information, the client hasn't decided to ask for it, and that, that whole model doesn't work. So instead we have something that's called WebSockets. And WebSockets are where we hold open this door. You see, usually the transaction looks like this red line where like, you know, you sent— the client says like the server, and then the server sends something back, and then it's over. But what happens when you do a WebSocket connection is that you come back and then it establishes this pipe that holds open for what are called bidirectional messages. Now, the messages that you send up to the server, those can look a lot like the requests you'd ordinarily do, but the requests that come down from the server to the client, at any point the server says, I have something new for you. That's the news. And that's what's really exciting about all this. And basically this stays open until one side closes channel. Now, Xano is uniquely situated to be able to do this because Xano has what's called an instance model. And so whenever you have your Xano instance, assuming you're on a paid plan, uh, that basically is your own virtual machine and you can use the resources of the virtual machine kind of the way you see fit. It's one of the reasons why we don't have to like pay on a meter, uh, for doing things in Xano. It doesn't operate the way serverless technologies do. And that same approach of being its own instance is what allows you to say, hey, this is my instance. I'm going to use it for things like holding open these pipes. Which would otherwise be kind of expensive and doesn't work nearly as well in a serverless type environment. So we get to take advantage of this. So let's do that right now. We're going to talk about how to bring this over to WeWeb. You know, WeWeb is a very popular frontend for Xano, and we're going to bring just a little bit of code into WeWeb in order to get WeWeb to be able to connect between Xano and itself and be able to receive those requests from Xano. And we're going to build it all as a completely fresh new WeWeb, you know, little site here. But we'll get from here to there. So if that's what WebSocket is, then the key thing that's different about it is it's not like you just can go set up a regular API endpoint on Xano side. Instead, Xano is going to be pushing that information back to the client, and Xano needs to know how to be listened to. In order for us to do this, there are a couple things we want to make happen here. So first thing we're going to do is we're going to make ourselves a function. And that function is going to, we're gonna add a function, and we're going to call it, you know, sendMessageToWeWeb. Now we don't have to do this with a function. I'm just doing it because I like to make functions for doing simple things like this. And we're going to say in the function stack, all it's going to do is send, and this is under APIs and Lambdas, under Real-time Events. And we're going to send into a channel that is called YouTube. We're going to give it data of hello, right? And by the way, that data can be anything. Xano is going to be smart enough to JSON encode it later on. Now this authentication piece is kind of key because that way you can say it's only going to go to those people who have authenticated their request. I use this sometimes, but even more common use case for me for doing this kind of WebSocket-based publication is going to be for shared stuff. And so it's much more common that I will be using channels that are going to be namespaced to like particular files or whatever. And so I'll sort of construct it as, you know, YouTube slash, you know, you know, one or, you know, a UUID or something along those lines. And that's going to be the way I usually set up channels. And then the data can be as complex as you want to be. And that's going to be what's going to get sent over to WeWeb. We're going to hold off on doing authentication right now. It just creates a little more complexity. But what Cyrus sell is up for is the ability to send a message. And of course, I can do a run debug. And have it send that message. And congratulations, I've sent the message, but it hasn't gone anywhere because nobody's listening. So how do we set up Xano so that our friends at WeWeb can listen to it? To do this, we're gonna go back over to our dashboard. And up here in the upper right-hand corner are these little three-dot menu, which doesn't have any background to it, so it's a little hidden, but it's pretty important. This is where you can do things like cloning your workspace and other fun things. But this is where the key is. We can set up what are called real-time settings. If I click on real-time settings, I can then enable it, and that puts me in a position to have all of this start to work. Now, this connection hash is going to be really important. It is a somewhat secure string that we give to the front end, but that only your front end knows about. That way, not every Tom, Dick, and Harry can go make a connection back to your XAML instance. It's only gonna be those that actually have this connection hash. Everybody else is just going to come in and die. Now, the other thing that's going to happen here is we have channels. And channels are really important because you don't want people to connect to your instance. You want people to connect to your instance and know what kind of conversation they're going to be having, right? Like you can have, you could set up like the classic examples, like a chat room and like which room is that going to be? Or if you want to have people be notified about documents that have recently been modified by somebody else. You want to have that include the name of the document. But really what we need to do is create what's called namespacing. So if you click on where it says channels here, click add channel, you can identify the target name of the channel, which are allowed to contain letters, numbers, underscores, and dashes. And so I'm going to call it YouTube. Now you can call it whatever you want, but remember, it can't include like slashes or whatever. Slashes are a special case. You see the, the, the, if I, if I enable nested channels, which is actually really important, this will allow people to connect to Xano and connect to a channel that could be dynamically generated, i.e., specific to like a document identifier or to a record or to a user ID or something along those lines, which is going to be super important because you don't want people to be notified about everything that could be happening on your appliance. That will create a very noisy communication and of course have security challenges along the way. So if we scroll down just a little bit here, we can see some other things that are really interesting. One thing that is super important is the idea of anonymous clients. Now, if you don't have anonymous clients, then people need to use an authentication token in order to talk to your Xano connection. This can be important if it's all going to be user-based. For many of my use cases where I like to use these WebSockets, they are not going to be on secured endpoints, so I will use anonymous connections. And frankly, they're a lot easier to work with as well. The other thing you're gonna find in here is you can like have presence updates, which sort of allows people to identify, you know, who else might be in the channel, which is then used for some of the rest of this authenticate, some of the rest of this messaging stuff. And then you also have the idea of client messaging, where a client can push information into the channel. And also whether you want that to be allowed to be public, or maybe that's only authenticated. Maybe everybody can receive messages from the server, but only people who are authenticated can push those messages up. Now, there's some other stuff in here that we can do, like start to log things in, and this idea of private messaging, we can have communications go between people. But this starts to get, frankly, a little bit more advanced and quirky. And I have found that the majority of really useful implementations of real-time are the simplest. And they're the ones where you're able to get your client notified by the server when information's coming through the door. And then kind of the rest of the stuff that's pushing information up to the server, I mean, you can do that through WebSockets, and we can talk about how you do that in Xano using triggers. But I actually don't find it to be nearly as useful. I would say you use the traditional push things up using HTTP and you push things down from the server using WebSockets. And by letting each one of those have its job, we get to maximize benefit while also maximizing simplicity. So what I'm gonna do here is I'm gonna turn off this idea of client messaging, 'cause I don't want the client to push messages. I want the client to receive messages from the server. There's this also idea of message history. I don't find this to be all that important. This is something that's much more important if you have like a channel, you're trying to get a whole bunch of data points of what's happened in the past. What I find is to be most useful for these things is actually just getting the signal of, hey, something new has happened. You should be, you should be acting as if something new has come through the door and go refresh your data or whatever it is. But you can set up and be able to have those histories be available to you. And this can be much more important for things like a chat implementation, maybe for a little bit more performance. But either way, I think it's sort of part of that whole make it more complex than it has to be. Cool, so we're gonna say save here. And it's called YouTube. And you see it has YouTube slash, and that's because it allows to have nested channels like we were talking about, that will allow some degree of dynamism to it. And then if I click into it, you'll see down here at the bottom, I can add triggers. Now triggers are what happens when people send up information from the client up into Xano. The tricky part about making a trigger is that now you're kind of duplicating logic, right? That you might've also had in your API endpoints, and now you sort of need to get that logic reflected going through the trigger. And this is creating kind of a virtual remote procedure calling situation that's, you know, stuffed into a corner of Xano. This is not my favorite. I don't recommend starting with this. You can learn more about it, but this is not gonna be what we focus on in this particular tutorial here. So now I've got my channel. I'm happy with my channel. It's going to allow information to get pushed down. And I'm gonna close this up. And yep, close that up. Now I've activated real-time, I've enabled a given channel, and I've also set up over here in my, not library, in my Xano, in my functions, I've got my, if I sort by created, yep, send message to WeWeb, which is nice and simple. It's just gonna send a real-time event to the YouTube channel with the text of hello. Okay, so Xano knows how to push and is configured to be listenable, but that doesn't mean that our friends at WeWeb know how to do it. So on the WeWeb side, we're going to need to, you know, create a WebSocket, and we can do this either using low-level WebSockets, or we can make use of the frankly pretty nice SDK that Xano's created and has available up on GitLab and is also published through npm. I have found that integrating this with the npm package from WeWeb has given me some connections. So I'm gonna show us a different way of going about it. And that's through a bit of code here that we have in script tag. And this will be available with the notes on this, on this video, where I create a little bit of a listener, right? And the idea here is that we're going to import the Xano client. And if you haven't done it before, this is the way you can asynchronously import JavaScript into your, into your, live into your application on the JavaScript side. And then because it's done this, I now, after this import has completed, there is a variable called Xano client that is available to us., and we're gonna be able to make use of that. And the, 'cause it now exists after we've done the import. And then we can just instantiate a new Xano client with a base URL, a real-time hash, and if we have one, an auth token. This will then establish the base relationship with Xano, and this will connect it to the webhooks. Using Xano.channel. After that, we're going to use the on function, which is also all part of the Xano, you know, SDK. And you can learn more about that over here on GitLab, and you know how the Xano token works, and also the way its real-time token works. And the And but what's going to happen is every time it hears an event, it's going to— uh, well, if you define a callback, it'll run a function with that argument. But the most important thing is we're just running workflow. We're going to run workflow, we're going to give it a workflow ID, and we're just going to pass in whatever it was that we just got from the, uh, from Xano. See, this way we don't need to think too much about how the Xano data is structured, right? We're going to allow— but we're trying to build a minimum amount of code to build a bridge between Xano's real-time feature and getting this over into WeWeb's built-in workflows. And then we create this as a little bit of a listener. This function becomes then something we're going to call, right? So we can define this function, and we will edit it, edit this code once we bring it into WeWeb. So now let's talk about WeWeb. So, in WeWeb, we're gonna need to do a few things. The first thing we need to do is we're going to need to listen for stuff that is coming from Xano. Here is a section. Uh-huh. Now we have a section. Cool. And now we're going to create a regular old input. Right? And then we're also gonna add a— button, right? And then, and then after that, we're going to create a bit of text which we'll just use to display what it is that we got from Xano. So we'll go to Elements and we'll just make ourselves a little text, text element, right? So now we have text. Cool. So the idea here is this guy is going to become the channel ID, right? And this is going to be start listening, right? We'll have a workflow associated with that. And then this is going to be the actual text that goes with the workflow. All right. So the first thing we're going to do then is we're going to click on the button. We're going to go over to the workflows, create a new workflow. And say that when we click the button, we want to turn on a listener to go talk to Xano. So how do we do that? And we're gonna say JavaScript. Okay. Custom JavaScript, my favorite tool in WeWeb. And we're going to just expand this out a bit. All right. So now I've got sort of this core code here that I did a little bit of explanation on, but I think it'll become clearer as we start to use it. So we'll copy this. And by the way, this is all shared, so you'll be able to have access to this as well. And we paste it into here. Now the idea is we have a XanoListener, blah, blah, blah, blah, blah, blah, blah, and it's able to get stuff from the— get this information from the arguments. Now because I've defined it using this function keyword, I can actually invoke it ahead of time, which is kind of cool too. So I can say XanoListener and I can pass it arguments. An argument I could pass it is a base URL. Alright, so what base URL am I going to use? I'm going to use, you know, StateChangeAI, you know, so I'm going to copy this and go back over to here and paste that, right? Remember to put in quotation marks, put in quotation marks. And of course, this could all be from a variable as well. That'll become important in just a second. So I have StateChangeAI. Cool. Now I'm going to need real-time hash. The real-time hash is going to come from where we originally set up in Xano. So let's go open up the dashboard. I'm going to open up in a separate tab because it's a little bit easier to work with that way. And we're going to once again go to that button in the upper right-hand corner and real-time settings. And here's my connection hash. I'm going to click copy there and come back over to my WeWeb and, you know, put in quotation marks and, you know, good to go. Now the next thing I need to know is, well, then that's, and then there's, there's a third thing we need to know, which is a workflow ID, but we'll come back to that in just a second. I'm just going to set verbose to true. And the reason we're using the verbose is that we don't need to worry about callbacks yet because we're just going to make use of console logging. I'm going to click over here and let me see if I can make it a little easier for you. See, see where it says inspect here? I did that by right-clicking on the screen. I can also do this using Option Command I, and you can also do Control Alt I if you are on a Windows machine, all of which will bring up the same thing over here. Now if it doesn't show up over on the right, I find it most helpful to look at the dev tools over on the right. But wherever you find them, you can click on this little three dots icon and decide where they're going to display. I find the most useful places for them to display is either undocked, allowing you to use a second screen, or having it over on the right-hand side. I find that sort of works best with the ratios of these wider monitors. Then I can go over towards this console and I'll be able to see what's going on. So the reason we're using this verbose is because it'll just do these console logs, which will create statements that will then show up in here. If I were to demonstrate that console.log, you know, hello from state change, it will just create the text in there, right? And so similarly, when these things fire off, it'll show SC Xano RT base and starting listener. And then when we get back messages, it'll say trigger an action, which is pretty cool. So let's close this up. Let us close that up. And we'll go to eyeball mode. And we're going to say start listening. It's starting to listen to our channel. It doesn't seem to be doing things exactly correctly though. So what I'm going to propose is that we refresh the whole page. That often makes things look a little bit clearer. So let's clear all this stuff out by pressing the ban button, and we'll press the eyeball again, and we will say start listening. Ah, see, okay, now it says a secure connection with a connection status. That's really good. That's a sign that we actually have some sort of relationship going on with Xano by making use of this little bit of code that we created. Now the next thing we can do here is we can go to our, um, uh, the, the little function we have here where we send the message to WeWeb, uh, and we set up the real-time event, this youtube/weweb, right? So let's now say, okay, we'll save that, that's not a problem, and we'll do a run and debug, and we're just going to run it. This should have the effect of firing off that real-time event, right? And then, um, I can go back over to your WeWeb and see, hey, look, Before it had connections asked, now it also has another thing that's called event. And this event, see, is from the channel YouTube WeWeb, has a payload with data of hello. Cool. This is getting somewhere, right? So the next big thing is, you know, console logs are nice, but wouldn't it be much better for us to send information over into WeWeb? And to do that, we're gonna need to build a bridge over to a workflow. And if we go over to the left-hand side of your WeWeb setup here, we'll go back to pencil mode. Everything gets tiny because I've got the stupid thing on the side. So we'll close this up for a second to be able to make it easier to read and nobody goes blind watching YouTube. We can click where it says Actions here. Actions on the left-hand side allow us to create what are called global workflows. Those are workflows that aren't tied to things like clicking a button, but things we can invoke whenever we decide. So we can New and we can give it a name. The name is going to be on, you know, Real-time event. Then we're also going to give it parameters, and the parameters we're going to call it is going to be, we'll call it action because that's the term that XAML uses internally, but you can call it whatever you want. It's not going to be of type text, it's going to be of type object because that's what XAML is actually going to be sending over to us. This has some promise to it. We're going to now say, and we'll add an action. And on the action, we're just going to, we'll just log it, you know, so we'll say log, right, and we'll say, got a real-time message. And the data display is just going to be whatever came from the parameters, right? So it's going to be from the parameters, we'll just say it's from parameters. Which is actually not that exciting right now. We don't have anything in the parameters, but we'll, we'll come back to that. Okay, so we'll close this up. Now, of course, this is us creating a workflow, but we want to be able to push information into the workflow. And to push information into a workflow from JavaScript, and I've done a video on this before, I can go to More here and choose Development. And on the left-hand side, it says Show Dev Information. I'm just glad it says Show Dev Information. It used to say Show Dev Informations. Because that's the kind of thing that transliterates better from the French. But here we have Show Dev Information. You can click this and you see how it gets this little blue guy over here, this blue UID. Fantastic. Now I can grab this UID by just clicking it and that will copy it to my— you see down here in the lower left, it shows I can copy to the clipboard and I can bring that to my other other workflow that went with the button to tell Xano, to tell our little bit of code to please invoke this workflow when you've heard the good news. So let's talk about how to do that. So we're gonna close this up and we're gonna go over to the button and we're gonna go over to the lightning bolt and click Workflow and Custom JavaScript and JavaScript. And here, instead of saying verbose is true, but if we scroll down a little bit, remember how we had these other arguments in here, right? Base URL, real-time hash, we've used that, channel, we've used that. Hey, look, workflow ID. So I had actually already introduced a little bit of code, and we can sort of see it more expansively in this other screen here, where it uses this workflow ID that's defined on line 5 down here at the bottom, where whenever it receives an event from the server, it will fire the workflow ID and pass it a variable called action, which will be the name of the parameter that sort of shoots into the workflow. So it is actually important in the workflow that we call it action unless you're going to go change JavaScript to accommodate this. So, uh, we now go back over to the— no, that's not it. Uh, go back over to my WeWeb, and I have my workflow ID. The workflow ID is going to be that GUID that we just copied from, uh, the other workflow. Keep in mind, this workflow here, this is the ID for the one where we push the button. What we wanted is make sure we put in for that global ID that we had. Whenever you're doing JavaScript stuff, you can add at the end of a line, put in a little bit of comments by doing slash slash. The green is the feedback that you're actually doing a comment, which is super handy. I can either keep or remove the verbose. I'm gonna keep it for the moment because my general approach is I add things, right, before I subtract. And then we can close this up. And close it up. And I'm going to close. I'm gonna say, ch-ch-ch-ch. Close that up. All right, and now we're gonna say, once again, we're gonna start listening to the real-time events, right? So let's Let's press— if I recall, we sort of need to refresh the page to make this stuff work properly. And then I'll click my little eyeball, and my channel ID will be— I don't actually— I'm not using this yet. So we'll say start listening to RT. And now it's listening. Now in theory, what should be going on here is if I were to look at my— data or, yeah, here's my logs. Okay, here are my logs. It says unexpected identifier channel coming through from my untitled workflow. And what was that? Yeah, okay, that's coming from this guy. So let's find out what I did wrong. And, and, and, and we're going to click on Edit Code. Oh yeah, so this is actually really important. I find it's actually kind of useful to be clicking on this Format Document thing, which actually will often not work if you have a syntax error. In my case, I have a syntax error, and the syntax error is the one that's at between this quotation mark and this // because underneath it I have channel and you have to separate all these things with commas. This is the kind of thing that people who are no-code really like. They sort of like the rails on this stuff so you don't get that kind of problem. And now see how it sort of snapped back into place? That's why I use this little format button because if I see the little snap, that's feedback back to me that I probably haven't made a silly syntax error like the one that I just created and that we were just seeing in terms of this unexpected identifier business. So let's close that up, close that up. Hopefully a useful lesson for you guys at home. And we will, you know, refresh the page just to clear things out. And I'll say, you know, go into eyeball mode and go to my log, right? And we'll clear it just so we can start clean. And we'll start listening to RT. Okay, so now we get, all right, all right, it's done some stuff. So it got a real-time message without much of the way of data. So we wonder what's going on with that. So now we go back So the got a real-time message is happening in the log because of this action we created that has a log event that says, on real-time event, got a real-time message with data. Well, right now the data is undefined, which is not as exciting as it might be. So, I don't think I have any parameters on this yet. I think I managed to set this up without creating parameters. Let's undo my error. See, I didn't actually create parameters here. So I'm gonna say this guy here is gonna be called action, right? Remember that was the thing that we saw in the code over here where this thing had to be called action. And we'll go back over to my WeWeb and the action is called, is a type of object and that's good, that's good. So that's done. And now when I do my log, I can say I want it to have my action. In here, right? So instead of the undefined, so the undefined, that was me not quite seeing what the mistake I made before. So you wanna make sure this thing does say action in order for it to work properly. All right, cool, cool. So we'll close this up and we'll now, you know, let's refresh the page just to reset our, reset the clock here. And we'll click on the eyeball again and we will start listening again. And if I go back over to here, you can see, got a real-time message with connection status, has options in it, and a payload of connected. Not super exciting, right? So let's give it something more to celebrate. And we'll have data coming in from real-time about YouTube WeWeb with the data of hello. And we'll say, well, that was already fine. So let's do run again. All right, and now we go back over to my WeWeb. I have an event. Look at that. Oh, look at that payload data. Hello. Not so bad. So now we can say, well, if payload data is going to be what's interesting in here, then let's go back over to our workflow. And instead of just saying the log, we're going to, you know, update a component. No, in fact, what we really need to do is set a variable and then that variable is gonna be able to set what's actually in the text. So let's set the stage for that. So we have here, the, this is some text, we can go back into pencil mode and this guy, we want to be bound to some kind of variable. So to do that, we're gonna go over here to data, we're gonna create a new variable and we're gonna call it display text of type text, fine. And then we'll create that. And we're gonna bind it to, you know, to the text areas can get bound to that particular variable, right? So now what should happen here is if I were to go back into eyeball mode and probably just refresh just to restart everything, and it'll probably start with blank text right now. There's nothing underneath it. And now I can start listening to the real— to, well, I can click on eyeball mode, start listening to RT, right? And we'll go back to log to make sure we see stuff here and all that's fine. In fact, we need to go back over to the workflow and actually add the set a variable. Let's see, we're going to change set variable value, right? So set, update, change variable value. There we go. And the variable we're going to set is called display text, right? And the value we're gonna set it to, I'm all, is gonna be from here. It's gonna be from action. And we're just gonna say it's action.payload.data. Of course it says it doesn't know anything about that. So by doing a question mark, It will keep it from just sort of exploding along the way, but it's not very exciting yet. Okay, so now we're going to do close here, and we're going to refresh the page. And we're gonna go to the eyeball, and we're gonna say start listening to the real-time, and see here, some stuff happened, great. And I'm gonna go back over to my Xano, and I'm just gonna go run that thing again. Remember, all it does is all it does is send over the real-time event. And over here, see, it says hello now. How cool is that? Now let's try how to— save, run again. Oh, it's another message from Say Change. See, now we're getting information being pushed down. Nice simple strings. We can actually push over things that are more complicated than that. But right now we're going to start with nice simple strings because it's easy to do. And because it's just in a workflow, we can do anything with it, right? You can be inserting into other variables that are then going to be used for displaying other stuff on the screen. It can be as complicated as you want it to be. But we're starting with a nice simple piece of text right now because it demonstrates how to make this whole loop go. Now, there is one more consideration that I want to talk about before we go, because I have created this so far premised on the idea that we have a static a channel, right? And basically the way this thing would have to work is everybody would be talking to the same channel. That's just not useful, right? So what I'd like to do instead is have it be that you're only gonna talk to your channel as opposed to talking to everybody's channel. So I'm gonna say in here that my channel, that this thing is gonna get bound to a variable. So let's go back to Pencil here. and let's take a look at the variable that it would go with. And in Fact, what should be here is going to be under data. Text that really whenever this thing changes, we want to reset a given variable. So let's create a new variable that we're going to bind it to and the variable is going to be subchannel, and it's going to be of type text, right? I want to start with blank. That's fine. Wait, where'd it go? New subchannel of type of text, and we'll say create. There we go. Now we have a subchannel. So now the next big thing we're going to do here is we're going to attach it to We're going to bind it basically to this particular form. And the way I'm going to do this is the somewhat silly way of doing this here. And I'm going to tell it to every time it changes, onChange, we're going to change a variable value. Of subchannel. And by the way, there's also something called answer that I could have used too. But I'm just gonna use this way for a second. And the value is equal to the answer value. Bing. Okay. So now whenever, so that answer is then being put into subchannel and the subchannel is gonna be more of a global function that way it's accessible from the other workflow. Okay. So now I've got that. It doesn't really have anything inside it. It's fine. But what we're going to do now is when we are saying, let's go communicate with, when I'm in this button and I want to say, I want to initialize my communication with Xano. Instead of setting it to YouTube/weeb plus, and then the variable called subchannel. And that way I'm dynamically building it. So previously, so it could be set to YouTube/weeb. It could also be set to YouTube-based and then attach it to something that I use, like something that's a specific user ID or something. Or whatever it is that's gonna be most helpful, right? And now I have my channel set up, and I'm gonna go close this up. And I'm going to go back to here and close this. And first, we're going to test the base case, which is, I'm gonna refresh this. And I'm gonna say eyeball, right? If I call this WeWeb, my expectation is that it will be able to work properly, and I'll be able to find that out by just running this. Yeah, another message that says change. Now if I set this to WeWeb, if I refresh the page for a second, if I were to set that to WeWeb2, eyeball again, I go to WeWeb2, I say start listening to real-time, and I go back over to here and I send the message, Nothing's happened, right? Because I said it was weweb2. But if over here I say, send it over to weweb2, then I can say save, and I can run that again. Now it shows the message. So now I've introduced dynamism, right? You can decide which sub-channel you're going to look at and have that be per user, per document, whatever, right? Because we've established how you can dynamically set that up in your Xano environment. We've also established that you can change that here. So what I can do here is I can say text sub-channel, and then I could say in here, this is going to be equal to we— YouTube slash Subchannel, and this is my preferred way of doing text substitution, is to just do a replace filter and to say I'm going to search, no, regular text, subchannel, and replace it with subchannel. Okay, update. And you know what, I'm going to also say that that should be something we do here too. So text, and we're going to say message. Save. And this is gonna be the message. Save. Now, here I can say this is going to be, you know, finished. And the message is, you have survived a big video on real-time. And over in Xanaland, I'm gonna say, we're gonna refresh this again just to clear out whatever the cruft was, and we're going to say eyeball and call channel finished, start listening. And over here, we're gonna say the sub-channel and a message, and the real-time event looks like it knows how to take that, good, and run that. And here we are. You have in fact survived big video in real time. So key points. Make sure that you turn on real time on your workspace. This is a per workspace feature, not per instance and not per function. You can create all the Xano push statements you want, but they won't do anything if you turn on the real time in there. Second, need to make sure you turn on the channel and ideally turn on support for subchannels. That way you can be having multiple channels having more targeted where you want your messages to go in terms of the relationships with which users or which sessions or which combinations of users and sessions. You do that through defining those channels. And by having sub-channels, they're also allowed to be dynamic, whereas the root channel always needs to be fixed. Like YouTube had to be fixed, but WeWeb and WeWeb2 and Finnish, those were all able to be dynamic. You're going to need to have a little bit of JavaScript code. You don't need to use mine, but like this is a relatively clean and simple way to get around the Xano client feature. And we establish how you're able to take this code, and then we also just added a little bit of extra stuff to it at the very top, which I will demonstrate again here. And we can say that whenever it listens to the real-time event, yep, and we have this code starting on line 9 that we copied in from script tag, but I created this stuff at the beginning which if I expand out a bit, it can be a little bit easier to read, where I just had these first 7 lines where we just invoke XanoListener, passing it the base URL, the real-time hash, the verbose, the workflow ID, and the channel. The workflow ID we got by using the dev information, right, that's sitting here in development for a global workflow that you had created. And the channel I set up as being the same static one with a slash, and then we will introduce whatever dynamism, which I was demonstrating by using that text box. Real-time features are super cool. They're going to make your apps much more snappy and responsive, and it's a feature that you will get, you know, among no-code tools. I think Xano is one of the earliest to the party, and you get complete control over when you're going to send over those messages. And this is really key. It's not just like subscribing to a database, kind of like what you get out of the of Supabase and the so-called real-time database features. It is you being able to decide what message is gonna get sent when, and that gives you a great deal of control to create extraordinary experiences for your customers. And I can't wait to see what you build next. I'll see you next










