Conf42 JavaScript 2022 - Online

Remix party, you’re invited!

Video size:

Abstract

Remix is a great framework to build robust, progressively enhanced and interactive web apps!

During Covid we all missed the Parties.... therefore Dave will create his own party on stage. He will take you on a fun journey on how he created a multi-user and real-time progressive web app. But be aware, there is a guest list and not every solution is invited to join the party!

Dave will show you how the Remix friend group will keep your party rocking:

  • where the state of your data is on the server where it belongs. (load some data and take action to get the party started).
  • where this multi-user web app is not dependent on complex client-side javascript (so even your drunk friend will understand it)
  • where the client-side is less error-prone (no party fouls wanted)
  • where the components are just plain stupid (no good story starts with a glass of milk)
  • where your application becomes simple and easy to understand (you know, for that friend)

Dave will tell you about the challenges he encountered building this web app and how it was solved charmingly by using Remix. He will show you how Remix can be used for web apps with a lot of interactivity not just for plain websites with an occasional form.

Getting FOMO? Make sure to sign up for the party and don’t miss out!

Summary

  • Jamaica make a real time feedback into the behavior of your distributed systems. observing changes, exceptions, errors in real time allows youre to not only experiment with confidence but respond instantly to get things working again. We'll cover everything in the next 35 minutes and have a look together at web fundamentals.
  • remix is a full stack web framework, emphasis on the web part based on web fundamentals. It aims to help you leverage the browser, leverage the web as a platform instead of working against it. People are sometimes not embracing the platform we are building for which is the web.
  • What we use is file based routing. We have in remix an app folder, where we have a routes folder. Finally, we have this root TSX, which is basically the wrapper around the entire application remix, or rather react router nowadays. You can find all of that in the basic readme of remix.
  • remix is a tool that helps you handle forms on the web. Instead of just a regular HTML five form, it does full requests to handle your logic. What remix is really focused on is also your error handling. It can enhance the user experience.
  • Once you join or created a session where you can actually run the application that looks a bit like this. We're going to do some starts server side rendering and that's important. Then we have the core of our interactivity for the user, which is here.
  • Instead of an action you have something called a loader. This is a function that whenever somebody fits a URL, it's going to execute this function where we basically get our data. So we can get the latest state from the server basically of the session and display that. We can also add some interactivity now with CSS. It's not about your user not having client side Javascript it's about reducing the complexity of your app.
  • Remix offers a couple of helper functions to get you started. You can use server sessions to save data for you. We do everything on the server where it's safe and on the client is as dumb as we can keep it. We can even make this more secure.
  • Modern Ux doesn't need clients at Javascript to have real time updates. Instead it uses a use superbase subscription to subscribe on any change that you want to. That is the entire layer of adding real time to this application.

Transcript

This transcript was autogenerated. To make changes, submit a PR.
Jamaica make a real time feedback into the behavior of your distributed systems and observing changes, exceptions, errors in real time allows youre to not only experiment with confidence but respond instantly to get things working again. Close hi everybody, I'm dave bitter. I'm a developer advocate working at IO in the Netherlands and today I want to have a look with you at Remix, the new full stack web framework. So what does remix do? How does it work? Why should you use it? We're going to cover everything in the next 35 minutes and have a look together at web fundamentals, which is always a very good thing to do between developers. So let's get started. So remix is a full stack web framework, emphasis on the web part based on web fundamentals. So it will have both client and server side and it's going to try to use web fundamentals to smartly talk between the two of them and to help you really leverage the browser, leverage the web as a platform instead of working against it. But Remix is also a framework to build over encountered websites. So this is what somebody tweeted me. I anonymized their data here after I got so excited about Remix and I shared something on Twitter. So this is pretty standard. When you post something on Twitter you will get these comments. But it was an interesting discussion and a perfect way to add an intro to my entire talk. So let's call him a guy on the Internet said well, remix is a framework to build over engineered websites and you appear to not know the difference between a website, a place on the Internet with a URL and an app, a standalone program on a mobile device. And I mean, I don't blame him. There are two different platforms, but are they so different nowadays? Especially since he tweeted this from the Twitter web app? And the lines between these websites and applications got so blurry over time that it's hard to sometimes spot the difference and which pattern should you use when? So naturally I reacted and told them, well, basically remix is actually really good against over engineering because it goes back to web fundamentals, right? It's leveraging what the browser already offers for you and you can then use that to build your website for the platform you're actually developing on the web. So basically it's a major shift in how we think about building for the web. So first we cover all our bases with web fundamentals, then we use progressive enhancement to build layer by layer and in the end have a full blown application where every layer of progressive enhancement is supported correctly, where we have basically the good old of the web but then up to par with modern Ux. Of course this Twitter beef continued, and I'm still talking about web apps, there's no such things. Website have a URL, apps are standalone. Well we covered this of course with the Twitter web app example, but he says you can try meshing them together and that will inevitably fill being good at one or the other. And here I sort of kind of agree, right. If you really try to get all these native patterns on the web, you might have to do some weird stuff and it doesn't work well. But what I noticed, what I've been doing, and people around me is sometimes really not embracing the platform we are building for which is the web, which is incredibly powerful and often overlooked. And naturally you never want to lose an Internet argument. So yeah, for instance, we have progressive web apps, right, where we can then have an app, but again, this is an enhancement. We have a basic layer, we build our website out and then we can always enhance further. And that's something really nice that the web offers, of course. But tell me you're frustrated by all these frameworks without telling me you're frustrated, right? And I fouls feel the pain. It's every time a new framework pops up and I wanted to give this talk because I really believe in remix as a framework, at least what they stand for, to basically offer you the web fundamentals and then tools to be up to par with modern Ux. Because sometimes it feels a bit like this, right? You have that friend who says well you should totally come to the party, it's going to be great, should see the lineup and this, and this person is going to be there, it's all good vibes. And you start thinking like, oh well maybe I need to really check this out. So this is what new frameworks often look like or feel like rather. And you get fomo, right? It's like, oh, am I still relevant if I don't pick up this framework? And I think that's an inherent thing about all these frameworks, is if you keep on reinventing the wheel, you have to keep on learning all these different new patterns. While learning a framework that uses web fundamentals will give you a solid base to work on the web in general. And hopefully more frameworks will pick up on this because usually when you use a framework, you run into the same issues that you had the last time you used a new framework. So I have an arbitrary amount of examples here, like complex state and it's like sure your readme works perfectly fine, but I got really complex state and I need to keep my data up to date and there are non standards being used. And this to me is then where remix comes in by using the web standards and using that to build around. So web fundamentals, enhance them with modern ux. This is a logo I think we all know, especially during the pandemic. We spent a lot of time on Microsoft Teams and it basically replaced every normal communication that we had with each other, but also our processes in development. So if you work in an agile environment, you have probably worked with Microsoft Teams to then do scrum sessions. Well, those are usually pretty interactive, which is nice about those sessions. But what we also needed to do was, for instance, give an effort to new tasks, right? There's a new task, it's been refined and everything. And now we say, okay, well I'm going to give it one, three, five, whatever system you use, we give it so much points and then we use that for our sprint planning. Well, how we did it now, because we were all remote, we sort of threw our hands up in the air, which everything above ten points is really awkward to do, but spotty connections, people didn't have it directly in view, so it became all the real quick, basically. So I was looking at, okay, can we just have an online application where we can do this? Turns out there are a lot of applications that allow you to do scrum poker sessions online. But hey, I'm a developer, I'll build it myself. Right. And this is a perfect thing to really put remix to the test because. Yeah, I get it. You go to the remix page, there's a readme there, it's a super basic dashboard, which it's amazing at. But can we really put it to the test and make this basically real time multi user application, but still on web fundamentals, still with progressive enhancement and covering all our bases. Is that possible? Let's have a look. So to build something like this, we have a couple of features that we need to support. Firstly, you need to be able to create and join a session. So you need to have some forms where we can start a new session where we can join one, give your username, et cetera. Well, naturally you need to cast a vote or an effort, depending on how you call it in your team saying, I think this story is worth five points or eight or whatever. Then when everybody voted, you want to toggle the visibility so everybody can view what everybody voted and at the end the admin can clear it around and restart, put the visibility back to hidden and you do the process again. So quite a simple app, basically four features, but can be quite complex to build in the end, if youre going to build that for the web. So let's have a look at how we can use web fundamentals for this. Let's get the party started. So the lineup or the tech stack for this is well naturally remix. That's the framework of choice that we're going to look at today. Then I needed to persist some data, right, youre want to maybe store the session state, maybe some users. I use superbase for that, which is basically if you know, Firebase, I think they market themselves as the firebase alternative. Do it what you will, but at least I like it for these type of applications. Short demo, small applications. Finally, we need to add some styling, make the demo look a bit nicer. For instance, something like tailwind can help you quickly style your pages. So that's what I used. I tried to remove as much of this out of the code examples as I could and simplify the code examples. But just so you know, this is the entire text deck. So how does that visually look if we design it? Well, basically we have this index page where we can create a new session by giving our name, or we can join an existing session where we pass it, the session id that we want to join and our name there. So basically two forms, then we have a dynamic session page. So for instance, session whatever id we put in there. And this already becomes quite more complex, right. We need to show some data, we need to add some interactivity and so on and so on. So these two pages will be the base of our entire application. And let's see how we can build that. So if youre ever worked with something like next JS, I think it's now also in new react router. This will be familiar, but basically what we use is file based routing where we have in remix an app folder, where we have a routes folder. And when I put an index TSX file in there was long as I export some JSX, I can go to index HTML and see that page. Similarly, if we make a folder called session with a file in there, it will be session whatever file you put in there. So you notice that I have this little dollar sign and that is basically remix way of saying, okay, this is a dynamic part of the URL, this is the session id. So whatever somebody puts in there, match on that and load this file and there we can handle our logic. Finally, we have this root TSX, which is basically the wrapper around the entire application remix, or rather react router nowadays because they moved it over can do really cool things with its routing, with nested subroute, with outlets. Really amazing. You can find all of that in the basic readme of remix. So please head over there, but be sure to check it out. So let's dive a bit deeper. The create or join session page as I call it here. So we have those two forms basically do similar things, but they both need to be handled. Okay, so how did we in the past handle a form on the web? Well, we did something like this. We said well we have a form with a label and input and a button that submits. So what you see here is that I actually import something from remix called form. And what's good to know is that underwater this will just render a native HTML form element in your page. So that's great. And we'll get to see why we actually use this instead of just the native form element in a bit. And as you notice here, I don't have any prevent default, no event listeners, I'm actually just going to say method is post submit this thing. And in the past this was not ideal because these frameworks, especially these front end frameworks, when you posted it, well it had nothing to post to, right? If you just had a create react app and youre post, there's no server running there, there's nothing that can handle my post request. So I had to have an on submit event on the form, prevent the default, then get the data, get it from the state and add all this logic to my application which by the way just works when youre have client side Javascript, which is not ideal because the web is really good at submitting forms. So let's just submit it. So where do we then handle that? Well, in that same file. And note that these are simplified code examples. So I've hidden the JSX here that we just saw. In the same file I export something which is called an action and this is basically a server side function. And this server side function needs to be named action, like exactly action and be exported. So remix will pick it up. And what it does is whenever you post something from the front end and do an actual post request, this function on the server will be ran. So as you can see here, I dave a request that's coming in and in that request there's just form data. Well we get the form data, we get the username and this is usually when I show this where older developers say hey oh, that's how I used to do it. Exactly. And it's still perfectly fine. So here we then say, okay, I will create a new session id. I use a nice package called human readable ids because it's a bit nicer to read those than these gigantic randomly generated ones. But then I call something called superbase client. And what's just important for you to know is that superbase client is just an SDK by superbase that allows you to talk with your database. So here we say okay, go to sessions, insert a new session with this session id, and then something cool happens. So what we do is say, okay, we need to return something from this function, always. So what we could return is a redirect which we import from remix. And that does exactly what you think, it just redirects the page to whatever you want. So in our case, that might be nice to redirect to sessionnewsessionid, but what the remix is really focused on is also your error handling, which in the readme of remix there's a lot of information there. But what I use, for instance here is say okay, well, if this superbase client returns me an error, I don't want to redirect, I want to show what went wrong. So how do I do that? Well, I just return an object here to be used. So remix can handle this. But how do I then actually get that object with the error data? Well, I use something of remix called the use action data. And this is a hook that whenever your action is ran and it returns something, this will be updated if you have clientside like javascript. So this is where that form package comes in. So instead of just a regular, which will still work, by the way, a regular HTML five form, when you submit it, it does a full request to the back end, it's going to handle your logic, you're going to return error, it's going to do a full rerender of the page and you actually see your browser basically refresh the page. But when you have client side javascript, it can do all of this on the clientside, right? It can enhance the user experience. It doesn't need to fully do a reload and be time consuming. No, it can just do it on the clientside for you. And in that case this action data will also be filled and the render method will run again and we can display them. Do whatever you find logical in this case. But this is a real core concept of how remix works, which is great because I don't know a lot of frameworks that handle form so well. So if you know regular old posts, it's basically that, and underwater remix will enhance the user experience for you. So that's great. So progressively enhance with JavaScript. And I will say that a lot during this talk and I can already hear you saying yeah, okay, but all my users do have JavaScript and the point is not about the user not having JavaScript. And I like to refer to this tweet from 2012 from Jake Archibald basically saying we don't have non JavaScript users. No, all your users are non JavaScript users while they're loading your javascript. That's the first example. So if youre resources don't load or aren't loaded yet, if your application doesn't work, what does that say for your user experience? Right, and we shouldn't so heavily rely on having this client side JavaScript. So this is while it's loading. But even if it's loaded, I'm sorry, even if it's loaded, you're still not but of the woods yet. So I gave this presentation to a few colleagues and I was talking with one of my colleagues and he said well Dave, I also built an app with remix like two months ago, like oh cool, let me see. Then we visited the page and he hadn't touched it in two months and the page was just blank. Well, remixes. Of course you can still do whatever you want, you can still introduce a lot of client side JavaScript, but what I told him is like well maybe just turn off your javascript for a second. And suddenly his entire application worked again, because it just used the server side actions, it just used the server side routes and used the web. And that's so powerful that even if your clientside Javascript, which might be error prone, even if that fouls, you still have hopefully a working application. I mean you can always run into the issue of having the full white page, sure, but at least if you put enough on the back end instead of the front end, you can make your app a bit more resilient. Okay, cool. So we had that first form, that was basically it, that's how you handle forms. And then of course we have a second form. So I already told you that whenever you submit and you have an action in that same file or in that same route, rather the action will pick it up. But what if you have two files, two forms, sorry, do you then have two actions? Well no you don't. So we need to use an alt trick that some of youre might remember, which is just a hidden input. So for instance in this hidden input we can say well the form type is join session. And for the other one we say the form type is create a session. And then what we can do is when this information comes in on the action, we can say, okay, well get that form type from the form data. And then, well, I made a switch here saying, oh, take the form time, create session, you should do this, this, and this. Join session, you should do this, this, and this. So that's an easy trick how we can basically reuse the same action but for different purposes on that route, for different forms on that route. And that's it. This is how simple you can make it. Okay, so it can handle basic forms. It's really nice. But of course we need way more if we want to create this real time interactive web application. So let's have a look at that dynamic page. Once you join or created a session where you can actually run the application that looks a bit like this. And there are a couple of parts here. So first we have this top bar, and in this top bar we basically want to load some data and show whether somebody has voted or not. If the vote visibility is toggled, we might want to show the actual vote that they did, but otherwise just voted, not voted. Then we have the core of our interactivity for the user, which is here. So note that this is the view of an admin youre can see that by the show votes and the clear votes button at the bottom, or rather toggles maybe that's just shown for the actual admin. The rest just sees that grid of choices. And then in the end we have this little bit where we say copy invite because of course somebody starts a session and then you want to share that with your team, maybe in a team's chat and you want to send a link. So first let's have a look at that so we can finish up the previous page we looked at. So of course you can just copy something from the URL. It's maybe not as nice as a user experience. So what I did is I said, okay, I'm going to have this little components which has a button called copy invite. And what does this button do? Well, basically whatever your domain is on the index page, it's going to pass a query parameter saying join session id. Splendid Al 40 in this case. So when you hit this button, if you are on a mobile device, well there's something web standard which is the native share API. So I'm going to check is that available? Use that and you get slack and teams and all those chat tools so we can really leverage whatever phone they use. If that's not supported. Well then let's have a look whether we have clientside Javascript because maybe we can then put it on the clipboard so somebody can paste it and otherwise this can just be the entire URL that we see on the left and somebody can manually copy that. Okay, so when somebody goes back to that index page with the forms, we need to handle basically this query param. So how do we do that? Well, we're going to do some starts server side rendering and that's important. It's on the server side for a better user experience. So whenever somebody visits this page with the search Param, we can basically get it out of there using the use search params. And why is this important? Because I understand that you can add a use effect and basically do this manually. See okay, what are the search parameters? The downside is the use effect is clientside and what you get then is that it's going to render this page. Then you're going to check whatever you need to do and then you're going to maybe update the layout so you get this flash of content, which is annoying. We can already do this on the server. So this hook first runs when this page is rendered on the server. And there we can see okay, is there a join session id param or not? Well if it is there, if you have to join session, you might not want to show the create a session form, right? Doesn't make sense. Somebody's intent there is to join a session, not create one. We'll hide it. Secondly, what we can do is say in the join existing session youre might already set the default value there for this input to be that value. So the user of course doesn't have to type it in. What we can also then do is say maybe I want to auto focus on the name input there so the page loads, you will just see the form and it will look a bit like this. Yeah, so a bit smarter way of rendering but also enhancing the user experience. Again, to for instance auto fouls on this name input, you type your name, you hit enter, which by the way will work because we use native form submits and all the logic is executed to basically redirect you to the page of successful. Cool. So we talked a lot about posting data and handling that in the back end and a bit of routing. But of course a big part of your application is actually displaying data that's probably stored in the database somewhere. So like this bar on top. So let's have a look at how you do that. Unsurprisingly, it looks a lot like that action that we looked at. So instead of an action you have something called a loader. And if youre worked with next JS, this is probably fairly familiar to you because this is sort of like get surropsite props, right? It's a function that whenever somebody fits a URL, it's first going to go to the server, it's going to execute this function where we basically get our data. So in our case here in the example we get the current session. If the session doesn't exist, maybe we redirect, we can handle this however we want, but after that we're going to get everybody's vote for this session and then return that data. So how do we now access it with the use loader data instead of use action data? So this is the pattern that remix keeps on following. So the first time it's going to render on the server, this loader data will be filled with the votes and the session data. You do render your HTML or JSX accordingly. And then on the clientside, if you don't have any use effects or client side Javascript that needs to be executed, this is it. Cool. So we can get the latest state from the server basically of the session and display that. So we need to also add some interactivity now. So at the start nobody has voted, but we do wanted to do that. And this is usually where we tend to reach for client side Javascript. We see a bunch of buttons, we see a grid of votes, and it's like oh okay, we'll need state and somebody's active vote, and I need to keep everything in sync and whatnot. But even worse, once we have this clientside Javascript, we need an API to post this to. Then that API needs to be hosted somewhere. You might run into stuff with cores, you need API keys, it gets way more complex, while all I want to do is just send some data over. So let's have a dive into that, into these interactive bits, or rather these microforms as I like to call them. So let's look at the voting first. Right here we have this grid and let's see how we can make this work without client side Javascript. And what's good to remember is again, it's not about your user not having client side JavaScript, it's about reducing the complexity of your app. First of all by having way less client side Javascript that needs to mimic browser behavior, have less error prone logic because of that, and really get this solid base in there and then enhance it. After that we can have a look at the show votes toggle and the clear votes toggle. Cool. So looking at that grid, and I called it a grid on purpose because I didn't want to call it a radio button group right out of the way. But isn't that what it is? So isn't it basically here a field set where we have a bunch of radio inputs that have the Fibonacci sequence here where you can vote? And why I'm saying this is because the radio buttons do exactly what we wanted it to do. You can always just have one active vote, and when you click a new one, the old one should go back to not being checked and the new one should be. So this works really well, it covers everything that we need. So let's just build it like that then with CSS. And actually you could basically hide the little radio button, make the nice square and have it light up. That's all on the CSS part, which a lot of people are familiar with on how to do that, but underwater it's just this cool. So one drawback of going to forms for this is whenever I hit one of the radio buttons, nothing happens because we still need to submit it. So I need to have a submit button at the bottom and then I can post it without any clients or Javascript. But that's not very nice for my user experience. That's not what we want. So let's have a look at how we can do that. We can use something that's called the use submit, and this is something by remix where you can basically say okay, I want youre to submit this form now, and I want to submit to the normal action that you would otherwise. So here I add an on change handler to this little form where I say when something changes, just submit it to the back end or to the action rather. And note that we don't prevent default because we wanted the default, we just want to submit this thing. Cool. But now I'm still left with this tiny button which says submit at the bottom, which is not needed if you have client side JavaScript. But how am I going to hide it or show it? Because you basically don't have, for instance client side JavaScript to check whether you have client side JavaScript and you don't want flickering of your UI. So don't be scared, we're going to have a look at some CSS. You can do this in a million ways and probably better ways than I have it here but just to showcase you can do something like say okay, I'm going to say set a data attribute on the body saying there's no Javascript, and then whenever there is clientside Javascript it's basically going to update the value to true. So then what we can do in our CSS and we can create some helper classes like no JavaScript show or no JavaScript hide. And based on that we can say well if that attribute is true or false, we're going to show or hide anything that has this class name. And I do some trick here with animations and why do I do that? Well of course we want to give JavaScript a second to load. So whether you want to hide certain UI parts, you want to give that check or basically the clientside said Javascript bundle some time to actually load. So in this case I just gave it 500 milliseconds and after that these things will come into effect. So it's a small little trick where we now have some reusable CSS classes, which is nice to use for youre team to show or hide specific content for both use cases. So now we show manual submit button for the non JavaScript UI using the CSS. Cool. So these two action buttons at the bottom. Well how are those microforms? Well, let's do the same thing as first we'll just create two forms which have two inputs which are basically hidden and say I want to toggle the effort or I want to clear the effort. This is the only way you can have these buttons in our forms to have these interactive bits without clients or JavaScript because the only interactivity that you can actually have is posting this to the back end. And what we do is just have these two forms here and then again use that same trick in that action we're going to check. Okay, what is the form type? When it's toggle effort you might want to do something in the database. And with clear effort it's the same and that's it. I mean it's not much harder than having an event listener on a button and then having to post to an API. No, it's just a form that now natively submits a new handle. Works perfectly fine with or without JavaScript. Great, so let's Dave a look like every party, you also Dave a bouncer in front of it saying can you show me some id? Right, we need to see who the person is that is actually casting a vote so they can just update their own. But you also want to know who the admin is so they can toggle the visibility. So when I was quickly building this, I just had a query parameter with the username. But of course you can fill in somebody else's username and then basically cast a vote for them or become admin, which is not great. I didn't want my user to have to do a full sign up because now I just want to do some scrum poker and who is Dave and why does he want my data and I don't actually need it. A username is nice to show who is who, but you can fill in whatever you want. And besides that I just need some basic information like a unique id. So what do we Dave on the web that is accessible on the server where we have our mutation logic and our data loading logic, and how can we make it only known basically to you as a user and not to anyone else? We can use server sessions, which are really cool, which is nothing new. Remix offers a couple of helper functions to get you started. In essence, if you've never worked with it, basically you can have this unique session in your browser. You start your browser up, go to this page, and for this session we can keep track of you basically. So what we do there is we're using to save some data for you. I appreciate that these code examples become a bit tidy, but just follow along because this is a very simple part. Basically what I'm doing here is I'm saying, okay, I have that cookie session and I'm going to set for this session id that I'm joining. I'm going to set my user id and my username. User id being a unique id and a username whatever somebody inputted. So when we handle the form for create session or join session, we store that information. So we can do now is when you're on that dynamic session page, whenever you want to cast a new vote, you want to say, okay, I think this is worth five story points. You're not going to send along who you are. Well, on the water it will, but you are not. As a developer, you just say for the current active session this user wanted to vote the value of five. So here I can do session get with that session id and I can basically get the data for you. So your username, your user id. So this makes sure that I can just store your vote. And you can never store somebody else's vote because, well, it's not your session and you don't even know their id. Well, you don't know their id. If we make sure that you don't because you can imagine if we have these votes and we store these votes and for everybody, we're going to return this data. These votes will contain everybody's user id and youre don't want to expose that because it's not needed for everybody. So what you can do, and that's a real added benefit of these server side functions here in that loader we say, okay, I'm just going to check whether I'm an admin and whatnot, but I'm also going to filter out this votes array. I'm just going to send back basically somebody's username and the effort that they gave. So for instance, five or three, but I'm not going to send back their user id because you don't need it in the application, so don't show it. We do everything on the server where it's safe and on the client is as dumb as we can keep it. We can even make this more secure. So basically we have this superbase and you can call to that superbase app. And how can I make this a bit more secure? Well, I can really leverage that server side only mutation part. So what I did is I said, okay, all my policies in superbase, I'm going to block everything. Doesn't matter which token, I'm going to block everything. Nothing gets past this. But I'm also going to create a server only token which youre can do in Superbase, which is basically the super token that can bypass these policies. So I'm going to get this server only token and what I do is I put it in my process env, which is a known pattern, I think to the most of you, but basically saying, okay, this is whatever that secret key is. And now this was, we just run it on the server will never expose that key. If you want to be sure, for every file that you want in remix, you can say server ts as a post fix to the file and it will make sure that it can just run on the server. But it does a good job regardless. And because we use this just on the server, I can just call this and we're safe in our security even more secure. So it feels a bit slow, right? Because you can imagine previously youre just hit a button, event listener post an app and you'd update youre UI. But now we're submitting a form post that goes to that action. That action is going to talk to Superbase. Superbase is going to do an update in the database. Then Superbase is going to say, hey, it went well. And it's going to come back again to us. Then we're going to say okay, in our UI we then update or redirect or whatever you want to and then you see it. So that is annoying. But it's even youre annoying when you have basically that grid of options to vote on. Because when I click that and I have to wait for this entire round trip before I can get the feedback in the UI. That's another nice user experience. And I promise you that we were going to use web fundamentals and enhance them to create a better user experience. So let's have a look at how we can make that a bit better. We can use something that's already existing online, which is called optimistic UI. And the gist of it is saying okay, I'm very optimistic that my code works. Basically I'm saying you hit submit, we know what you want to submit, we're already going to update the UI was if it went successful, then when the response comes back and it says it is successful, perfect, we don't need to do anything anymore. Once it says that there's an error, we need to put it back. This can be a bit cumbersome, but luckily remix thought about this and added something called a use transition. And what does a use transition do? Well, basically it has a transition state and you have this hook. For instance on your dynamic session page you listen to the transition state. So whenever any form on that page is submitting that transition state updates from idle to submitting doesn't do just that. So when we listen to it and we say okay, it's submitting, we can basically access that form data the same as we did it in the action. We can already do that here client side. So what we can do is get the data out of there, maybe add some little bit of client side state to show the optimistic vote here and clear it again once it's idling and then we can already update the UI. So what we basically do is see that we have on the 8th line we have active user effort where we basically say use the optimistic vote or the loader data vote and then use that in the render logic. And I know I said no client side Javascript state sure you can have client side state. If you want to enhance it, it's perfectly fine. But first cover your basis, have everything working and then see okay, how can I enhance this on the client and you can do it like this. If my client's Javascript doesn't load or something breaks, my normal flow will still work. It's a bit slower, but it will still work. So one thing I haven't talked about yet is going real time. And you can imagine if you first build your application fully real time and then try to bring it back to one that works with that client side Javascript. That's really difficult to do by the way, which is called graceful degradation instead of progressive enhancement. So how difficult is it now to go real time with that solid base that we have? So how can I have this Modern Ux? Because technically I don't need clients at JavaScript. The user could refresh and get the latest version, but that's not the nicest, right? There's an admin that's going to toggle the view, it's going to reset around. So how can we work with this? Naturally I need clients at Javascript to have these real time updates, but let's have a look at how that works. So first I created something which is called, I call it a use superbase subscription. So what is a subscription in Superbase? It's basically this little socket connection to Superbase where you can subscribe on any change that you want to. So what I did here is that, okay, I'm going to listen for any query that somebody passes to this custom hook and then on, well whether it's a put or delete post, a get whatever, whenever there's an update I want you to call the past callback. So great. In this callback I get the little record that got updated. So let's say that you updated your vote to eight, I will get your user which says I updated this to eight, please update your UI. So what I did naturally was say okay, thank you and I'm going to push that through some client side state. But when you have a lot of people and all spamming the buttons, you have to sort of trust that it comes in at the right order. Suddenly I was keeping track of basically against state and basically a copy of whatever was in the database and I was trying to keep it up to date and I ran into some issues and then I thought well no, I already have the logic to get the latest state out of the database, basically refreshing my page. Can I just reuse that? You can. So what do I do now? Instead of pushing into started, I use the last hook that I want to show you, which is called the use fetcher. And in essence what a fetcher does is you can have it rerun your loader function that you have on your file. So our loader function give us the latest state. So when somebody visits the URL, they're going to see the latest state. But then what we can do is call this fetcher. And then in fetcher it will have a key called data, which will then be filled or not. So the first time this page renders fetcher data is empty. So the loader data will be used. But when we say, oh, we have a callback and I'm going to fetcher load, well, my current path, this fetcher is going to be filled with again the latest version of the data. So now I'm basically just listening. Hey, there's an update. Just rerun my logic and have the data there. But with this simple or statement here, we can say which one we want to use and that's it. That is the entire layer of adding real time to this application. And I'm not that surprised that it is this easy because I first built this solid base and now I enhance that. So then you go for a test run. Well, this is me going for a test run with my team. So on the top right we have the application and on the left I have my teams call. Well, naturally, since there are a lot of developers in these meetings, they're trying to submit the form with things like drop table and try to see if I screwed up somewhere. Luckily I didn't. But more importantly, suddenly I had all these people just randomly selecting votes and tapping it. So really stress testing my system and my poor free superbase subscription, having all those requests going on, that was not the best. So what I did is I throttle it and normally youre would be like oh, why would you trottle it? You make your application slower. But we do this in a bit of a smarter way. So we have this optimistic UI part. So when you click on for instance, eight, it updates immediately for you that it takes a while in the back end, sure. But for you it's instant. So you have this feeling of an instant update whenever somebody else pressed on a vote of, for instance, one. If that takes 1 second before I execute it, are you really going to notice, do you know exactly the millisecond somebody pressed on it? So this is how I could just say, okay, well let's maybe throttle this for my demo and for my free superbase subscription. So now me and my team can actually just use this. And it's been serving us really well for it. Great. So we looked at a lot, right, all these little parts and that was the exact intent of building this application. You have so many of these. We basically had four little features, but look at how much complexity it even becomes when you try to keep it simple. And what I want to show here is that remix isn't just simple forms. And when you talk with people about remix, they will most likely talk about forms and having the dashboards and all those standard applications. But you can see we fouls easily. Just create a real time application. Not because it's all remix that offers that. No, it offers this solid base which makes it easy for you to add it on there, which is how I believe you should always build. A big benefit was that we basically moved all the state to the server where we could because we have the latest state on the server. We don't have all this client side logic that you need to keep in sync, keep up to date, which suddenly becomes very complex. And when you dave complex client side state youre going to introduce something called Redux, which needs a redux saga, which is going to need, and you run into this gigantic system. Well, all you had was basically a simple bit of data. Databases are perfect at keeping the latest state. Just get that and use these tools to do that and use web fundamentals. So I said that quite a few times during this talk and that's really what I want to get across, that if you use these web fundamentals which are proven technologies fully optimized for the browser that your application actually going to run in, really use that, it's really good at all these things. But then sure, enhance for modern Ux. So basically do it in that order instead of the other way around. Finally, it's not about remix, the framework itself, which is a weird statement after talking for 35 minutes about a framework, but it's more the thought behind remix. Right. It's basically pushing to use the web was a platform more and that's going to benefit you because if you pick up a framework like remix and another framework also relies heavily on web fundamentals, you can really leverage all your experience and your mental model of how you build it, but then just learn what is slightly different in the API of that new framework. So yeah, I'm really excited to see that we finally are going to, I feel like a web developer again, basically instead of a JavaScript engineer, and to really embrace that beautiful platform that we all know and love and want to build for. And with that I wanted to say thank you. I hope I inspired you to try remix out or think about progressive enhancement or web fundamentals in general in your application and see where you can actually apply some of these techniques or really rethink the way that you build your applications. These are my socials, so please don't hesitate to reach out to me. And if you have any questions, please send me a message and I will respond right away. And with that, I wanted to say thank you for your time, and I'll see you next time.
...

Dave Bitter

Developer Advocate, Team Captain & Senior Front-end Developer/Consultant @ iO

Dave Bitter's LinkedIn account Dave Bitter's twitter account



Awesome tech events for

Priority access to all content

Video hallway track

Community chat

Exclusive promotions and giveaways