Realtime Jamstack Apps With Ably
With tools like Ably, we can create multiplayer experiences on Jamstack apps quickly and reliably. In this episode, Srushtika Neelakantam will show us what we unlock by adding realtime features!
Resources & Links
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
JASON: Hello, everyone, and welcome to another episode of Learn With Jason. Today on the show, we have Srushtika Neelakantam. Srushtika, thank you so much for joining us. How are you doing today?
SRUSHTIKA: I'm doing great, and thank you for having me on your show.
JASON: I am super excited because we're going to do a few things that I love today. One is we're gonna build an app that uses realtime. And that is always one of my favorite things to do. And two is, we're probably gonna play with pictures of Corgis, which is my second favorite thing to do.
JASON: So, before we talk about that, let's talk a little bit about you. So, for folx who aren't familiar with you, can you give us a little background on yourself.
SRUSHTIKA: Sure thing. Hi, everyone. I'm Srushtika Neelakantam. I work as a developer relations engineer in Ably, which will talk about today. I fiddle around with lots of different kinds of technologies, platforms, different languages to see how we can use realtime data to connect all these different pieces together with sort of live exchange of information. So, really excited to be on the show.
JASON: Yeah, I think this is gonna be so fun. I, like, every time I get a chance to play with realtime, it's always a blast because there's nothing more fun to me than building an experience that we can all enjoy together, right? And while it's kind of fun to, like, get on Twitter and I'll tweet about the same thing while we're doing it, it's way more fun to be in the same app and watching the reactions fly by and that sort of thing. So
JASON: Before we talk about exactly what we want to do today, because I do think we have a really fun idea, I just kind of want to get your take on, like, obviously you believe in realtime, right? You wouldn't be working with Ably if you didn't think so. So, I'd love to hear what to you is the major benefit. Why would somebody want to add realtime to their app? What are they getting when they do so?
SRUSHTIKA: I think more than ever, now is the best time to sort of, like, talk about this with, you know, the pandemic and everything else going on. And everyone coming more and more online and collaborating online with sort of live experiences as well. Whatever is happening in the real world, we have a need with a lot of different use cases to sort of get that information as soon as it is being created. And I think realtime messaging is the most efficient way you can do that, because there are ways to sort of, like, just send a request, get the response back, et cetera, and sort of, like, do this at certain points when you require that information. But as it is being generated, you can't expect the person who's interested to know this information to know that there is new information available. So I think that's what makes realtime messaging really useful. And I think this sort of is creeping into, like, almost everything we're doing, right? We are working online. We are doing this livestream. There are people chatting with us, adding comments on Twitch. There are, you know, all these experiences happening in realtime is made possible because of realtime messaging. So I think we're moving only closer to userdriven experiences that way.
JASON: Yeah, and I think it's kind of subtle, but it feels like realtime is creeping into everything, right? And what I've noticed is, like, the experience that I didn't realize I wanted until I had them that realtime has made possible. So, a good example of this is if you use the Headless CMS, they have this feature if you're logged in and editing the same page as somebody else, they will show that person's picture and say, hey, so and so's in this document, and more importantly, they will lock a field that is being edited so that you don't accidentally override each other's stuff. Or, you know, another similar implementation of this is in Google Docs where multiple people are in the page at the same time, and you can follow their cursers around, and if somebody's giving a presentation, you don't have to necessarily be doing a screen share, you can actually look at the same document and see where their curser is. Tools like Nero and Figma have these nice realtime experiences where I can drag someone to my curser. VSCode Live Share. These are all things that are possible with tools like Ably. So, you're focused on the web or is Ably is Ably kind of broader than that and web is one of the targets?
SRUSHTIKA: So, web is one of the targets. Ably can, I think, literally work on any platform. It has a bunch of different SDKs. It also has different sort of protocols, and what do you call it, protocol translations in build. So, you can have an IoT device working on the MTTD protocol sending a message which a web page is subscribed to in realtime, but on the whole, it's working on web sockets. So, you can do that with Ably with no relation to the actual underlying protocols or infrastructure even.
JASON: So, if I were thank you for the sub, Neonflights. So, if I, for example, had an idea that I wanted to, say, my partner is into plants, right? And so she gets an IoT sensor that can detect the moisture level of the soil in one of her potted plants.
JASON: You're saying that we can set up something where the moisture level hit whatever threshold, Ably could push a result or a notice to, like, a website that says, you know, Marissa forgot to water her plants?
SRUSHTIKA: Definitely. That is 100% possible. I actually had a I actually had a live webinar where I built this app which is very silly, because, I mean, it tracks schedule of when someone is entering the office building, and I'm almost always late.
JASON: Oh, okay.
SRUSHTIKA: So, it doesn't work for me. It actually detects the sensor of the access card being touched on the, you know, sensor, card reader or whatever, and then uses that information to publish that message to Ably, and Ably in turn will publish it I mean do all of its magic, and at the end of it, you get an update in the standup channel on Slack saying, hey, this person is now in the building.
JASON: Okay. So, now I want to build a thing that would detect when I go live on Twitch and turn on the little red light that's, like, in session. Oh, now I want that. Okay.
SRUSHTIKA: Even the tweet you made, as soon as we started the livestream, you could automate it entirely when you click on, you know, start. Twitch must have an API which tells you that. So, it just sends an automatic tweet.
JASON: Okay. All right. Well, you're getting me sold here. I mean, and this is really one of those things that, like, okay, so, we're talking about so many different services that we can now plug together because we have access to these sorts of realtime things. So, specifically, when we're talking about realtime, let's talk a little bit about what's actually happening. Because I think that especially for me when I first learned about realtime, I had a hard time understanding what is actually going on, because it's not like when I, like, if you and I are on a website, I'm not on your computer. I'm not, you know, I'm not touching anything on your computer, so, can you talk a little bit about what the actual process is? Like what's happening?
SRUSHTIKA: Yeah, so, essentially, I think it would be good if I told you how this works under the hood.
SRUSHTIKA: To make this possible, right? So, we know that over the internet, if two people have to communicate with each other, it's essentially using the hypertext protocol or HTTP as we more commonly know. So, for example, you need to get information from me or let's say a central server. You would send a request to that end point. Depending on what your request is, I will send back some information for whatever you requested, if I have it. And this is okay for things which are, you know, infrequent, because you're just doing oneoff requests for information, right? But for realtime use cases, we are talking about chat, we're talk about multiplayer games which two people or even the Google Docs, which multiple people over the globe are actually working on at the same time. So, there's only almost, like, a few milliseconds worth of delay for the information to go from one person to the other. And in that sort of a scenario, if you're just, you know, relying on request response cycles, it adds to a lot of overhead and delay, which is not acceptable in these use cases. So, instead, what you do is actually there is a middle step in that where from HTTP, you can think of something called long coding, where you're still sending a request, but you're getting a bunch of responses back together. Like a bunch of data back together. Instead of repeating, let's say, three or four request response cycles. You're just sending one request, waiting there, collecting some information, and bringing all of that together, which would have which would have been three requests in terms of HTTP. Even so, let's say a multiplayer game, we don't want, you know, batches of data. We want the data as soon as it's being produced.
JASON: Right. Right.
SRUSHTIKA: As more the data can be. So, now with realtime, we now have a protocol called web sockets which starts off as a HTTP handshake. Because HTTP and the standard and everyone is compliant with this. Web sockets, it's not the case with that, right? Not every device speaking to the internet is compliant with web sockets. So, you start that off as an HTTP handshake. You include an upgrade header saying, hey, I would like to upgrade this information to one that works over web sockets. Are you compliant? If yes, we can do that upgrade. If the other party is compliant, they say yes and switch to biodirectional and duplex connection. What that means is both the parties can talk with each other at the same time, and also that connection remains open for as long as the application that they're communicating on is running. This mean that, you know, for you and I do sort of chat, we have an open connection, your computer and my computer have an open connection, and whenever I'm sending something, it is pushed to you because you're already subscribed to it. Like a magazine, you subscribe to it, and they automatically send it to your home. You don't have to go to the shop and get it to see if it's available or not. So, that makes things very efficient.
Having said that, web sockets is not just the only protocol for realtime messaging.
SRUSHTIKA: There are also things that I was mentioning for IoT and stuff, which is a different kind it works in a slightly different way, but the premise of it is the messaging pattern where people are, you know, devices are either publishers and subscribers or both, and all the information is pushed to subscribers of that information so they don't have to request it from that end point which is making that information available.
JASON: Nice. Yeah. And what I like about it is that when you start working with this protocol so, and everything that you just described is a lot, right? Like thinking about web sockets and this upgrade handshake and all the things that you have to do there. That's why a service like Ably is valuable, is because you do all of that for us, right?
SRUSHTIKA: Yes. Actually, it's not just masking the web sockets protocol to give you, like, pub/sub pattern on top of it just to use out of the box, but also the infrastructure, because it's probably easier to scale things that are working with HTTP, right? If one server is overbooked, you go to another server. You just redirect the request using a load balance or something. With web sockets you have persistent connections, so what do you do to make sure the information is remain consistent with all the server end points you're speaking with. Scaling that web sockets becomes very complex. Ably provides infrastructure along with the pub/sub messaging.
JASON: I have to give you respect for keeping your concentration throughout this nonsense. Cassidy has arrived in the chat. Hello, Cassidy. I also saw that Ben raided a minute ago. Thank you, Ben. Welcome, everyone. We're talking about realtime today. Well, we're not talking about anything right now. We're just getting buried in boops. But thank you very much, Jimena sub. Thank you very much, 503, for the sub. At this point, I think we have to let them get it out of their system. This is another application of realtime, by the way. So, this is the way that this works is that whenever the boop emoji gets used on Twitch, it fires a realtime event to my stream overlay, which then triggers one of them to fall from the ceiling. So, when someone like Cassidy gets the urge, they can just spam boops until there is nothing left of us.
SRUSHTIKA: That's awesome. We should build something like that with Ably.
JASON: Yeah, I actually think this would be super fun, right? And this is kind of the benefit. So, for me to do this, I had to build a whole realtime implementation. It was a huge pain, and I don't even think it works very well. So, having something that would make this more consistent, that could make this more predictably multiplayer would be really fun. Because one of the things that is true here is, like, I have no replay ability. Like you want to see me make Cassidy really sad? Watch. I'll reload this scene. And, look, they're all gone. Bye.
But there's so, there's no persistence here, right? And there's no replay ability. I can't go back in time. All this work that happens on the Ably side, I would have to go implement that myself. And that would be fine. But it's a lot of work and I don't really want to maintain it. So SRUSHTIKA: And that's not what you really want to build, right? You just want to get your boops on the screen whenever someone clicks on it.
JASON: Exactly. I am really looking at shortening the time to boop. Oh, we've angered Cassidy. Look at this.
All right, chat. All right, you win. SRUSHTIKA: I really love the time to boop, by the way. Code by Jason.
JASON: So, with that, I feel like maybe we should start let's maybe jump over and actually write some code. What do you think?
SRUSHTIKA: Let's do it.
JASON: All right. Here we go. So, I'm gonna move us over into pair programming view. While we do that, this episode, like all episodes is being live captioned. We've got Jordan with us today. Thank you so much, Jordan, for hanging out. Jordan's from White Coat Captioning. If you want to see those captions, they are on the homepage, learnwithjason.dev. There it goes. That's the link. And that is made possible by our sponsors, Netlify, Hana, Hasura, Auth0, all kick in to make the show accessible to more people. I very much appreciate that. While you're checking out the homepage, these are the links you can click them. We're hanging out with Srushtika. Make sure to follow her on Twitter. That's the link. Make that happen. We're using Ably today to build this thing out. Get over there, check it out. And I think this is where I need to start, right?
So, I'm at here. I don't have an Ably account. I don't have any projects set up. What's my first step if I want to jump in here?
SRUSHTIKA: So, you would sign up for a free account.
SRUSHTIKA: Either using the button at the topright or on the central screen. Yep.
JASON: Oh, good, I can sign up with my GitHub. Let's do that.
JASON: All right. So, I'm gonna authorize Ably. And let me let's see. That one? Eh. So many. Okay. Here we go. Here we go. All right. So, I am setting up an account. Yeah, Netlify, good. I agree and consent. I'm not a robot.
JASON: All right.
SRUSHTIKA: So, I should mention here that we are improving this developer experience, because when you arrive to this page, we have realized from a lot of feedback that it may not be clear why you have these three options, because at this point you're very new to the service. So, while that's being done, I can help you out here. So, the first one is what we need at this point because we are building realtime apps to sort of communicate with each other. The second one is more meant for different data streaming companies or services, enterprises wanting to stream data to millions of users. So, for example, let's say Tennis Australia is doing different kinds of matches, right? And they want the to stream the scores that are happening live to millions of users across the globe. So, you would just use that service, which is called API Streamer, and just allow millions of subscribers to create their own Ably account and subscribe to your feed, if it's free.
JASON: Oh, okay.
SRUSHTIKA: If it's a commercial one, you'll date it and only invite people to subscribe to your service.
JASON: So, today I'm going to click realtime apps?
JASON: Is it gonna let me
SRUSHTIKA: No, I'm not sure. Oh, they did. Oh, cool. Okay. So, nice. Oh.
JASON: Oh, wait, did it, like, break break? Uhoh.
SRUSHTIKA: That's cool.
JASON: Okay. Nope. Not this one. Logging in with GitHub. This. And we're logged in. Okay.
JASON: So, this API key I'm gonna need to roll, because we wouldn't want people to use that.
SRUSHTIKA: Exactly. So, you can you can copy that here or you can, again, access it any time when you get to your dashboard. And below that, you would see that you have different code snippets. So, it's literally three lines of code to publish, three lines of code to subscribe, and you have realtime messaging on any, you know, any number of devices working.
SRUSHTIKA: Right away.
JASON: Yeah. No, this is great. Okay. I like that you've got the different language snippets set up. That's really nice. And I do like that it kind of auto completes with the API key. So, if I oh, nice, subscribe only. That's also cool.
JASON: So, like, this one could be public if I wanted to have, like, a stream, right? Of just people seeing the
SRUSHTIKA: Yes, but if you're using that as well and you would like to publish some information, you can't do that because, like, the whole API key is subscribe only. But if you want to use that for subscriber applications, like let's say you have two applications, one with which you have the admin control, you know, you're doing different things, and the other one which is only you want it only to just listen to information and not do anything, you can use that. But you can come back to the dashboard later and set up, you know, different keys with different permissions. Subscribe, presence, publish only, et cetera.
JASON: Great. Okay. So, I've got my account. I've got an API key. It looks like I've got the ability to both send and receive a message here.
JASON: Should I like what's what's our next step here? Should I, like, set up the little toy app that we were gonna build today?
SRUSHTIKA: Yeah, let's do that.
SRUSHTIKA: We can sort of load a script file and add this in.
JASON: So, here's our idea, chat. Here's what we're gonna do today. We are going to build a Reactions app so that you can react to a picture of a Corgi, which is always my favorite way to use technology. So, let's open up I'm actually gonna why did I open this? I meant to open up the terminal here, because I'm gonna create a new folder. So, let's go into we're gonna make a directory. We'll call this realtimejamstackreactions. And then we're gonna get into it. All right. Let me get init, and then I'm going to open up this folder. So, inside this folder, it's just empty, and I want to create a new file. And it's just gonna be a straightup index.html.
JASON: Realtimejamstackreactions with Ably. And then in here, we are going to set up our basic site. So, let's give ourselves a main. And in our main, we will have a div, which will be our image. Right? And then below it we'll have a form which will be reactions. And we'll figure out how to do the rest of that later. But for now, let's just make should it be a form? I think these are just gonna be buttons. Yeah, these are just gonna be buttons. So, instead, let's make this a div, and we'll give it a class, and each of these is going to be a button. And the button will be for, like, a different thing. So, we want oh, no, I forgot how to what for emotes. Quick, chat, you know accessibility. What's the right way to label? It's like Aria is it Aria label? But let's do some reactions. So, we need to do a span. I can't remember exactly what the thing is. I'm hoping the chat is furiously googling this for us right now. Let's add another one.
SRUSHTIKA: I think it was Aria label. Yeah, it is Aria label, as you said.
JASON: Oh, perfect. I'll add heart eyes. And then we'll do maybe maybe one more, which is gonna be, like, do a we'll just add a dog. Those are all good reactions, right? So, let's wait, no, in the span, span, span. Go aria label. And each of these needs to be a thing. So, this one will be purple hearts. This one will be a face with heart eyes, and this one will be dog face. Right? Okay. So, now we have these pieces here. Let's go get ourselves an image. So, I'm gonna go to Unsplash and look up a Corgi.
SRUSHTIKA: Oh, very cute.
JASON: This is a very good Corgi. This will be our Corgi here. So, we're gonna copy the image link, come back here, and Unsplash is unique in that they like hot linking. They're one of the only services I've seen where they're like you need to hot link. Corgi lying down looking real cute. Okay. So, now we have the basics of a site here. Let me add a style tag. And let's just run this. Let's get it running in the browser. So, I'm gonna run Netlify Dev, and this should get our site up and running. Opened it in this browser. Let me pull this over. Here we go.
So, we've got the basics of what we're doing here, right? So, let's make this look a little bit nicer. So, I'm gonna pull this over to the side. And let's add just a teensy, tiny bit of styling. So, I'm going to set let's add main. We'll give it a display of flex. We'll give it an alignitems of center and justifycontent of center. And then we're gonna take the image, and let's add go in here. Image, right? Then we can make this one a maxwidth of let's say 500 pixels. And then we're gonna give the image a maxwidth of 100%. Okay. We got that. I just realized we need to set the flex direction on this. Nope. Flex direction column. Look at it go. Beautiful. And then we need to also set the height on this. So, let's set the height to 100 height. Hey, vertically centered. So, then we can come into these reactions, and let's just add a little bit here. We'll go with Morgantop of, like, 2rem, 1rem. I feel like that's pretty good, right? That seems okay.
SRUSHTIKA: That's good.
JASON: Let's maybe make the buttons font size, like, 2rem. Yeah, bigger button seems like a good call. And we'll give them just a tiny bit of margin. Okay. So, then we can go over to this inspector style sheet and grab all these and drop them right in. Bam, we got an app. So, then if I refresh this, we should have kept all of our bits. We did. Ong. So, this is all good. This is, like, the basics of an app. It doesn't actually do anything yet, but let's go ahead and deploy it so that we can when we add the realtime, we can see that stuff happening, and everybody can try it out. So, I'm going to gitadd everything here. I'm going to GitHub repo create Learn With Jason, realtimeJamstackreactions. It's gonna be public. All right. Then we can git commit. Work in progress. Markup, no interactivity. Let's push. And then we're going to initialize this. So, I'm going to use Netlify NIT. We're using the Netlify CLI here. Create and configure a new site. Put it on my site or my team. We will call this realtimejamstackreactions. Good. My build command, I don't need one because it's just an indexed file. Deploy the current directory. We don't have any Netlify functions yet, but I think we might end up there, and I'll let it create a Netlify.tumble. That sounds pretty good. That puts us in good shape here. We've got our site running. So, let's open up Netlify. And it opened up in this browser again. I don't know why. That's my primary browser here. But now we have a site. Here's our realtime Jamstack reaction site. Nice and fast.
JASON: Like, love that. This is one of my favorite things about building in the Jamstack is this site is now live, it's running, we can do whatever we want with it, y'all can go and look at it, but it's not doing what we want just yet, because the thing we really want here is I want to be able to track counts of reactions. We don't have time to do the animation I'd love to do where they fly around. Imagine that's what's gonna happen. Instead, we'll just keep track of the number. So, I have now reached the extent of my knowledge. I can get this to look right, but I can't get it to do anything yet. So, what should my next step be?
SRUSHTIKA: So, if you go back to the page where you signed up for the Ably account
JASON: Yes. Here.
SRUSHTIKA: yes, perfect. So, if you click on try this in the browser, just so that we can grab the CDN link. Go to HTML. Yeah. You see the CDN script there for Ably?
JASON: Not J query, just Ably.
SRUSHTIKA: Just Ably. Add that to your HTML.
JASON: Okay. Let's stick this right here.
SRUSHTIKA: Perfect. Now, if you go back to the signup page, just the main one where you had those three yeah. Just copy that and paste it into JS File, which thinks to that HTML.
JASON: Okay. So I think since we're going simple, is it okay if I just put it here? Is that all right?
SRUSHTIKA: Yeah, that sounds good.
JASON: Okay. So, let's drop this in. All right.
SRUSHTIKA: You already have the key there. We are using the test channel, as you see there. You can change that to anything else that you may like.
SRUSHTIKA: Yeah, perfect. And the channel.publish thing, you need to do that on button click.
JASON: Got it.
SRUSHTIKA: And greeting is event name and hello is the data, and we can send an object instead of hello, and instead of waiting.
JASON: Okay. So, let's do this. Let's get let's get a function set up, and it will be handleReaction. And I guess we don't really need to do anything with an event because it's just a button click and it doesn't have any, like, nothing's actually gonna happen right now. So, what we can do is we can say oh, no, we do need that because we need the event target.
JASON: We'll go event.target. So, our event is gonna be the our button is gonna be the event.target. And then what we can do is we're gonna channel.publish, and we want to publish to just greeting
SRUSHTIKA: Yeah, or we could call it new reaction as the event name. So, the first parameter is event name that you're publishing.
JASON: Okay. And so we could do let's do this. Let's do the type, and then the type, let's give each of these a datatype, and we'll say hearteyes and dog. So, then we can get that out and, wait, what is it? Crap, got to look it up. How do you get an HTML data attribute? Using there you can tell I've been here before.
Dataset is the one I was looking for. So, we can then get type will be button.dataset.type. And then count, we can just make 1, because it'll we can even call it something you know what? We don't even need that, do we? SRUSHTIKA: Yeah, because we can add it in the subscribe callback. So, we can get rid of that other publish thing outside.
JASON: Okay. And then for each button. So, let's do document.queryselectorall' button' and then we will. Did you just figure this out for me? That's kind of magical.
SRUSHTIKA: How is it doing that? GitHub Copilot?.
JASON: Yeah, GitHub Copilot. We can go for each button. For each of these, we'll do button.addeventlistener click, handleReaction. Awesome. If that does what we expect it to do, this will send a new reaction, but it
JASON: We won't see anything really, right? Well, I guess we could see it in the network tab. Should we look at that?
SRUSHTIKA: Yeah, also there is a dev console in Ably if you want to check things out there.
JASON: Let's do this. Let's run Netlify Dev. That will get our site back up and running here. So, here is our thing. So, to find my dashboard
SRUSHTIKA: Yeah, apps dashboard. Perfect. Yeah. Click on the yeah, that's the only app you've got.
JASON: Okay, so, two peak connections. That's the maximum we've got. I assume that's because I refreshed the page.
SRUSHTIKA: Yes, one is the app that you're using and the other is the previous page that was showing you it was running live.
SRUSHTIKA: So, if you click on that default app
JASON: There we go.
SRUSHTIKA: Go to the dev console tab.
JASON: Dev console?
JASON: All right. Let's do this. I'm gonna move this to one side. Then we'll get this over here. We're gonna look at here's the local host one.
SRUSHTIKA: Yes, one thing you need to do on the dev console is if you scroll down, there is a place where you can subscribe to a channel. Yes. So, channel so, you enter reactions. I think that was our channel name. Perfect.
SRUSHTIKA: Here, you'll get all logs whenever something is published.
JASON: Excellent. Oh, wait, I pushed the wrong button. Let me reload this. And now new reaction.
SRUSHTIKA: Look at that.
JASON: Hey! I think I sent the wrong data, though.
SRUSHTIKA: We don't have data coming in.
Okay. So, we need to get up to the see event.target. what is it? There's a thing for this. Mdn find nearest processer. Maybe. So, if we want to get to div. Okay. So I think we do closest button. Look at Copilot reading my mind.
SRUSHTIKA: Oh, wow, that's crazy.
JASON: So, that's magic. Let's try this one more time. We should get tada! Okay. So, let me reattach to this channel. Let me reattach to reactions.
SRUSHTIKA: Oh, why did it go away?
JASON: I accidentally refreshed the page. So, now we get heart.
SRUSHTIKA: Look at that.
SRUSHTIKA: Very nice.
JASON: Look at it go.
JASON: So, this already we're, like, we're just humming along here. So, then the next thing to do would be to listen to this event, right?
JASON: Okay. So, to do that
SRUSHTIKA: So, you just subscribe on the same channel with channel.subscribe.
JASON: Come on.
SRUSHTIKA: That is amazing.
JASON: Okay. So, we got channel.subscribe, and we're going to reactions, right?
SRUSHTIKA: Yes. No, sorry. So, new reaction is the event we need to subscribe to, because that's what we're publishing.
JASON: But didn't we call it reactions? Like is this is the channel name?
SRUSHTIKA: Yeah, but we are calling subscribe on that channel already, because it is channel.subscribe. I mean, we could actually give it a reactions channel. That's the name of the variable, because it's confusing. Otherwise
JASON: Okay. I understand. So, in subscribe, am I calling it with no arguments?
SRUSHTIKA: You can leave the first argument, add a callback in a second parameter, but you can also add the event name, which is new reactions. So, it will subscribe to only that event in the channel.
JASON: Got it. Okay. I definitely misunderstood how this worked. And now I get it. And I'm very excited. So
SRUSHTIKA: We can actually I generally name the channels according to what the channel is. So, in this case, like, I would have called the variable reactions channel to say reactionschannel.subscribe. Then it sort of makes sense in the head. Not as confusing.
JASON: Got it. Okay. Actually, that does help a lot because that clarifies what's happening. We're already in the reactions channel, so I don't need to subscribe to it. I need to subscribe to the event. Got it. Okay. So, then in here, we should be able to do something like let's do let's do this. We're gonna put in span of class currentcount, and we'll set that at 0. And just duplicate that across. Okay. So, then in here, what we want to do is we want to get the button is going to equal are you serious right now? No way. Is that correct? Hold on. Get the button with the data type of event.data.type. Is that what's
SRUSHTIKA: Wow. Oh, wow. Like how does it even know what's gonna come back? That's crazy.
JASON: I have no idea.
SRUSHTIKA: That's amazing.
JASON: That's magic. It's like it kind of inferred that from this.
SRUSHTIKA: Wow, that's very intuitive.
JASON: Unbelievable. Then we would be able to get the current count. Get out! Get out and don't
SRUSHTIKA: You don't have to do anything here.
JASON: Geez. So, we don't need that is actually oh, my God. That is unbelievable. Okay. So, it gets the current count. And then we would do button.query why am I even here?
I can't. SRUSHTIKA: Oh, wow.
JASON: I can't even handle this. Okay. So, I'm gonna have to turn this off just so that it doesn't like unbelievable. So, yeah. So, we're getting the button, and the button is whatever button matches the type that we sent for the event. Then we grab the current count by parsing the integer value of whatever's in this current count span here. So, that will just pull that out as a 0 or a 1 or whatever it is. And then and we're using base 10 is what that second argument is. Then we reset the internal the inner HTML of current count to be current count plus 1. So, we're effectively just incrementing that count by 1. So, theoretically speaking, if I save this and I go out here and I refresh,
SRUSHTIKA: Look at that.
JASON: It's doing the thing. It's doing the thing, and it looks great. Okay. So, then, the next thing that we can do is let's just go ahead and publish this thing. So, let's git add everything. Git commit. Get realtime working. Okay. So, let's push. And this should build nice and fast for us. Okay. That's live. So, now if you go to realtimejamstackapps. Everybody's already there. Look at them go. Yeah, so, it works now. We've got realtime events coming through. Lots and lots of Corgi love in here. And, I mean, this is amazing, right? So, one question that I do have, though, is I just published that API key, right? And so that feels like probably not what I would want to do, because if I was if we were doing anything other than sending these reactions, there would be issues of potentially impersonation or somebody sending something naughty and things like that.
You hackers. You dirty hackers.
JASON: Exactly. So, if we want to prevent the chat from mercilessly trolling us, what is the, like, how should we how would we approach that?
SRUSHTIKA: So, yes, you're very correct in that we never use or suggest using encourage using the API key in the front end app, front end script in any way because people can literally just take it, you know, pretend like they're you and publish information, you know, also do anything, right? So, instead so, API key authentication is only for, you know, testing development, et cetera. In production, you should always use a different authentication strategy which Ably provides, which is called token authentication. So, in that, what happens is instead of instantiating this would be the URL of an authentication end point which would be on auth server that you deployed or check some data back based on those credentials. You can make it return an Ably token request. That token request will be use by our front end line to authenticate with Ably successfully. So, in a sense, your own back end service has done the authentication step, you know, taken let's say if it is this email and this password, only then give the token, you know, token request back to the client. So, in that way, you basically made sure it's not being used by people you don't want to.
JASON: Yeah. Yeah. Okay. So, there's a question from the chat about the Ably so, the question is, what parts of this are open source versus proprietary? Is part of the Ably service open source? And which parts?
JASON: Okay. Great. So, then looking at that, it sounds like we have to do a couple things here. So, the first thing is we have to set up an auth URL and an auth callback. These are two separate end points we need to be able to hit, is that right?
SRUSHTIKA: So, that is two options of implementing token authentication. You have have auth URL or an auth callback. Let's go to the for the auth URL option. If you actually skip to step four
JASON: Oops. Clicked the here we go. This button.
SRUSHTIKA: Yeah. And if you switch to NodeJS. And then scroll down to the code snippet. As you can see, let's say this is an express server handling this auth end point, it is essentially creating a token request using that method and send that as a response back to the client. And we need to essentially implement this on a serverless function or back end server.
JASON: We're going to create Netlify functions. Let's do Ably auth URL.js. And in here, we want to exports.handler. That's going to be an async function with an event. That event is going to be we're gonna need the and for body, we're just gonna start by sending back, like, okay. So that we can make sure it will do what we want. Let's start with that. I'm gonna run Netlify Dev to make sure we've got our FUNCTION up and running the way that we want it to be. Okay. So, let me go to Netlifyfunctions Ably auth URL. It sends back okay. Next, it looked like there was a REST. Where did it go?
SRUSHTIKA: Yes, so, Ably actually has two types of SDKs. One is the realtime and the other is REST. If you're interested in sending requests but still use the service, do a oneoff request to see, you know, what data is just there on the channel, that sort of thing, you would use REST. So, for tokens, because we're just sending requests to Ably with the API key, we can use REST, but we can also use realtime. It doesn't matter.
JASON: Okay. So, I'm gonna install Ably. And then it looks like I get it like so.
JASON: So, here's what I'm gonna do. Let's get let's switch this over to be I'm gonna use const and change this to be an environment variable. Process.env.ABLY_API_KEY is what we're gonna call this. Then I'm gonna do these env: set. I'm going to pull this off screen, because you gave me an API key that can handle a little higher rate limiting, so, I'm gonna use that API key.
You hackers. You dirty hackers.
JASON: I know, I know, you hackers. Okay. So, now we have Ably API key is set, and when I run this, we're gonna have access to it. But let's get into respond to authentication requests. So, back to here. I want to REST.auth.createtokenrequests. So, let's do that. Rest.auth.createtokenrequests. Love that TypeScript auto complete.
SRUSHTIKA: In the example, the token params are empty. Let's say the front end user has logged in with Jason at something.com. I know Jason has an account with my service, and I know this person's username and client ID is this. I can assign that to this person and send it back. So, for let's say in a service where you're seeing, you know, who else is using that service, you can make the client ID or username or other information show, hey, by the way, these people are on the same page or, you know, adding reactions at this time.
JASON: Got it. Okay. So, I'm gonna use the callback format, because we're doing like the REST style. So, we'll do if error, we are going to call back with statusCode: 500 and a body of JSON stringify error. And then oops. All right. So, then we can take the same kind of setup here. Say else. We'll do a callback with status code of 200. And it looks like we need a header. Content type. Application/json. Then we'll do a body. And the body was JSON.stringify(tokenRequest)
SRUSHTIKA: So, essentially what's happening here is our function is communicating with Ably with the API key. Because it's not accessible to front end clients, it's okay to use the API key. For the front end clients, it is sending back the token request on a need basis. After checking the credentials. If they are okay to, you know, use that service. So, you sort of put that layer in between.
JASON: Okay. So, what I am wondering here is I don't I'm not passing anything in, right?
SRUSHTIKA: Yeah. I mean, the token request over there is empty. So, that should be okay. We will end up authenticating everyone.
SRUSHTIKA: And also not assigning them any attributes.
JASON: Okay. So, we can we don't need either of those, but what we should get now if we go out and run this again... is, first and foremost, we got that API key. Here. And then it runs, but it didn't like something. No, wait, that did work, though. Oh, it's because I made this async. Still didn't like it. What have I done? Status code 200. What have I oh. When you use the callback format, the response has to be the second parameter, because the first parameter is an error. Okay. So, now we have a keyname, we have a time stamp, we have a nonce and a Mac. So, the Mac is the actual device.
SRUSHTIKA: It's an authentication parameter.
JASON: Okay. Got it. Got it.
SRUSHTIKA: So, we need this URL. Do you want to continue using local host or actually deploy this?
JASON: We can we can do both. Yeah, let me go ahead and deploy it. So, let's git add all. And then we'll git commit. And we'll say work in progress. Add token auth URL endpoint. Shoot. I just crap. Git reset HEAD1. Yeah. Okay. So, now let's echo nothing into.gitignore. And then let's try that one more time with node_modules in git ignore. Yeah, that's better. Let's try that again. So, git commitm.
SRUSHTIKA: And also the environment file, if you have it.
JASON: So, I use the GitHub or the Netlify CLI to set the environment variable specifically so we wouldn't have to worry about it. So, now I can git push. Because I didn't push that, I don't have to do any rollbacks. I just skipped that so, we didn't actually, like, push that original broken commit. That's the power of fixing git mistakes before you push. That should mean this will be live here in just a second. Oh, no, it didn't like it. What didn't it like? Netlify function oh, you know what I forgot to do? When we added that we didn't add a package JSON. So, I'm going to npm init, and then I'm going to npm install Ably one more time. Okay. Now, if I git add everything and git commit, add package.json. Let's try this one more time. If you don't have a package JSON, it doesn't store the dependencies, which means it won't try to install them, which means your build will fail. If you want to avoid the callback method, you can use promises. We can look at ways does this REST SDK include a promises API if we wanted to do it differently?
SRUSHTIKA: Yes, there are there's information on documentation that people can check out to use the promise.
JASON: Nice, nice. So, yeah, we
SRUSHTIKA: That's okay. The response we get. What we need to do now if the function is live is get the URL for that function.
JASON: Function is live. That means that it the gonna be over here, but I can just copy/paste this one. Bring it over here. Blam! All right.
SRUSHTIKA: Awesome. So, copy that URL. Over here, the place we are instantiating Ably, which is in the script. So, we said newAbly.realtime is sent it just that stream.
JASON: Right. That Ably.realtime takes in a JSON object, in that you can either specify key, which would be this, or auth URL, which is what we'll specify now.
JASON: So, do I do it as authURL like this?
SRUSHTIKA: Yes, "U" is capital. CamelCase. That's pretty much it. If you go back, it should still work.
JASON: Now let's run it and make sure it the doing what we expect. Okay. So, here we are. I'm going to head out here. Reload the page. Bam, bam, bam. Things are going wrong. What have I done?
SRUSHTIKA: There is an error in the console.
JASON: Access is blocked by CORS. CORS!
SRUSHTIKA: I hate that.
JASON: That's fine. That's fine. We can fix that really fast. To do CORS I need to get my options request. Let's see, Netlify. There's like a just a nice little copy/pastable here it is. So, if we do it like this, we can drop in these headers right at the top here. So, what I'm gonna do is we're actually gonna do just if event. wait, what is it? Event.HTTPMethod is the one I was looking for. We're looking for OPTIONS because that's actually what gets called for CORS. There I'm gonna take this and we're gonna return it country actually check the body. You just have to send one. So, then we can do this. And let me just link to this Stack overflow answer because we didn't write this code. So, then what did I break? I have like an extra there we go. All right. So, this should fix the CORS problem. So, let's git commit am. What? Typos all over the place. Off we go. And this thing should deploy nice and quickly again. Of course. CORS. There we go. Off to the races. Let's start this thing up again. Netlify Dev. Okay. So, now it's you were not you were not blocked by CORS. Why are you blocked by CORS? I did the thing. We did what you asked. Let's look again here.
SRUSHTIKA: Did you refresh the page after that?
JASON: So, we're sending off request headers. Oh, it's running off as a get? Oh, I wonder if I wonder if I just need to include those headers all the time? Because let's just do that. Okay. So, we're not actually sending an options request. We're sending a get request, which is a different thing. So, a get request with these options or these headers should mean that we can call up from wherever the content type is allowed and we should GET, POST, PUT or DELETE. I don't want to get too lost in the weeds here. So, let's get add all. We will git commit. So my commit messages get increasingly frenetic as we get panicked for time.
So, now we get oh, here's a question. Do people use GraphQL with Ably?
SRUSHTIKA: They could be. We have used it in some of our interesting dev projects, so...
JASON: Yeah, I think because you could use Ably as the transport for, like, a GraphQL subscription or something, right? T yeah, we actually have a project which implements that and makes it available in NPM for anyone wanting to do that directly. You can have the GraphQL in the front end, but still use Ably's native platforms that don't support GraphQL.
JASON: Yeah, that's really nice. All right. Here we go. This time it's gonna work, everyone. This is the one. I can feel it. All right. Hey, look at that. No errors this time. So, let's get in here. Let's do some requests. Hey, look at it go.
SRUSHTIKA: Hey, look at that. Very nice.
JASON: All right. So, now actually this should work out here because we deployed it. So, let's everybody go refresh your browser and start doing some realtime. Let's make sure this thing works. Look at it go. Look at everybody boop this dog. Yeah, this is I mean, this is great. We're seeing realtime come in. And now we also have the benefit of when we look at the repo, if I go and look at my repo here, which, again, has opened in the wrong browser. Don't you freeze on me, computer. All right. If we go and look at this browser, what's on GitHub is not sensitive anymore. So, this is allowed to be published. Like there's nothing secret about this. And when we get into the function itself, this is allowed to be published. It's an environment variable, right? So, now we can actually publish this code. It's safe to share this out. Even though what we're allowing is effectively anonymous access, what we do have is when people post things through, and I'm not gonna look at the network tab, because I know what you jokers could do if you're being naughty, is if somebody was being a bad actor, we have their unique connection ID, and we can ban that connection. And, you know, if we were build more robust commands, we could try to ban an IP or things like that.
So, now we have a little bit more control. And you said earlier, I think, that we can take this further and actually make this it can rely on a login, it can rely on a
JASON: A.token or something like that, right?
SRUSHTIKA: Mmhmm. There is also other than token authentication, a subpart of token authentication is also JWT that you can use with any existing auth services that you might have that are already working with JWT.
JASON: That's great. I mean, this is awesome. This went super well.
SRUSHTIKA: Oh, wow.
JASON: You can see this is clearly the reaction we're after here.
SRUSHTIKA: Awesome. Very cool.
JASON: So, I mean, this but this is amazing. I love the fact that in, you know, I think by the time we stopped talking and started building, it was about 45 minutes ago, maybe a little bit more. But we've been able to put together a rough UI really quick, but we're able to wire up realtime communication, get that thing deployed on the internet, put it up in a way that's secure, that we can share safely, you know, no API keys required, and at no point did anyone on this stream, outside of when we talked about it in the abstract, have to think about a web socket connection or the, you know, the pieces like that. And the thing that's cool is, like, if you do go through to your network tab, we can see the web socket connection here. This is the thing that's really useful, is if you go and you look at one of these, you can see the messages, and it kind of shows you as messages come through.
JASON: What is actually happening. I find this really helpful to get a better sense of what's going on.
JASON: But, you know, we can see we can see a lot of information here, and it's a very kind of nice experience.
JASON: So, wow, Srushtika, we just owned it today.
SRUSHTIKA: Very cool. I see 62 people on the stream, right? And we're having, like, so many reactions on the actual page. If we wanted to share with everyone on the globe, we didn't have to change anything, because Ably is still taking care of this. Pay for the particular tier, you know, to be able to use more number of messages, but that's it. From the developer side, you're actually not doing anything.
JASON: Yeah, that's really amazing. So, one more thing that we had talked about and I don't know if we have time for, is you talked about the idea of presence. So, if we wanted to show how many people are looking at this page right now, is that something that we could implement in the next 15 minutes?
SRUSHTIKA: Yes, definitely. I think so.
JASON: Okay. How would we go about doing that?
SRUSHTIKA: So, I'm thinking we you know how Twitch has all these usernames? We can maybe give an input box for people to add in their usernames.
When they click enter, they enter a present set on the reactions channel. And we'll be able to see as soon as someone has entered the channel or exited the channel. In effect, like, enter the app or basically quit the app.
JASON: Okay. Would it be possible just given that I have no way to moderate to just say, like, "X" people are connected right now so that we don't have usernames?
SRUSHTIKA: So, yeah. Whenever you are subscribing to the channel, the place where you're subscribe to the channel, you can also let people automatically enter presence. So, here we won't get the username because no one is entering it and we don't have that ability from the auth side, but we can still get the numbers, right?
SRUSHTIKA: So, I can walk you through the documentation or directly the method if you like.
JASON: I mean, let's just drop it right in, right?
JASON: So, kind of going back to the basics here, I've got I'm connecting. This gets me authentication.
JASON: Then I go into my channels and I get the reactions channel.
JASON: And this is my connection to it.
SRUSHTIKA: Yeah, yeah. That is the channel instance. So, when you subscribe to the channel, you have subscribed to it. Now you have capability of receiving the messages coming on that channel. Immediately after that, let's make the user enter the present set. Present set is a separate thing you need to exclusively enter on the channel. So, you would say reactionschannel. here, we're only entering. We're not showing yet. If we were show, we would subscribe to presence on that later on.
SRUSHTIKA: So, right now
JASON: All right. So, I'll comment this later.
SRUSHTIKA: Cool. So, reactionschannel.presence.enter. And enter is the method.
JASON: Okay. So, now we're in the this would be me saying "I'm here, everyone."
SRUSHTIKA: Yes, exactly. But to know you, yourself, or other people knowing who is on presence and who is coming in and going in, you would say reactionchannels.presence.subscribe this time.
JASON: And are the events, like, enter or something?
SRUSHTIKA: Exactly. So, you can subscribe to enter. You can subscribe to leave. You can subscribe to update. So, this one
JASON: Is update would update be, like, all of them?
SRUSHTIKA: No. So, update is as we said before, there could be some information related to every user, right? Like username or some other metadata. An update would be triggered whenever someone updates their presence information.
JASON: Gotcha. Okay. So, let's do this. We will just down underneath, we can set a paragraph and say 0 let's give it a span name. Span class. Currentpresencecount. And we'll say 0 people are here right now.
JASON: Okay. So, then what I would want to do is when someone comes in, I want to set the current number. So, does the event include, like, a total?
SRUSHTIKA: No. So, that event includes only one single member who has just entered.
SRUSHTIKA: So, it would be, like, one trigger of that enter event, you could increment a local count or something.
JASON: I got you. We could kind of do the same thing we did before.
SRUSHTIKA: Yeah, exactly.
JASON: We'll get the current count, but this time it will be current presence count.
JASON: So, we'll get our current presence count, and then we will set document. And then with this one, we'll just set equals. Current count + 1. Okay. And then for the others, let's do a leave. We could do a presence 1.
JASON: So, that, let's see what this one not even gonna check it. Let's just ship it. Git add all. Then we're gonna git commit. Show presence counts. And so there was a question about, like, getting numbers to sync up. The step that we're not showing here is we're not showing any kind of, like, data persistence. So
JASON: If I wanted to keep track, I would need, like, a database and I would write the database and then kind of send the updated counts over Ably.
SRUSHTIKA: Exactly. So, initially when the website loads, you would retrieve the existing count from there and show that and start the counter from there. That is one option. Even though Ably doesn't do longterm storage, it does provide, you know, temporary storage for up to 72 hours. Which means you can request previously published information by rewind on a channel at the time of subscribe. Or by ebbs police Italy using the REST API called History API by requesting previously published information on the channel.
JASON: Got it. Okay. So, we didn't check this, but let me see if I have an error in here. No errors. So I think if people start joining
SRUSHTIKA: Might be
JASON: I screwed something up.
SRUSHTIKA: I think I saw a warning in the console from Ably.
JASON: Let's see what it says here.
SRUSHTIKA: No client ID message. Oh, yes. That is my bad. You need to you need to enter with a client ID if it the I mean because we've implemented token authentication, we can just give them a random token in our Netlify function. So, if you go back to the Ably authURL.js, over there, we can basically in our token parameters that we had before, just like, yeah, over there, you can just say a client ID, and that could be some sort of a randomized
JASON: Yeah, this is gonna be ugly. I'm sorry, everyone. That seems okay, yeah?
SRUSHTIKA: Yeah, that should be good.
JASON: So, let's git commit. And we'll say add a random client ID. Okay. So, we'll let that build. That should just take a second. There we go.
SRUSHTIKA: Oh, no.
JASON: There we go. All right. Let's try this one more time. Let's see. It doesn't like invalid client ID. Must be a string. No! Okay. We can fix that.
JASON: We can fix that. So, let's do String. And now it's a string. Okay. So, then there we go. All right. This is it. This is the one. This is gonna be the thing, and then we're gonna get
SRUSHTIKA: Fingers crossed.
(Music) SRUSHTIKA: Jason seems angry.
JASON: Oh, my goodness. There we go. Almost done. And... off to the races. All right.
SRUSHTIKA: Okay. I think it's working.
JASON: It's working, and there's our presence. As people leave, they're coming in and out. All right. So, there's I mean, there are a million things
You hackers. You dirty hackers.
JASON: we want to clean up, but what's really exciting about this. What, we did that in, what, eight minutes or so? I think. For a quick and dirty how many people are looking at this web page right now, that is pretty dang impressive. So, you know, I really, really like this. I think combining this with any kind of authentication solution where I'm logged into a site and then I can just use that authentication as a way to determine presence. Because what it looks like, I didn't look deeply into it, but when you were saying token parameters, there was one for username. There was one for hey, what's up, Alex. Thanks, everybody. You're coming in right at the end. We just built some really cool stuff. If you want to play, go check out let me actually send the thing here. Go check this out. Go jump on here, and you can do realtime reactions, and these are gonna run across, and you'll all see the counts increment in real time, the number of people and the number of reactions. So, this is a really fun thing that we've done. We're using Ably for this. So, what else, like, I mean, there's a million things that we could do here. We are out of time, unfortunately, for, like, additional dev, but let's talk for a second about possibility.
JASON: So, if I am letting somebody log into my site, I'm gonna get a user ID.
JASON: And I can use that user ID as my client ID. I can set a username. It sounds like I can set arbitrary data, right, for whatever that token is. And once I've done that, I can have, like, we could send somebody's mouse position and we could do those, like, synced cursers were things all move around the screen.
JASON: What else have you seen? What are some of your favorite implementations of realtime that you've seen?
SRUSHTIKA: Definitely live collaboration. Like, you know, live curser tracking or, you know, editing the document or chatting. Things like that. Live collaboration has actually been really big in the past one year because of obvious reasons. So, that's definitely a big one. But also really interesting things like location tracking for when people are just moving around and you are able to track location of the person in real time on the map and see that on any device. That is also sending us GPS location in real time. We actually have a specific SDK called Asset tracking SDK. Where you get the UI benefits and out of the box realtime tracking on the map. So, that's pretty cool.
JASON: That's pretty cool.
SRUSHTIKA: We have things like multiplayer games, like, it doesn't have to be turnbased where you're just, you know, it could be turnbased games, but you can also have really interactive games where you just, you know, shooting away things not so violent, maybe, but essentially everybody is participating at the same time and is still able to see, you know, the same context of the game without, you know, messing the things up.
JASON: Yeah. This is super fun. I love all the ways that you can kind of start making collaborative web projects without having to become an expert in, like, web socket protocol or any of the lowlevel transport stuff. We can fire up Ably, fire up a site on Netlify and, like, off to the races. You know, in an hour, we can play with something like this. I'm just imagining how fun it would be to be able to do something where, you know, we could make these emotes fly up on Instagram live. We could show everybody's curser and everybody could be petting this dog right now. There are so many fun things we could do with realtime that seem feasible with Ably that I would have just been like, that would be fun, but I'm not gonna do it if I have to build the realtime link itself.
SRUSHTIKA: Yeah, definitely. One of the demos I had for a conference talk was, you know, virtual reality, which is accessible on the web, using this A frame library. Everyone in the audience, the conference, had that on their mobile. As they moved their phone in sort of real life, their Avatar danced around and moved in the sort of virtual space as well.
JASON: Oh, that's really fun. I mean, love stuff like that. And I saw a link in the chat to Ably Labs here. So, these are just, like, oh, a whiteboard. That's a great idea. Some chat stuff. Syncing stream videos. Now, this is a watch party app, right?
JASON: Didn't Daniel Pirri do this one?
SRUSHTIKA: We collaborated on that watch party app. That's how as part of that I realized what Jamstack was and what the buzz is all about and Ably is a perfect companion in that sort of new trend.
SRUSHTIKA: So, we built this, hosted, like, the app itself is hosted on Netlify, of course. And it uses Ably to synchronize the time stamps of the video. We can actually try that out if we have time.
JASON: Sure. Yeah. Let's see what I can do here. I'm gonna go in here.
JASON: Copy shareable link. All right.
JASON: So, I'm sharing my link.
SRUSHTIKA: Give that to the people in the chat.
JASON: And then to pick a video to watch, let's stream pub/sub. All right. And synced Rick Roll. That would be have been a great idea. Now if people jump in here with me. And, again, you can jump in here. Yeah, here's
SRUSHTIKA: There are four people watching.
JASON: Five people watching. And so I'm just gonna mute it so that we don't get a bunch of extra noise in here. But, like, now we should all be watching the same thing at the same time. And I'm gonna switch over to who's watching instead of the comments, just in case. But, I mean, this is super fun. You know, I love the things that are possible with this, right? So, we've got a list of cool projects. We've got Ably Labs. Where should somebody go if they want to take next steps?
SRUSHTIKA: So, definitely on Ably's homepage, you have links to everything that you need, direct links to documentation, all the features that it provides. I think one major thing we didn't talk about is integrations. How it has incoming and outgoing web functionality, which you can talk to thirdparty services and streaming data sources, you know streaming or queueing sources. As well as Netlify functions. So, you have everything on the homepage available. Just land there, figure out what you want to do and go to that page.
JASON: That's great. Well, great. Srushtika, is there anywhere else that you want people to know? I'm gonna to another drop to your Twitter. Anywhere else you want people to check out?
SRUSHTIKA: Definitely Ably Labs is one, and the website, that's pretty much it for now.
JASON: Awesome. All right, y'all. Well, this episode, like all episodes has been captioned. We've had Jordan with us all day from White Coat Captioning.
SRUSHTIKA: Thank you, Jordan.
JASON: That's brought to you by Netlify, Fauna, Hasura and Auth0. Thank them for making the show accessible to more people. Make sure you go and check out the dang schedule. This week is a little bit special because we have another episode tomorrow. Speaking of Daniel, we were just talking about him, the Ably example.
JASON: He's gonna come on tomorrow and we're gonna build something with Strapi, which is a whole lot of fun. We've done a little bit of Strapi on the stream before. I've seen it around the old interweb. There's a lot of fun stuff happening there. On Thursday, we're doing another one. We're doing three this week, y'all. We're going to have Moriel come on and talk about RighttoLeft support for websites. If you haven't seen RighttoLeft support before, come check this out. It's not as simple as it sounds. That's gonna be a whole lot of fun. Make sure you mark your calendar. Add on Google Calendar. We'll show you when the episodes are happening so you can stay up to date on that. Wow, what a great time. Thank you all so much for hanging out. Srushtika, thank you so much for hanging out. We're going to go find somebody to raid. Thanks, y'all. We'll see you next time.
SRUSHTIKA: Yeah. Thanks a lot for having me. I had a lot of fun.