skip to content

Let's Play With Realtime (Using Supabase), pt. 2

Join Jason to have some fun with realtime coding. Let's finish the app we started together last time with Supabase.

Full Transcript

Click to toggle the visibility of the transcript

Captions provided by White Coat Captioning ( 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. Apparently, I got my deejay voice on today. So, I am excited to be doing another solo episode. We've got a lot of fun stuff coming up on the show, had a little schedule reshuffling, and that ended up with me doing this one on my lonesome, which is actually kind of a blessing in disguise, because the last time we did a solo, I was playing with a multi screen idea for what a realtime talk would look like, like what would it look like if I had a presentation going, and you could have a second screen and interact with that in a way that would lead to something happening on the main presentation. So kind of live polling, live reactions. Kind of like what we do with the stream here. The stream is actually a second screen experience. You interact with the chat window, and the second screen, the overlay for my stream, is responding to that. So, we just saw some boops drop. Love that. So, I want to try to build is blender still running? No, blender is not still running. Also, how fun was that episode? Did you all have fun with prints? Any chance I get to hang out with Prince is a great, great opportunity. So, you know, like I said, the overlay on this stream, what you're looking at, all the framing around me here is this is all a website. It's a web page, right, and that has a real time API whatever. It's got a reactive layer on it. And whenever events happen, like subscriptions, or using a certain emote in the chat, running a command, any of those things, all of that leads to stuff happening. You know, you get overlays, you get the boops dropping. If you use enough of the party corgis, you get a stampede. All of those are fun ways to interact with the stream. So, how can we move this forward and bring this into different environments? This is an idea we had, because we're starting to get back to in person conferences, and I love speaking in front of people. It's really fun for me to get up on stage and have a conversation with folks, but I'm realizing that I miss the interactivity of Twitch when I'm not on Twitch. I really wish there was a way to have input from the audience while we're speaking. I think it gets too chaotic to do call and response. It can be off putting to introverts. Nobody wants to yell if they are an introvert. Not everybody wants to put their hand up, nobody wants to get called on stage usually. So, you find yourself in a situation how do people participate without prioritizing those folks who don't mind being big and loud. I think the answer becomes how do we make your phone into a second screen, or your laptop, whatever device you're using, into a second screen that will allow you to participate by pushing buttons. So, you get to be part of it. You get to influence the talk, but you're not required to really put yourself center stage. You know, you can participate without being perceived. And I know for a lot of folks it is important not to be perceived. So, this to me is a really interesting opportunity to build out better interactivity into real world spaces. How do we make a conference talk more interactive? How can we make even internally, could we make internal AMA sessions with the CEO, or other leadership, could those be more interactive without requiring people to grab the mic and ask a question. Those are the sorts of things that I'm interested in, and I was having a conversation at Render ATL, which was a really fun event. I was talking to James Q. Quick and a handful of other folks about what would those second screen experiences look like. We had an idea it would be funny if you think about how the Nielsen ratings system works, or how focus groups in TV shows and other types of media, they will have people watch the show, and they have a device in front of them. And as they are watching the show, if they are feeling good about what they are watching, they turn it to the right, and that indicates I'm enjoying myself, this is fun. If they are not, they turn it to the left. It's kind of a dial. So, in this case, they do it by kind of setting an extreme. Oh, I hate that. They crank it all the way to the left, right. Oh, I love that, crank it all the way to the right. If they are saying this is boring, they crank it a little bit to the left. I would like to get there. I think it would be fun to get that level of nuance, but for right now there's a general reaction. If I make a claim, can people say I feel good or bad about that claim? I gave a talk recently, where my click baity setup for the whole talk is full stack developers don't exist. Then I spend the rest of the talk explaining how full stack developers exist. Can you do something where the audience can say, oh, you just made me angry with that, I want to disagree with you, and, you know, that's the sort of thing that I think is really fun. Learn With Jason Discord. I don't know. So, the thing about a Discord is that I feel weird making a space that's predicated on me. I don't know, this is an interesting relationship with attention, right. I feel let's get philosophical, chat. You thought we'd see a rabbit hole on CSS this time, we're going to rabbit hole on humanity. I have this sort of I like the idea of creating community. And I like the idea of building a collective of people who are working to improve themselves and learn more and things like that. And I love the general concept of groups of people coming around, coming together around common interests. This is what makes me love the web dev community, why I'm a part of the communities I'm a part of. Where I get squeamish is when it becomes a leader/follower dynamic, because it's a short hop from leader/follower to cult. And I've seen this happen a lot in even in the development community, where someone kind of emerges as a thought leader, and before too long, and chat, I swear to God if you start dropping names, I'm going to be upset, so please don't do that. If you find yourself in these situations where people kind of emerge as leaders, and then you see groups form around them that kind of take everything they say as a fact. And what I get uncomfortable with is that idea of like I don't want to be a mentor with mentees. I want to be someone who has like minded people who are kind of co generating things together. Yes, Ben, yes, that's actually I love that. I used to have this on a T shirt before I wore the T shirt out. Hero worship kills communities. And that's at the crux of all of it. I have a big also, Tatyana Mac, she say near me, I should say hi to her. At the bottom of all of it, right, the thing that I fear more than anything is becoming somehow separated from the community. And I think that is a really it's a weird position to be in. And you can see it with some of the folks like just feeling like they can't participate in the community anymore, because everything they say has so much weight that it gets dissected and used as a weapon, and taken out of context, so they feel they can't really talk, because if they talk, it's taken as too serious. They can't joke, they can't, you know, you can't make an off handed comment. You have to deeply consider what it is that you're saying and what the impact of that is going to be. And, so, I find it a little all of this getting around to the original point. I'm not opposed to the idea of a Learn With Jason Discord, but I am nervous about introducing spaces that are built around me. So, if it's built as a community thing, it's super onboard. If it's built as a Jason platform, I feel weird. I haven't figured out how to do it without feeling like it could cross that line to hero worship. And, you know, one of the reasons that I love this show is that it doesn't feel that way. It's very you know, we're not acting like there's a separation. I'm working with the community. Y'all are working with me. And that co creation is a big part of that, which is, okay, full circle. We're back to this idea of participation and creating things together. So, from my standpoint, the goal here should be co authorship, co ownership of what's being generated.

So, I find a community type Discord. Yeah. I mean, yes, I'm definitely open to the idea. We should maybe talk about this a bit and see how that could potentially work. Because I do I have a Learn With Jason Discord, but I currently use it to coordinate guests, and I work with Aiden, who manages a lot of the web properties, and I work with Chris, who does the editing and the highlight videos and stuff like that. So, I use it in that way, but I haven't opened it up as like a general public thing. So, if there is a way that we could do that, that doesn't feel it's centered around me as a personality, then I would be very happy to create a community space. But, yeah, let's talk about that, chat, if you're into it. Maybe, I don't know, send me a DM or hit me up on one of the other Discords I'm in and we can talk about it. Okay. So, let's talk about what we're trying to accomplish today. So, what we did last time on this is we built out a screen that is, like, a slide. And we did it kind of quick and dirty, centered some content, and the slide makes a claim, is a hot dog a sandwich. Then we have a second screen, which is buttons. How do you feel about what is on the slide right now. And one of them was a yum face, yeah, hot dogs are a great sandwich. One was an angry face. How dare you call a hot dog a sandwich. And what we're trying to build out is the ability for the slide that says is a hot dog a sandwich to reflect the input from the crowd. The way we'd done that was put a meter, and this is where we fell into a rabbit hole, having a meter or two meters, you know, was it a select, whatever. That maybe starts in the middle, disagree, moves to the left. If they agree, starts to move to the right, and that puts us in a position where we have some form of feedback. A good prototype, something we can start with. So, let's dive into I don't know, let's find out. Let's go into yeah, let's just go into the programming mode. All right. And from the programming mode, I'm going to pull over the homepage of the site here, and we'll start like we always do with a shout out to our live captioning. We have Ashly here with us today from White Coat Captioning, who is taking down all these words, and making it more accessible to more people, which I very much appreciate. And that is made possible through the support of our sponsors, Netlify, Nx, Backlight, and probably as of last week, New Relic, who we finally have everything lined up, and we're ready to go. So, we'll get that set up, and thank you very much to New Relic for coming on as another sponsor. That really helps do all sorts of fun and ambitious things. And today you're dealing with me. Let's talk about what we actually built. So, last time that we were here, we were working on this realtime box. And let's do just a bit of a code review. Get this up here. Make sure that we can actually see the whole screen. There it is. So, what we built is we built two apps. We have the main talk, which is I think I used veet and just kind of generated a really simple React app. That gives us our let's see. And, so, we put together a slide that says hot dogs are my favorite sandwich, and then it has the hot dog emoji, and then we have the responses. And, so, how the audience is feeling, and then we got into our range elements and what the current sentiment was, and it starts at 50 and it will drop if it's people are disagreeing, it will raise if people are agreeing. So, if we run this, let's see, I'm going to have to look at how we set this up. We're using Nx here, Nx is also one of the sponsors. If I look at how to run a package, because I always forget this, we want to run Nx serve, and I think we put the name of the package in, which would be main app. So, let's run npm start. Let's see what would happen if I just ran npm start. It runs Nx serve and goes to the main talk. So, starts with our default thing. That brings us to our local host 4200. Here's our default set, and what we want is for this to move back and forth. You know, there are a lot of things that we can do with this. I'm not going to try to style this anymore, because I don't want to waste anyone's time. I want to get to the realtime part, because we didn't get that last time. We're going to leave this good enough for now and try to use our second screen to get this moving left and right. So, to do that, what we ended up doing was we set up a Supabase database. And we're using that for authentication and for a handful of other things, so that we can get our sign in. Wait, this is the wrong one. This is second screen. Let's get into the main app. The main app is going to pull in the insert, right, and now I did some of this wrong, and Jon Meyers was actually really, really helpful. So, let's take a look at what he did to make this better. This is Jon Meyers. And he very kindly saw that I was having a little bit of an issue getting all the things I needed working, working on Supabase. And he put together a whole video on this, which was wonderful. And he also set up a he set up a thing, what's the thing I'm trying to say? He set up a pull request. And that pull request will let us do some really good things with Supabase, and I don't have to figure out how this works, because Jon told me. This is kind of like having a bonus guest. I'm going to drop this into the chat. I forgot to drop a bunch of things. Here's Jon's Twitter, that's in here. Here is the homepage, if you want to follow along with the live captions. And let's actually pull up the repo, as well, for anybody who wants to see it. This is the repo as it stands today. So, you can go and take a look at what we've built so far. And I'm going to go back to the repo and let's look at this pull request, because it's going to let us walk through what should have happened. So, a couple things, we target only the sentiment table, and I can go to Supabase and log in, so we can look at our database as well. So, here is Supabase, here is real time talks, and we have our database, auth requests, all those things all working. And if I go and look at a table editor, we should have sentiment, and sentiment has a bunch of oats in this. When John was testing this, he agrees on a sandwich. So, that should give us actual data we can work with. And if we look in here, that's this table. So, what we're trying to do is get the any time someone inserts, which is voting, you click a button, it's going to insert a thing, we want to be able to do something. But to start we want to make sure we're getting that payload. Then because we don't want this to register multiple times and have multiple subscriptions running, any time this component unmounts, we return this remove subscription. So, that's thing one. All right, mark that as view. Then let's go look at in the second screen, cleanup to our auth, which is good. We don't get a user session, because we're using third party providers. We have to get those separately. So, that is why Jon removed these here. And then we can check if there's an error, we will log that error message, otherwise we don't really do anything at all. And once we hit the use effect, we're going to load the user by using the Supabase auth object, and that comes in from the client that we create. We can look at that in a second. And when the auth state changes, we're going to set the user, or set it to null, and I'm just going to assume that's good enough. Looks like I forgot to include this dependency array as empty. That would have meant any time you use this component at all, it would re auth, which we didn't need. Then we are going to insert, and it looks like I was using an array. I didn't need to use an array. So, we just drop in the one value. Good, good. And that will give us our thing. So I'm going to approve these changes. And submit. And let's squash and merge. Supabase. All right, now, there's another thing I have to do, which is turn on replication. And in order to do that, I need to go and look at what let's see, where did he tell me how to do this? He told me let's see if I can remember. It was in here, database functions (reading to himself) was it in databases? Replication, yeah, yeah, yeah. And we're going to set up sentiment, good. And now it's set up. So, that should work. I think I could potentially turn off some of these, but I'm not going to stress about it. And then if I go out here, and I git pull, good. Then I am going to just run again. Okay, come back out here. Let's open up our console. Make this a little bit bigger. And now what I want to do is let's take one on this side. And let's take this one on this side. And I want to add something to this database. Let's see, that's not going to work. I have to make this bigger. So, I'm going to insert a row. And we won't create an ID. We won't mess with that. And I'm just going to put in let's go with bad, and we'll view data oh, do I need to I'm going to need to get a user ID. Actually, why don't I go out here, and I'm just going to confirm. I'm just going to get a user ID out of here. Can I just click it? I would like to click this, please. There we go. Now I can come back out. Insert. Bad. Drop in a user ID, and save. Okay. And, look, aha! We got new data, and it says that we went value bad. So, this is good, because what this means I guess this is a bad, ha ha! What this means, now whenever we get an update, we should be able to pull in one way or the other to just kind of show what the general sentiment is. Why does it call sign in twice. Good question. Can you clarify what you mean? Let me pull up our changes here. We're going to go to our second screen, look at the source, and we're looking at the app, specifically. So, this one here, the sign in with GitHub, is what we want to run when you click the button. And that will actually, like, do the auth flow with GitHub. I should probably just start this. We'll try it out. That starts the auth flow, we'll reload the page, and what that does, it calls the is this user logged in and sets that user. And then whenever the auth state changes, so if you log out, which we haven't implemented that or anything, so we wouldn't really get it. But, you know, in the future when we do implement that, this would update that. But we only call that sign in once, I think. Yeah, it was probably the diff. And my diffs look weird, because I use the enhanced color blindness pattern, so you can see my diffs are orange and blue instead of green and red. I don't have red/green color blindness, but I do find this is easier for me to differentiate, and I just dig it. So, that's why that's happening and why you see the sign in happening multiple times. Yeah, okay, so, we have the ability now to react to this. So, let's do it a little bit. I'm going to try to do something here whenever we get out of the second screen and into the app. So, what I want is I want our initial state how are we doing on time? 25 minutes in. All right, we got some time. We got some time. Let me see just a second here. Sorry, one second. I got to respond to this text.

How professional is this? Least professional. (Reading to himself) not until 11:00 a.m. Best five seconds of television I've ever made? Okay, sorry about that. So, let's do I want this to move. So, we've got a default value, and we're actually going to do a controlled component here. So, I want the value to be set, and that value needs to be current sentiment, and I think the way that we will do this is we'll get rid of the default value, we'll set this value, and then up here, I'm going to set current sentiment and set current sentiment as a use state, which we'll pull in from React. And we'll default that to 50. So, then what we can do is we can let's see. The payload that we got, hopefully it's still here. It is. So, we will get a payload that includes new and old. So, I'm going to check if it's new. Are we going to check the new? We'll do const value equals So then inside of that we want to get the value oh, no. What if we just do that? That seems we'll whatever. You know what, we're prototyping. It doesn't need to be perfect, right? So, I'm going to get that value and say if the value equals wait, we can do it this way. Let's do set current sentiment to current sentiment plus equals is this too junkie? This is junkie. Don't do that. Even in a prototype, never do that. Don't be like me. Be better than me. Let's do an increment value. And that will be if the value is bad, we'll do 1. And if the value is good, we'll do a 1. And, so, we're going to do a value plus equals incValue. This should work, but just in case then we'll drop this one in here. Cannot set what? Okay, yeah, that's why. That makes sense. So, we're going to do a plus. So, it's either plus 1 or plus 1, which means it goes 50 or whatever. And the other thing we should probably do is just a quick check, where we make sure it's within range. So, we can do this is going to be gross. Math.min of 100, or math.max no, math.min of 0 in this value, and math.max of 100 in this value. Ta da! And that should put us at a it will be at minimum 0, at most 100. In line setter function, it could definitely do that. I think this will work. We can refactor later if we wanted to. So, let's maybe yep, yep, yep, yep, that could definitely be part of the problem. I don't think it will matter in this case, but let's run it. You provided a value prop without an onChange. If the field should be mutable I don't want it to be mutable. Or read only. I can set it as read only. So, let's set it as read only. And now it should stop yelling at me. Try that one more time. Good, okay. So, then what we can do, and basically what I'm assuming is any time you switch to this slide, you would want a new setup, right? So, this should be 50, although that definitely doesn't look like a 50, does it? Kind of looks like a 40. Value 50, though. Oh, min is 10. That's what I did wrong. Let's set these back to what they should be. I was trying to get clever last time. So, this is our 50. And we've got a min of 0, max of 100, that's set in both places. And we can now try to make this let's try to make this go down. So, I'm going to set let me go off screen, I'm just going to hit my clipboard. Come over here. Show the clipboard. All right, here is going to be our user ID, and here's our value. And I'm going to say bad. Let's save. Okay. So, it did kind of did what we wanted, but definitely didn't exactly work. So, why did that cause it to completely give up on us and go to zero instead? Oh, I know why! I did these backwards. Min and max should be the other way around, because we want it to be if zero is greater than, we want it to be zero. If 100 is less than, we want it to be 100. I got these backwards. That should fix it. Let's go back out and try it again. All right, let's do this one more time. I'm going to insert, and here is our saver. Got a little bit worse. One more time for just to double check. Go bad. User ID. Didn't do anything. So, it did get both things, but our value is still set at 49, which means something didn't get set.

If the value equals bad, we want the current sentiment, plus the increment value. Did I mess something up? Yeah, that's fair. Fair, fair, fair. What's up, Brittney? Thank you for the raid. Hello, hello. I'm bad at code. So, let's add some more console logs, because that's how I debug. We're going to go with value, new value, and let's find out what this thing says. Because the only thing I can think of is this is somehow completely re rendering, which would be weird, but it's not out of the question. So, we're at 50, right. Now, as I add things yep, I did. So, we're going to do a bad. So, if I add another one, we say bad. Should be 48, but it's not. Let's go to the console. We got a bad, an ink value, and we messed a thingy up. So, the function current sentiment is locked to first mount because of the bracket, but this subscription shouldn't be. Right, this oh, I see what you mean. Let's do that. Still a little confused by what try this one more time. Everybody bear with me. We're going to get this thing right. We got this in here, going to do one of these. Going to do one of those. Do one of these. Huh? Okay. Current sentiment is 50. Now, what I think y'all are saying, and somebody is probably screaming this at the computer right now, is that I am resetting this whenever it returns. Okay, okay! I get it. I get what happened. Let's see if I can explain what happened. So, the subscription being set up here is only happening on the first render, because we weren't passing this before. Now what I'm unclear on is why no, I still don't get it. Still don't get why that works. Hmm, hmm. Oh, y'all. Okay, I do get it. So, what was happening and what everybody has been saying, is it resubscribes each time it changes, which is not what we want. What we actually want is for the set current sentiment to be here. So, we want this to do it this is why everybody was saying that. Okay. So, let's walk through what just happened, because this is super confusing if you are not if this isn't clear to you what's happening, that's okay, because it's barely clear to me, and I've been doing this for 20 years. So, because we weren't tracking this, which is actually probably the right idea. We only want to register the subscription once. What was happening here is this is a closure. So, we were saying when you register this component, create this function. Now, this at the time of the first mounting, is set to 50. At no point after we change this value are we changing this setting to something other than 50, right. So, what's happening because we're not reregistering our subscription on every mount is we're basically saying use 50. We're hard coding it by putting this inside the closure. So, if we go here instead, and we say currentVal, and we just move all of this in here, right, and we, you know, we can do this however we want, but we're going to do it like this, and then we'll drop one of these. And that's it, right. So, we'll get that. Get that out of there. And then we need to return the new value, that's how that actually works. And we're going to use currentVal instead of current sentiment. Now it's not yelling at me, because we're not using anything that would be stuck in the closure, and we'll get the current value of the sentiment every time it goes. Okay, now we're setting up our closure correctly, using the set current sentiment. I'm doing this from memory, so this definitely might not work, but I think I'm in the right direction at least, so that, I guess we'll see. Let's try it out. No, my clipboard. This one. And then we need bad. Let me copy/paste this again, so we have it available. I'm going to save, and it worked. Okay. Let me refresh the page, because I think I might have just used a cached version of that. Did I save? I did save. And now drop this in, and new value is 49, current value is 50. And assuming I did this correctly, we will see the current value is 49 now. Okay. All right. So, that basically what we just did is we got all of that stuff put together, the closure is working correctly, and, yeah, as the chat is saying, this is the pitfall of useEffect, it is very smart, but you got to get your head around how this stuff works, and you need to have a good understanding of things like closures and what happens when you do that. But now that we've got this running, we can move to the second part of what I want to do, which is getting the second screen working. So, we can save this. I'm going to actually commit this now. Say get realtime sentiment update working. And I'll push that, in case anybody wants to look at it now. Again, that's all being pushed to this repo here, the realtime talks repo. So, yeah, yeah, yeah. It's a sharp knife. Yeah. That is true, Matt.

So, we've got our presentation side is doing what we want. I probably should have tested that it went up when we did good, but you know what, I'm going to trust I did do that kind of math at least. And now we want to get the second screen running. So, let's go into our second screen, which I think I can do like this. And so what this is doing, under the hood this is going to run the npx start, or npx serve, and I'm using this to escape npm, and passing an argument to the Nx that will run the second screen command if I'm remembering correctly. Yeah, Nx. So, now if I come out here and reload, we have this ability here. And, so, I need to actually, I might not need to do anything. I think John might have done this for us. Let me see. Apparently I'm logged in. So, let's see if I click on this. Is it entering anything? Refresh. It is. Okay, let me click this three times. Boom, boom, boom. All right. And then we're going to refresh. And now there are a bunch. Good. Jon just fixed this for us, it just worked. So, let's go and look at how that is functioning. So, that's under second screen. And we've got our app, and let's take a peek at how this works. So, inside here we haven't styled anything. If we get let's see, we got 45 minutes left. So, if we get this all the way running, maybe I'll get it and style this, but otherwise I'm going to get this deployed so you all can play with the sentiment and we can watch it happen in real time. And I'm realizing we should probably have some kind of a unique combination of, say, the slide would have an n ID. We'll make that a stretch goal. So, the first thing I need is the ability for the slide changing to update what the options are on the second screen. And after that we'll make sure people can only vote once so somebody can't set up a script and vote a thousand times and that kind of stuff. We can figure that out later. Right now what we've got is the Supabase auth. Let me clear the application cache so we can see the log in flow. I'm going to do all of it, I think. I can sign in, it's going to have me sign in to GitHub, and apparently I already authorized the app, so it doesn't make me hit the approval thing, but that makes me in, and now I'm logged in as me, so I'm using my own user name. If we look over here, this is my user ID, and this is Jon's, because he was doing the tests earlier. So, this is what we're getting as a unique ID. That way if I'm set up oh, that's a cool idea, Tony, to hook this back into the Twitch API and do an action like a stampede. Yeah, there's some fun stuff we could do. We could set triggers, where if the sentiment drops below a certain thing, it plays sad trombone and I'm forced to move on to the next topic, right. There's some really fun things that we could do to make this more interactive and stuff like that. But for now let's see if we can get this to run, which I think we can, and the way that I'm going to do that is how do I want to do it? Let's see, we got this part running, and that's adding things. Now we just need to get both of these running together. So, first and foremost, I think we can deploy it. So, let's get this running on Netlify. And the way that I want to deploy it is if we look into the deployment, I think, I think this will just work, because we're going to build. So, what happens when I do a build? I'm going to do npm run build is it called main talk? Main talk and we've got second screen. Let's build main talk. And it's doing a production build. And it apparently knows all the things that we need. So, it ran that, and it did it in Nx cloud, which is kind of cool, which means a lot of these resources are cached and stuff like that. Actually, we can see. Watch. Look how fast it goes the second time around. So, that's really nice, and that means everything got output to got output to dist/apps/main talk. That's great news, because what that means is I can then do one of these at least. No, here's how I'm going to do it. I'm going to do it like this. I'm going to the And hopefully it's in mine, it is. I'm going to create a new site. Add a site, import an existing project from GitHub. Can you tell I always use the CLI for this? So, let's get into our realtime talks. I have so many repos. Here we go. Then we're going to deploy our main branch, that's the one. Our base directory is set, and then our output directory, what we're actually going to use here is the one that we found. It was dist/apps/main chalk. So, dist/apps/main talk. So, a little bit of config here, but I'm feeling pretty okay with it, and I'm going to deploy. I probably should have named this. I'll name it now. So, we'll say realtime talks then if we go back to the deploys, I think this will already be done. Let me go close to done. And while we're waiting for that, I'm going to set up the other one actually. Set up the second screen, and the way we'll do that is go back out here, go to sites, add a new site, import existing, go to GitHub, do the auth flow, come out here, search for realtime. Go through my 600 repositories. Let's get realtime talks. And for this one, we're going to do second screen, and that means it's going to be in apps second screen. So, that is how we deploy multiple apps from the same Nx mono repo. I should click that. That's actually like a question we get a lot, how to do that. That little section of how we just did this. Let's go realtime talks second screen. Save that. And we go out to here. We've got the realtime talks main screen is deployed. So, here's one. I just want the main one. Here's our main talk. And then go back to the second screen. So this I think should all be working, because we're using public keys. Do what we want. Then here we want the second screen. Here it comes, completed, building, and live, I think. Let me get back to the top and click on the main app name here. Okay. So, chat. At this point, you should be able to actually vote on this, right. So, let's give it a try. I'm going to make this one way smaller. Stick it over here. And I'm going to take this one and stick it over here. And let's log in. No! I got to fix my path. So, that means that I need to go back to my GitHub. Is it this one or Supabase? I think it's Supabase. Do I have another? This one out here, I'm going to go to authentication. Settings. Site URL, and I need to update this to be our actual site URL here. Oh, it's going to be second screen. That's the one, okay. So, now that I have that. Use as an allow list, is it possible for me additional URLs. Do I need to set a redirect in here? Feeling like a made a mistake. Configuration settings. Do I need to fix this in the code itself? Where's my log in. Let's go into the second screen. Source, app. And when you log in, we're not providing anything, so theoretically speaking, I think it just needs to be that default. For the sake of this, I'm going to put this up here, and we will, if we need to, post 4200. I'm going to save. Going to come back out here. Come back here. Reload. Sign in. There we go. Okay. So, now I have gotten these back. Oh, no, they always increment. Did I spell something wrong? Value good. Oh, yeah, we hard coded. So, that's why that's happening. So, then what we need to do is figure out. Okay, so, major hurdle here is overcome, which is that if you all go to this realtime talks endpoint and log in, you can now affect this thing. Yeah, I do have strappy content. Let's go here. I will show you my favorite thing. If you come here and hit command k or hit the search box. We have a suite of content on Strapi. I don't know which uses next.js, if any of them. That's a good question, but do have Strapi content. Strapi is very cool. I would definitely recommend taking a look at it. Very configureable, fun to use, very flexible. Chat, are you voting? Taking my hands off the screen, off the screen. Yeah, yeah, look at it go. This is great. We're doing realtime interactivity. Let's go and fix this to where, actually, this will be a good test. Won't go higher than 100. Is it throwing errors? Yeah, yeah, this is great. Won't go higher than 100. At least the basic math guards that we did, after I broke them the first time, work now. So, next what we want to do is not run this as a hard coded value. So, instead, we want to figure out which button was clicked. And to be completely honest, I don't know if this works, because I haven't checked for that before. So, let's find out, right, let's see what happens if we do this. Because what we could do is we could do like a create vote and then pass in a value of good or bad and kind of set these to be like on clicks. But I kind of like the idea of doing it on submit, but let's find out the form data. We're going to say data and get a new form data, event target, which is the submitted form. And then I want to why don't you like oh. FormData, then console.log of our form data. And I want to see if the button name comes through as part of our FormData. So, let's go back out here and I'm going to npm start second screen. How are we doing on time? 35 minutes. We're making a lot more progress this time. I guess it has something to do with me not just getting into the CSS. Okay, let's try this. Here we go. Now we got our form data. And that is prototype form data, entries, can I see I'm going to have to get values or something, right. Equals FormData.entries. ToArray. That's not going to work. Why don't you like this? Entries does not exist. Yes, it does. Form data, entries. Name is entries. Do it get all and see what happens. Also exists. That's the argument. Get all name. Boo. Let's see if I name this. If somebody clicks it, let's go with good. If that ain't programming, what is? Let's try again. Good, bad, array 0. Both of these come back empty. So, that's not going to do what I want. So, I think what I need to do instead is a kind of let's do this. We're going to function create good vote. And that will just do an event. One of these. Do one of these. Prevent default. And then inside of it we're going to we want to create vote good. Then we're going to change this to be value, to be a string, and then I don't need to be any of this anymore. And instead I can just set the value. Just going to clean this up a bit. Do all of those, do all of these. Now we've got the good vote, and let's create a bad vote. I'm going to do it anyways, just in case we want to wait at that. And then we'll get rid of our onSubmit, and instead we will do an onClick. And it's going to be create good vote. Promise void not able to type oh, I need to do one of these. Okay. I need to do another one here that will be our bad vote. Now, theoretically speaking, this will do what we want. So, let's see. That should have created a bad vote. So, let's go to our data sentiment. And that's a bad at 24. Maybe that's not working. Data, data. Bad. 6/23 at what time? 17:29:59. Now I'm paginated is why. So, bad, bad, at 17:29:59. So, that's working. Let's try good. Good, refresh. Here's our good at 17:30:23, 17:30:23 should be what we see here. Okay. So, now we are actually creating our data.

I'm going to just skip the console logging to make less noise, and we're going to do one of these. We could check for errors. Again, we're prototyping, trying to learn. We're not necessarily doing full blown error management here. But let's do a git add all. And now we've got a git commit, and we're going to say what do we even change? Hold on, let's go to the diff. We got rid of some console logs. Okay. Let me actually unstage this. And this one we'll just say refactor, remove console logs, right, doesn't actually change the behavior of the app. This one, however, we did a refactor, or we'll say a feature. Get folks working without hard coded value. You like to stage all other changes and commit them directly, yes, I would. Great. So now I can push, and what should happen is if I go back to my deploys, I'm going to go to here, and we should see both of these building. Look at them go! Okay. So, this should clean up our stuff. And we could do things like ignore directories, where we would kind of short circuit the build if only one of them had changed. I'm not going to do that, mainly because I don't that will take enough research on my part that I don't remember exactly what it is. Pretty quick thing to do, but a thing you've got to look up, and that would burn through the rest of our time. So, instead, what I'd like to do is validate this is working the way that we expect by let's restart here. I think that should be both of them. Builds, done and done. So, reloading here. Good, look at everybody going. Everybody go good, so we can see it go up. Now everybody is really mad about sandwiches. There we go. Everyone is going good. Okay, everybody go bad. And, okay. Now we've got sentiment is working. Look at that, broken ranges work. That would attempt to show what was happening. Wasn't quite doing what we were after. Look at it go! Yeah, all right, great. So, now we have the ability to do interactive stuff. The participants are now co authoring the experience, right, and we can make some of this stuff more fun. This is just one application, right, one way we could use this is what we're doing here, sentiment. I put up a controversial statement, and people are either in favor of that or not. Is a hot dog a sandwich, you can vote yes or no. Live polling is kind of a fun way to do this sort of thing. Another way we could do this is we could do something like an interactive element on the screen. I'm going to be telling my presentation, and I'm going to put something up on screen, and there will be a call and response. If you want to see this, you know, see this dance, everybody who hits the button on the second screen is going to advance the animated GIF by one frame. If everybody starts doing it, you get the dance. There's some fun ways that you could make this playful, you could make the presentation something that you collaborate on. I think that's really, really fun. Did the build wipe the database, it did not. That's one of the reasons why what I would probably want to do I guess you could kind of decide how you want to do this. One way you could do this is you could just periodically wipe the database, so that you don't have tons and tons and tons of rows. Another way you could do it is create a new instance for every time you gave the talk. And then you would have a, you know, a set like the presentation that you gave at this event on this date, this is what the audience created together. And that would give you some really interesting things, because if you were to do more interactive than just live polling, you would actually be able to do something like co creating. Everybody could, say, pick everybody gets to pick one word, but you pick those words in sequence, and you would let the audience basically build out a sentence from a kind of a mad lib. You know, then you have a really fun thing, where you've got an audience generated mad lib. Of course, you have to assume people are going to be jerks and maybe give them a dictionary to use, and they'd choose a word instead of freeform put in a word. But you could create one of a kind presentations. It's getting into the idea of improv theater, where instead of me standing in front of you and reciting a talk that I have prepared and rehearsed, I am giving a set of parameters for a discussion, and then there's input that guides that discussion. What if we use it as a choose your own adventure. Everybody has 15 seconds to vote, and whichever one of these pathways gets the most votes is what we're going to talk about today. And every slide could end in, you know, I want to hear more about the implementation, or I want to hear more about the use case. And then based on the votes, you would go one way or the other. That could be a really fun way to create these one of a kind experiences that you could give multiple times. Like the format of improv enables you to do an improv show every night, but that show is different every time you see it. And that to me is really, really fun and opens up some doors for collaboration with the audience that are unique. I've never I mean, I can't imagine nobody's ever done this before, but I personally haven't seen it. At least not in our community. And, so, I would be really excited to see how different people could use technology like this to mess around with these things. But, yeah, I think this could be really, really, really fun. Should we try to do something else? I'm thinking what would my next steps be if I was going to try to productionize this. I think my next steps would be how do we tie the slide to the votes, so we would need some kind of an ID that would so, this would be slide one, and then these would be the questions for slide one, so you'd need some kind of a tie there. And then we would need a uniqueness, so that each person maybe that's a setting, but in general, I imagine I would want, you know, each person gets to do one vote. If it was something like you push a button and it makes something move on the screen, then cool, whatever, unlimited uses. Tap that button and make the person dance, or make the cartoon bounce, or the things drop. That could be really fun. But I think in general you'd probably want a one person, one vote kind of thing to make it more just avoid that spamming problem, which the spamming problem is fun in certain cases, but in this if we were going for sentiment, one person shouldn't be able to dictate. Oh, we all hate this, because I tapped this button a thousand times. So, yeah, this could be really fun. Yeah, Ben's talking about doing it as an on demand voting screen. That could be extremely cool. It's like a game show where you poll the audience. Absolutely. Extremely cool. You could do things like, yeah, what we're seeing right now, everybody is playing with the grow command. Every time somebody runs grow, the beard on this animated Jason that Cassidy made, actually made on stream. I should find that. Let's get Cassidy up here. We did a realtime Twitch. This is the one. Here's where we actually built this growing thing. Yeah, the beard long enough it goes rainbow. This type of stuff is so much fun. There's so many cool things you can do with this, that it really opens a lot of doors for pretty boundless creativity. You can make anything that you want to be possible possible, because it's just a website. You can build anything you want on it. The only difference is, instead of clicking a button to trigger the thing, you are letting someone click a button on a different screen to trigger the thing. That's to me what makes this so dang fun. I can show you a QR code. Hey, this presentation is interactive, point your phone at this QR code, and it's going to take you to a website where you can interact with the presentation as it happens. Those to me are really, really fun things that give you a lot of opportunity to make things more engaging and make the things that you build more fun than they would be if it was just you on your own. So, really, really excited about that kind of thing. Wrap around my blender smash burger. Yeah. This is really, really fun. Yeah, shared audio player. We sort of have this. I kind of want to play with it more, but like a soundboard for the stream, where, you know, right now people can play sound effects that are clips from the show. There are some really fun things you can do with a soundboard. There's a game called Bwamp. If you have not seen it, it has this fun, like you can go and make noise (clapping). To me, this is really, really fun, where we have the ability to just kind of add this noise. Does this even play? This isn't coming through to y'all. I have to figure out how to get desktop audio back in. The fun thing is we have, you know, we can give a soundboard and whenever I say something inspirational, everybody does "oh!". And if I say something people don't like, they can play the boo. You can do sad trombones, things like that. This is really, really fun, I think. So, yeah, do it as dungeons and dragons. That also is really fun. There's endless creativity available here. I think that's maybe the part that I'm most excited about. Again, the goal of this stuff is not to be on stage as, like, I don't ever want to be somebody standing up I have knowledge and you're here to access it, and, you know, you have nothing to offer me. I think instead it should be collaborative. I know some stuff, you know some stuff. I can point us in the direction, but then together, like today, you all helped me solve my useEffect problem with the closures. A lot of ideas on this actually every idea on this stream is something collaborative. The overlays are almost always built off an in joke with the chat, pull requests, sound effects people clipped, you know, so much of this stream is a co authored creation. This is a community creation. And I get credit for it, because my face is on it, but really if we think about what's happening, I am here as a facilitator for a group of people that do cool things. The idea of trying to make that built into the experience through the chat interactions through things like this, where we've got presentation that's more interactive, these are the sorts of things that really open up the door for community creation and collaborative creation. That's really the goal and the crux of what we're getting after. Yeah, the improv viewpoint, not everybody loves improv, not everybody loves doing improv. I guess I should also say I mean no shade toward people who want to practice their talks, who wants to be very deliberate about what they are presenting. There's so much value in that. This is all my perspective based on what I find fun, what I find valuable, and, you know, what I would do with my time, given the choice to do whatever I want. And really, where I land personally is I have more fun doing collaborative things. I find it very stressful to have a script that I have to stick to, because if I want to go off on a tangent, I don't want that to mean that I have to go over time. Or something like that. I love going into tangents, dive into a rabbit hole, somebody comes up with an idea, I can spin off and think about that for a while. That to me is so much fun. But I also know that what I do with going live every week without a plan and no script, and no prep, that is a lot of people's worst nightmare. So, I want to make sure that I'm not making any value judgments here. What I'm getting at is this idea that there are a lot of ways to create. There are a lot of ways to present and to share knowledge. I personally am a huge fan of collaborative ways of creating and sharing knowledge. So, I like this idea, because it tickles my particular set of fancies around how people should share and collaborate that's fun for me. That's all it is. I want to play with ideas in ways we can co create, co think. I guess that's what we're after, right. Bobby Tables puts this a good way, opens up new options, doesn't limit other options. There are a million ways that you can do things. And, hopefully, it makes it a million and one or a million and two. So, I think there's not really much else I'm going to be able to do in the next 15 minutes, so let's call this one done. And what I'm going to do is I'm first and foremost going to do another shout out to our captioning. We've had Ashly here today from White Coat Captioning. Thank you very much. And that is made possible through the support of our sponsors, Netlify, Nx, Backlight, and starting next week, New Relic. Thank you all very much for hanging out and for sponsoring the show. We've got a lot of good things coming up on the schedule. I am extremely excited. Next week we're bringing back Sunil Pai and bringing back Edge computing. If you're not sure what it means or why it would benefit you, come to this. Sunil is one of the people I like the most as a thinker on what the future of the web could be. It's always a blast to talk to him. I have no idea if we'll even get to writing code. We might honestly talk about what's possible, the future. Really, really excited to talk to Sunil. We are going to have Shem from the Wilco team. This is going to be really fun, because one of the things that happens is when you're early in your career, you have a lot of different exercises and intro things and beginner things, and you're going to play and try. And then you get into a job, get busy in the job, and you don't necessarily want to do a bunch of work outside of work, so you kind of level up based on what your job provides for you. It's one code base, one approach, one architecture. What Wilco does is gives you the ability to dive into different architectures and real world projects to get a feel for what it might feel like to work in different ways and that will help you stretch your brain as a developer. Like a flight simulator they'll call it. I think that's cool. John Lindquist, who's been on the show in the past, the last time he was on the show, we were working on script kit, but it wasn't called that yet. We were working on a collection of JavaScript that does local workflow automation and since then it's matured a ton and there's a lot of capability and promise here. So, this is going to be like revisiting developer workflow automation that you can program, things we can build custom to improve the way that we work. We're going to get into automated accessibility testing with Storybook. Storybook is a cool way to work on UIs and flag you wrote code that's not accessible. Don't try shipping that. Fix it right now, which helps avoid tech debt. Never create tech debt in the first place, it's wonderful. React, might be React, might be general JavaScript now, but Matt Perry has been on the show before talking about that. We're going to build really, really cool things using dev tools that make it easier to debug, export, and manage that stuff. Sid is coming on to talk about Rust in the context of a JavaScript developer. We talked about this before with Chris, with Prince Wilson, and now Sid is also working on Rust for JS devs. I find it very interesting. I wish I had more time to learn whole new programming languages, but Sid has solutions for us. Finally, Will Johnson to talk about Auth0 action. Serverless, low code and no code solutions. A lot of good things coming up, lot of fun. There's more on here I haven't had a chance to put up yet. So, please make sure you go add the show on Google Calendar, follow on Twitch, follow on YouTube. I think we're pretty dang close to 30,000 subscribers on YouTube, which I find very not me. What is this? Let's look at me, Learn With Jason. So many people learn with. I can't spell, and it's making noise you can't hear. I probably feel like I'm okay, 28,000 subscribers. We're moving along, whole lot of stuff. Do I just throw the whole show unedited on YouTube? Yes. I mean, not completely unedited. We cut out the silent intro and the dead space at the end. Yeah, it's just the show, if you want to see 90 minutes of somebody paired programming, that's how it works. We've got so much good stuff on here. We're almost at 300 episodes. And, you know, here's to 300 more. There's also stuff that's not Learn With Jason. I did a series with Free Code Camp, where we did how to get into tech, I have a bunch of my conference talks up here. So, if you want to see more stuff, please subscribe on here, and you'll get notified of the new ones. I think you have to ring the bell, right, that's how you get them. That's enough about me, y'all. Let's call this one a win. I'm going to find somebody to raid. Thank you all so much for hanging out. It looks like anybody have a suggestion on who we should raid? Who's live right now? Let's go look. Browse. I'm going to click this browse button. Let's go to let's see, who's live. We'll look at JavaScript. Who's live doing JavaScript today? Primeagen. Doesn't need help from us, plenty of people watching. Who should we say hi to? Drop ideas in the chat if you've got them. Martine Dowden, where is Martine? Let me copy/paste this. Let's do it. Let's go raid Martine. Y'all, stay tuned, we're going to raid Martine. We'll see you all next time. Thanks, y'all.

Closed captioning and more are made possible by our sponsors: