Progressive Enhancement with Elliott Johnson - JSJ 591

Elliott Johnson is a Multi-stack data software generalist and works in Vercel. He joins the show to talk about "Progressive Enhancement". He begins by explaining Svelte & SvelteKit and how it's different from the other frameworks. He goes into more depth about Progressive Enhancement, and how it works. Moreover, he tackles Progressive form enhancement with SvelteKit and many more!

Special Guests: Elliott Johnson

Show Notes

Elliott Johnson is a Multi-stack data software generalist and works in Vercel. He joins the show to talk about "Progressive Enhancement". He begins by explaining Svelte & SvelteKit and how it's different from the other frameworks. He goes into more depth about Progressive Enhancement,  and how it works. Moreover, he tackles Progressive form enhancement with SvelteKit and many more!

On YouTube

Sponsors


Links


Socials


Picks


Transcript


Steve:
Hello, everybody. Welcome back to another exciting episode of JavaScript Jabber. I am Steve Edwards, the host with the face for radio and the voice for being a mine, but I'm still the host today. I snatched it away from AJ. Speaking of AJ, he is my co-panelist today here on the panel. That is from the Department of Redentancy Department. How you doing, AJ?
 
AJ:
Yo, yo, I'm coming at you live from air conditioning
 
Steve:
from air conditioning. That's
 
AJ:
Yes.
 
Steve:
a nice place to be, especially on a hot day.
 
AJ:
Yes.
 
Steve:
72 degrees.
 
AJ:
That's what they're telling me.
 
Steve:
That's what they're
 
AJ:
It was
 
Steve:
telling
 
AJ:
six,
 
Steve:
you.
 
AJ:
it was 68 before I turned on the air conditioning. I
 
Steve:
And
 
AJ:
turned
 
Steve:
it went
 
AJ:
on
 
Steve:
up
 
AJ:
the
 
Steve:
to
 
AJ:
air
 
Steve:
72.
 
AJ:
conditioning preemptively. So I don't know, that's a bad sign.
 
Steve:
I think you would call that reverse air conditioning, wouldn't you?
 
AJ:
Well, some would call it heating, but I
 
Steve:
Right.
 
AJ:
think that it's just that the air conditioner is not going to keep up with the ambient heat. That's why I started it when it was at 68. Cause I thought, well, might as well get it flowing because. It's going to be a hot one.
 
Steve:
All right, and before we get to our very special guest, I'd like to also welcome in the studio audience. Yes, thank you
 
AJ:
Give
 
Steve:
audience
 
AJ:
me a
 
Steve:
for
 
AJ:
chance
 
Steve:
being here.
 
AJ:
to wake up, sweetheart.
 
Steve:
For those that are interested, tickets go on sale online and you can get them and join us in person.
 
AJ:
Hahaha!
 
Steve:
We don't know where in person is, but it's still there as you can tell by the crowd. So with all that, let's get to our guest. Our guest today is Mr. Elliot Johnson. How are you doing Elliot?
 
Elliott Johnson:
Great, how are you?
 
Steve:
Good, good to have you. So before we get into our topic of progressive enhancement, why don't you give us a quick background on who you are, why you're famous, and so on and so forth.
 
AJ:
and how
 
Elliott Johnson:
Yeah.
 
AJ:
many gray hairs you have.
 
Elliott Johnson:
You know,
 
Steve:
Any?
 
Elliott Johnson:
maybe zero. I haven't I haven't found any yet. I'm still a baby. I haven't really gotten to the famous part yet. Maybe maybe ever.
 
Steve:
Well, after this, I've heard stories about after coming on our podcast, people just getting inundated with requests and even autographs and stuff. So never
 
Elliott Johnson:
Wow,
 
Steve:
know.
 
Elliott Johnson:
well, I don't know if I'm ready, but I guess I'll do my best.
 
Steve:
All right.
 
Elliott Johnson:
So yeah, so I currently work as a growth engineer at Vercell. So I work on basically any front end stuff that we have that faces users, and then also some backend stuff that nobody ever hears about. And my way into Vercell and kind of the whole front end world was spelled. I started out my career as a business intelligence analyst and then moved into enterprise data modeling and kind of hated it the whole time and needed to make a somewhat custom data site at some point. And I had, you know, just for fun learned about a bunch of different JavaScript frameworks. So I played around and React and Angular and some other stuff and stumbled upon Svelte and just absolutely loved it. And discovered a bug in the spelt kit one day and went and fixed it and one thing led to another and I ended up a maintainer of spelt kit and that kind of was my foot into the front end full stack door and yeah ended up here at Vercell making cool cloud technologies.
 
Steve:
So sort of the Jerry Seinfeld thing, I fixed a bug and yada, I'm a maintainer now.
 
Elliott Johnson:
Yeah, pretty much one thing led to another.
 
Steve:
All right. So when you joined it, was it called SvelteKit or was it still Sapper?
 
Elliott Johnson:
Um, so they are actually still separate things. Uh,
 
Steve:
They are? Oh.
 
Elliott Johnson:
Sapper just kind of, uh, so basically Sapper was kind of the first attempt. And, uh, I mean, it works. There are still sites running in production on Sapper, but, uh, there were a lot of learning opportunities there and it ended up kind of being one of those, you know, we could try to fix the mistakes that we made, or we could. make another attempt using some of the lessons that Next.js and Nuxt and the other frameworks have learned and that we've learned and kind of start fresh and make something new. And so we had a very long beta phase. I think we reached like almost 600 beta versions before we hit 1.0 on SvelteKit. But yeah, Sapper is still out there and available. Just wouldn't recommend using it. Svelte kid is now past 1.0 and has been for, I don't know, maybe half a year now.
 
Steve:
So by way of explanation, for those who might not be familiar with it, the best way to describe SvelteKit is as next is to react and next is to view, SvelteKit is to spell the sort of the meta framework for server-side rendering and so on, correct?
 
Elliott Johnson:
Yep, exactly.
 
Steve:
Okay. So why don't you give people a description of Svelte and I guess what it is and how it's different than some of the other frameworks. I mean, a lot of people have heard of Richard Harris and his history and how he developed it, but maybe there's some who don't know that.
 
Elliott Johnson:
Yeah, so AsphaltKit is, at its simplest, just another one of those component frameworks for front-end development, right? There's a bunch of different flavors of them. We've got React and Angular and Vue and all the other ones. And they're all really just abstractions over how do we make reusable UI components that handle state for the web. And if
 
Steve:
Thanks for watching!
 
Elliott Johnson:
I had to distill it, what I would say is different about Svelte is just that somehow, some way, Rich has managed to create a developer experience that I have not found an equal to among the other frameworks. It is just simpler and easier to use for my brain, at least. And what makes it different internally is that it is it's rather than being a runtime like svelte Not that it does not have any runtime, but svelte ships its entire runtime for like dom diffing and You know all that stuff svelte is a compiler so at build time, basically what we are doing is we're taking as much of the runtime logic that React and other runtime frameworks require and moving that into the build step and basically building the imperative code that is necessary to manage your state at that build time so that we don't have to ship a runtime when you actually visit a website. And the effect of that your base bundle size is just much, much smaller because there is no big runtime to ship the first time you visit a page. Yeah, so I mean, that's pretty much what Spelt is.
 
Steve:
So I've played around with it a little bit, haven't really done with it too much. The two things that always stand out to me that I think of when dealing with Svelte is one, that it's basically plain JavaScript, right? There's not a lot of viewisms or reactisms or something like that. And then the second thing is that everything gets compiled, it has to be compiled into plain JavaScript because there's no runtime distributed with it, right? So that's the whole benefit. It's smaller, it's cleaner. no runtime, so that's what makes it so performant.
 
Elliott Johnson:
Yeah, I would say like from the just the aesthetics of it, like when you're looking at it, if you look at something like React, right? React is kind of in one way a superset of JavaScript where you are working in JavaScript, all of your components are functions. You may be using JSX, which is like a new syntax that kind of brings HTML into JavaScript, but that's what it does, right? It brings HTML into JavaScript. Svelte kind of looks at it the other way. Svelte, the templating language, of HTML. So rather than looking at it from the let's bring HTML into JavaScript realm, we kind of looked at it from the let's make it as much like HTML as possible and use as much as possible just native JavaScript syntax.
 
Steve:
Excellent.
 
AJ:
So what's the difference? So with JSX, it's kind of like they didn't have JavaScript templates yet and so they made their own template language. And if they could do it again, I'm sure they would just use templates rather than having their own thing. With HTML, there's been lots and lots and lots of template languages that are not incompatible with HTML. They are, well, HTML doesn't really have a standard so much. So I mean, you just type text
 
Elliott Johnson:
Hehehe
 
AJ:
in a file that counts as HTML, but in terms of, you know, the brackets going where they should go, things looking like you expect it to look like maybe adding a question mark or a percent sign or something, but they, they pretty much can be parsed by something that can do HTML parsing. So what with, with Svelte, is it something where when I just open up my tooling, It's going to be able to format it and indent it just like HTML, or do I have to have something that's specific to svelte or what's, what's the syntax that makes it different.
 
Elliott Johnson:
So there are only a few things that are not like native HTML syntax in Svelte. So like a Svelte component, when you're looking at it, it's... normally split into roughly three parts, and most people sort them busily. You have a script tag at the top, which is just an HTML script tag, which has your JavaScript in it. Below that, you have whatever markup is associated with your component, which is your kind of HTML stuff, and underneath your markup, you'd have a style tag where you can write CSS, and that CSS is automatically scoped to the component that you're working in, so there's no like weird crazy class names that you're having your app, you know, if you need to write a very simple class name in a very simple component, you do that, hit stay scope there. Inside the HTML portion, there are a few additions, which is the superset part that Svelte has made. All of them are really just simple templating, you know, control flow type things. Like we have, we have in template, control flow with if, if and else. We have an await and We have an await. Block, which I believe also comes with catch and then. So basically you can take a promise while the promise is resolving, have some loading state when the promise has resolved, show the result of the promise, or catch errors thrown by the promise in a different block. But all of those share the same syntax. It's very similar to like mustache syntax that we use to do those blocks. All that being said, if you're in like a markdown processor and you're trying to share code with somebody, if it doesn't support an actual like svelte markup, you can normally say, you know, triple back tick HTML, and it will highlight your code exactly as you want it to. Because it is so close to regular HTML, but it just about always looks right.
 
Steve:
So that structure is just like a view single file component, script, HTML
 
Elliott Johnson:
Pretty
 
Steve:
styles.
 
Elliott Johnson:
similar, yeah, yeah.
 
Steve:
Not that I do view every day or anything, but
 
Elliott Johnson:
Hehehehe
 
Steve:
just so you know. Okay, so that's Svelte. That's SvelteKit and everything you ever wanted to know. Well, maybe not ever wanted to know. So let's move on to progressive enhancement and start out with a definition. And for the politics junkies, we're not talking progressive versus conservatives, I'm pretty sure. So what is progressive enhancement?
 
Elliott Johnson:
Yeah, so to caveat right up front, some of the stuff that I'm going to include in progressive enhancement here actually goes by some other names, but I kinda like to lump it all in because it's all under the same philosophy. Really, progressive enhancement is saying, We have a lot of diverse users. Not all of them have our wonderful 15 inch MacBook Pros with M1s in them, right? Some of them are on very cheap cell phones or very old computers with very low processing power. Some of them haven't updated their web browsers in a very long time. And what we want to do when we build websites is build websites that present a functional, if maybe not as beautiful, experience to as many users as possible and if those users can make use of... higher powered, you know, GPU accelerated features on the web, we want them to be able to have that beautiful experience that we love to build. So basically at the core of it, it is build a functional experience for everyone, build a beautiful experience for everybody that can make use of it. Because why would you exclude users from your site just because they don't have a nice enough device to view it? That's kind of the core of the philosophy.
 
Steve:
Okay, so in other words, it's only give people the things that they have the resources to use.
 
Elliott Johnson:
Exactly. Give them a way to use your site regardless of how they're using it.
 
Steve:
Okay, so what are the, if you're progressing, if you have a progressively enhanced website or application, what are the tiers? Is there, is there like a general sort of pattern? Okay, give them straight HTML and then if they got JavaScript, we'll give them JavaScript and then if they can handle this, we'll this, or does that kind of vary depending on the situation?
 
Elliott Johnson:
Yeah, so I think that a lot of times when people talk about progressive enhancement, they think that you're talking about shipping no JavaScript, which some frameworks have made it like their explicit goal to ship no JavaScript. And I don't think that that's where we should land with this conversation. Right. Like people, people do exist who have JavaScript turned off or who, you know, for some reason, you know, bad network connection didn't download the whole JavaScript bundle, you know, any number of things don't have JavaScript working. Uh, and we need to consider them. So, I mean, I guess I would say that's probably the first tier is like, can we implement this feature in such a way that it will work if JavaScript does not work at all. and then when JavaScript comes in, make it work better. But then the rest of it is any number of philosophies. Can we make use of older JavaScript APIs or compile? Well, can we make use of older JavaScript APIs to increase compatibility without affecting our developer experience? You know, you can transpile back to whatever ancient browser version you want to, but that will like inflate your bundle. So you gotta be conscious about how you're doing all of this. You know, anything that we can do to decrease the size of our site, right, when we're shipping it, helps with those people that are on a train and have an intermittent network connection or are out in the middle of nowhere and are getting, you know, a megabyte per second. So yeah, I would say probably the way that I would approach it is to start with, um, how do I make this work without JavaScript? Um, if I start from there, then I'm going to hit the largest audience probably that I can hit. And then when you run into the walls of like, okay, no way to make this work without JavaScript, you think, okay, how can I make this work with the least amount of bundle size and the most efficient, you know, code that I can write? Um, you know, maybe not adding dependencies to my module graph. Yeah.
 
Steve:
Yeah, in terms of people that would have JavaScript turned off, I can remember back late 90s, early 2000s, where that was a viable thing. People would have it turned off. They didn't want it for performance reasons, maybe security concerns, whatever the case may be. And I can remember there was a check you could always do in your HTML page and you just play a warning. Sorry, we need JavaScript to run this site. Better turn it on or you're hosed. Well, not maybe those words. But... Um, anymore, I mean, I think it's by default, um, that people are going to have it turned on. It's more the, the very rare exception than the rule that JavaScript would, would be disabled.
 
Elliott Johnson:
Well, I agree, but I also think that like, there's a good quote by, I think it's Jake Archibald of Google fame. He says something like, every user is a no JavaScript developer or user until the JavaScript bundle has finished downloading. And
 
Steve:
Haha, alright.
 
Elliott Johnson:
they're,
 
AJ:
I like that actually.
 
Elliott Johnson:
yeah, right. So it doesn't matter if they have it disabled, which I gotta tell you, there's a member of the allow JavaScript on most sites. So like there are still those weirdos out there,
 
Steve:
So
 
Elliott Johnson:
but
 
Steve:
he's
 
Elliott Johnson:
definitely
 
Steve:
working
 
Elliott Johnson:
a.
 
Steve:
on a JavaScript framework, but doesn't allow JavaScript on most sites.
 
Elliott Johnson:
Well, see, that's where SSR comes in, right?
 
Steve:
Okay.
 
Elliott Johnson:
So there's lots of cool stuff that you can do with SSR where JavaScript is always enabled that you could not do in the browser. But again. The point is not to ship no JavaScript. It is to make it work for as many people as possible. And I would say like when I'm on bad network connections, the most common failure mode for me is I got the HTML and CSS and something got screwed up with the JavaScript, right? Like this button is no longer working because I missed something as I like went out of my network connection. I live in Denver, so I'm like up in the mountains all the time. And there are lots of times where I can get. a website and then not have it become fully interactive, just because my connection is spotty. But we don't have to sacrifice our user experience for that. I think one of the coolest things that we have done in the past short amount of time is all of these meta frameworks kind of leaning on. What can we do with this hybrid server-side rendering, hydrated client behavior? One thing that's feltkit has done a really interesting job of is making it so that your progressively enhanced code is as similar to your non-progressively enhanced code as possible. It's probably not the best way to say that. But basically trying to make it so that when you're thinking about how do I write code for many, many users, the delta between that and what is the best experience I can write is as small as possible. One of the most common use cases that I can think of is form submissions, right? Native HTML form submissions, if you have a network connection, just work on pretty much everything, right? They've been a part of the standard forever. but they don't give a great user experience. So if you've got like an HTML form submission that fires off a post request and that post request takes even a second or two, if you're not using interactivity features like JavaScript, you don't get any feedback that form is submitting, right? Until it finishes submitting and loads your confirmation screen or whatever. But the really nice thing about HTML forms is that you can attach event handlers to them. So typically if we were on like, you know, a purely client rendered application and we were creating a form, we can. create that form and we can attach an on submit handler to it so that we can trigger our loading state and perhaps intercept that submission request and handle it through JavaScript in such a way that we can show them a modal or redirect them to the page that they're supposed to be on afterwards. And what's really nice about that is if you are trying to attach an event handler to a form. And for some reason, your network disconnects before you can download all your JavaScript. They have JavaScript turned off any number of failure modes. You can't attach an event handler to that form when JavaScript is not working. So if JavaScript's not working, that form is going to fall back to native form behavior, which is whatever the form action defined on it is, it's going to make a POST request to that URL.
 
AJ:
So I think this is.
 
Elliott Johnson:
Right.
 
AJ:
I think that we want, let me say it this way. It would be nice if, if something could work by default, it does work by default.
 
Elliott Johnson:
Yep.
 
AJ:
But at the other hand, you know, the weirdo that has the JavaScript turned off, I'm sorry, but he's just not buying my product, right?
 
Elliott Johnson:
Sure.
 
AJ:
He's like, I'm not making money off of that person. He's not contributing value to what I'm creating. So if he just wants to look at blogs and that's what he's using the Internet for. good for him, right? But I'm not, as a business owner, I know that I'm not gonna make money off of him. So I don't wanna spend 10 times as much effort trying to figure out all this nuance to appeal to him when he's not gonna gain me any business. So, I mean, and I could argue with me here. Am I making the wrong
 
Elliott Johnson:
Thanks.
 
AJ:
assumption? Is it that we're actually only using one-tenth the effort? Or is this, yeah, what does
 
Elliott Johnson:
So
 
AJ:
this look like?
 
Elliott Johnson:
I guess one thing that a lot of people miss here is that, like, we tend to think of this from a very, like, I have a thousand dollar smartphone point of view. This also just applies to very computationally limited people as well, right? Like...
 
AJ:
But are those people my customer?
 
Elliott Johnson:
I don't know, it depends on what your business is. If you're looking to go international further than just the US and the European Union, very possibly. But the other point that you're making on effort, again, is the whole point of the framework. If the framework can make writing progressively enhanced apps the smallest delta possible from writing whatever the heck I want to write with whatever experience I want to have, that's what we're trying to do, right? Is take the amount of effort required to write what I want and also to reach as many customers as possible and make that delta just minuscule.
 
AJ:
I'm 100% in on that by the way.
 
Elliott Johnson:
Yeah.
 
AJ:
I do a little bit devil's advocate. Most of the time it's
 
Elliott Johnson:
Oh,
 
AJ:
my
 
Elliott Johnson:
definitely.
 
AJ:
own opinion, but
 
Steve:
Haha,
 
Elliott Johnson:
Yes.
 
AJ:
on this one,
 
Steve:
a little
 
AJ:
I'm,
 
Steve:
bit.
 
AJ:
but
 
Elliott Johnson:
So
 
AJ:
I'm with you.
 
Elliott Johnson:
yeah, and the reason that I bring that up specifically is like in the case of spelt kit where we have SSR built in and we can use that on any number of platforms, the difference between writing a progressively enhanced form and writing a native HTML form and writing an all JavaScript form is like, a line of code. It is easier for me to write a progressively enhanced form that when people have good network and good processing, looks great and has loading states and does all that. The difference between that and making sure that it works for everybody is nothing. I have to write the code for my interactivity anyway. And by writing that code, I also write progressively enhanced code.
 
AJ:
Now with forums though, typically, unless it's a comment field, you have a sense of nestedness, right? So I'm going to, I'm going to have some parent object that's going to have some children objects, which may have some children objects. So typically that's best represented in JSON, not URL encoded. And in fact,
 
Elliott Johnson:
Yep.
 
AJ:
I don't think that we have a standard for how to URL encode that as of yet, which would be great if we did. But how do you work
 
Elliott Johnson:
Yeah,
 
AJ:
around that or is that not a problem?
 
Elliott Johnson:
so post requests are not URL encoded unless you purpose like a native post request with a form submits the data as form data.
 
AJ:
That's your L encoded. That's dub
 
Elliott Johnson:
Well.
 
AJ:
URL. And we're, we're saying the same
 
Elliott Johnson:
It's
 
AJ:
thing.
 
Elliott Johnson:
yeah so okay yes so let me let me back up when you said you are all encoded I'm thinking query string.
 
AJ:
That it well it is it's the same
 
Elliott Johnson:
yeah
 
AJ:
it's mime type
 
Elliott Johnson:
yes.
 
AJ:
mime type www URL encoded x form or I forget what the mind type is
 
Elliott Johnson:
Yeah,
 
AJ:
but yeah
 
Elliott Johnson:
so,
 
AJ:
same
 
Elliott Johnson:
but
 
AJ:
thing.
 
Elliott Johnson:
there is a very useful JavaScript wrapper around the form data object, right? So essentially when you make a post request, one, when you're on the server and you're receiving that request, you get your form data object back, which is not just some strange, like magic string that you're having to parse. It's parsed. You get, you know, you can call form data.get and all of your other methods. But
 
AJ:
Yes,
 
Elliott Johnson:
there are
 
AJ:
but it's
 
Elliott Johnson:
also,
 
AJ:
not, it doesn't have nested objects. So you can,
 
Elliott Johnson:
Yeah,
 
AJ:
okay, okay. Your face says that you know something I don't know.
 
Elliott Johnson:
so there are also some amazing and super easy to set up wrapper libraries that will just basically transparently parse your form data into whatever kind of object it's supposed to be. Super forms is one that has come out relatively recently, actually is kind of the result of a hackathon that we had earlier this year that has just absolutely blown me away. Libraries like that, we've got, what's the other one? There's a TypeScript transport library that works just fantastically for this as well. But basically, what all of them do is they sit between your form data and your code and do whatever transformations are necessary on your form data to turn it into whatever you're expecting it to be. And so the benefit of that is, right? you get to work with JSON or whatever object, like JavaScript object structure you're wanting to work with for your data. but it still works because it's all running on the server. It still works for everyone. So you're using the web fundamentals under the hood, but not having to interact with them directly.
 
AJ:
Okay, so this could still work in the no JavaScript environment. The thing that gets pre-rendered has the foreign fields
 
Elliott Johnson:
Yep.
 
AJ:
rendered according to whatever format and then it gets parsed on the other end. So we don't
 
Elliott Johnson:
Yep.
 
AJ:
have a standard for it per se, but you can pick. You can pick a library that will do it in the way that it understands.
 
Elliott Johnson:
Yeah, I would say until you get to somewhere on the upper end of like medium complexity, you probably can do it with no help. Like I have had very good luck with just using SpellKit, but when you get to those complicated examples where you're really trying to build enterprise grade apps, there are also libraries that give you that extra bit that you need to make it even better. And I guess to kind of go back just a little bit to the SSR part, one of the really nice things about SvelteKit and other meta frameworks, too, is that typically what they do is on first render. When you get your page, you get your page and it's server-side rendered. So you're getting all of the content as it was intended to be rendered on the server. And then what they will do is hydrate a client-side router. So. When you are using it and you have good processing power, you're the ideal user. You get the speedy quick navigations from, you know, that client-side router taking you places and rendering on your browser as you would expect. But the nice thing is if something breaks, if you do miss that JavaScript bundle or your computer is too slow to hydrate the router before you try to go somewhere else, because the router has not mounted. you get a normal full page magic navigation to your next page, which is also server-side rendered. So there's this very graceful failure state for pretty much everything on these meta frameworks where if your client-side router's not working, that's great, because the server-side one will.
 
Steve:
So going back to forms, which is the example you brought up, I remember there's a lot of JavaScript libraries out there for handling forms, whether it's validation, formatting your data for you so it looks nice and pretty for the user, that kind of stuff. But I remember, it's been a while, and I think it was Austin Gill I was having a conversation with. He works for Akamai, he's a friend of mine. He's been on here a few times. And it was about. what you can do with forms without JavaScript. And
 
Elliott Johnson:
It's
 
Steve:
you
 
Elliott Johnson:
pretty
 
Steve:
know,
 
Elliott Johnson:
incredible.
 
Steve:
it is, it really is. I've been working on an application. It uses inertia.js and view and Laravel. And so it's, you know, a bunch of view on the front end, but it's pretty data heavy application. And in working with my forms, there's a lot of stuff that I could do in with just. native forms, you know, without having to bring in a library that gives me a custom date picker and all this stuff that makes it, it was like so easy and so much less of a headache to just work with the forms. You know, there's an easy enough date picker. It may not be fancy enough. Some people, for me, it worked, you know, some, you know, requirements, validation type stuff that you can do. So to me, that would be a boon. progressive enhancement lease because you don't need the JavaScript in the first place. So there's nothing to enhance. Granted,
 
Elliott Johnson:
Yep.
 
Steve:
if you want to get really fancy,
 
AJ:
Cough
 
Steve:
there
 
AJ:
cough
 
Steve:
is some stuff you can do. And if from a validation standpoint, I mean, it's pretty well known that JavaScript validation can be bamboozled or overwritten. You really want your validation on your server side anyway, just to catch stuff like that. But my point being that there's a lot you can do without JavaScript in the first place.
 
Elliott Johnson:
Yeah, and actually one of the really nice things about the way that SvelteKit does handle its progressive enhancement for forms is that because it makes use of the client-side router when the client-side router is available, it really feels like you are doing client-side validation and doing all of this super simple stuff that we're used to doing in React, but you can run that on the server so that it works in both cases, right? whether the user has functioning JavaScript or not. And there are also really simple progressive enhancement cases within forms. For example, you were talking about a date picker, right? If you wanted to progressively enhance a date field, you can server-side render a normal date picker in there. And then you can run a JavaScript check on the client to see is everything working and replace it with a better date picker if you want to, right? Rather than just trying to ship a date picker that may or may not work, you can ship one that you know works and then replace it with one that's better if it can handle that.
 
Steve:
Okay, AJ, any more questions before we move on? Cool, good, I had my fingers crossed. Okay, so,
 
AJ:
I've got a finger for you, Steve.
 
Steve:
easy, this is a family friendly show.
 
AJ:
Hahaha
 
Steve:
So, when we talk about progressive enhancement, I'm always the details guy and how does stuff work? So, when you're saying, okay, here's my main HTML site, now, okay, if they've got it, I'm gonna throw in this JavaScript. Where and how do you do those checks? It's always the thing I wondered, are you like looking at the browser and there's a setting in there API that says, okay, he's got JavaScript enabled, go ahead and throw in a bunch of JavaScript. Or what is the mechanics of adding those different tiers on based on the capabilities of the browser or the user?
 
Elliott Johnson:
So this is where people that are really hardcore progressive enhancement people get angry at me for saying that this is progressive enhancement because they're terms people. But there are a number of ways. Well, one is like if we're talking about specific features, most, not all, but most like newer browser features that you might want to use but that might not be widely supported yet, you can check for somehow, right? Like you can check for like window.navigator. if you want to use window. If it's defined, then it's working, and awesome, you can use it. And if it's not, you've got to find something else to do. So some of this stuff you can actually explicitly check for. Others, we rely on graceful fallback. And actually, the term for that is graceful degradation, which I would consider part of progressive enhancement. And in cases like that, right? If you have set up your forms to work in a native manner, so if I ship this and it's just HTML, it will submit to the right place on my server, run the right code, return the right response. It's gonna work. If you've done that, and then you try to attach an event handler to that form, if JavaScript is working and the person was able to download your full bundle and everything is bootstrapped correctly, that event handler is going to get attached. And you can like event.preventDefault in there to handle whatever client-side stuff you want to with your form. And if JavaScript doesn't work, then that handler never got attached and your form is going to behave natively, right? I think that most, like most of the code that I write relies on kind of just the fact that if I write a check, that requires JavaScript to run, then that check is going to fail if JavaScript does not run, right?
 
Steve:
Sort of a catch 22, huh? How do I check
 
Elliott Johnson:
Right?
 
Steve:
for JavaScript without having JavaScript to check for JavaScript?
 
Elliott Johnson:
Right, exactly. So
 
AJ:
No script
 
Elliott Johnson:
typically,
 
AJ:
tag.
 
Elliott Johnson:
yeah, yeah.
 
Steve:
Right.
 
Elliott Johnson:
So typically, typically you'll write something that SSRs to a usable state and then enhances itself with JavaScript if it can, right? So write it so that it works when it's SSRed and write it so that it's better when it hydrates.
 
Steve:
So you can SSR with JavaScript already included, right? Like a script tag or how does that work?
 
Elliott Johnson:
Well, essentially, one of the nice things about Svelte is that it's kind of an SSR first framework in that basically, unless you are using browser primitives, everything that you write in a Svelte component can run both on the server and on the client. So if you think about it, kind of... I'm looking for a word here. If you think about it, progressively, I guess, if you think about the order in which everything runs, if you are SSRing your content, your component is going to run on the server, it's going to produce HTML, CSS, and JavaScript, and it's going to ship that to the client. Your HTML and CSS output is going to be the result of that server render, right? And you may ship JavaScript to the client that tries to make updates to that HTML and CSS. But even if that JavaScript doesn't work, you're still gonna get that HTML and CSS that was rendered on the client. So essentially you can do whatever the heck you want to on the server, ship the result of that, and then try to enhance it with whatever client side behavior you want with that JavaScript that gets shipped.
 
Steve:
So you said you have a component that runs both on the client and on the server. Is that okay? So my mind's just melting down as I'm trying to figure this out. So do you have from a physical file, your component file, you know, a single file component, whatever, do you just have one copy and somehow it's distributed to both the server and the client or, or how does that work?
 
Elliott Johnson:
Yep, so there is, we have a number of hooks that you can use in spell components. So when you're rendering a spell component, you have your script tag. your script tag is going to be run from top to bottom just like a normal JavaScript module is. So when you run your script tag on the server, it's gonna start at the top, it's gonna run all your code, and whatever values from your code are referenced in your markup are going to be rendered into that markup. So like in the simplest version, if you have a script tag that says const hello equals world, and then you have an H1 in your markup that says, that has, you know, hello, the variable referenced in it. When you SSR that, the output HTML is going to be H1 world, right? And that's what you're gonna get on the client. So that's cool and all. But we also have, there are hooks. onMount, onDestroy, you know, lifecycle hooks. And if I write an onMount hook in my component, when it is run on the server, that onMount hook is not going to be run because there's no mount on the server. You're not actually mounting anything to the DOM. You're just generating a string that's gonna be output as HTML and shipped to the browser. When it gets to the browser, it's then going to hydrate that component. And when it's mounted, it will run that onMount code. So that's kind of at base how it works, but there's also the fact that like the spelt compiler can output, like when we're running for a spelt kit, it can output a version of your, based on the same spelt file, it can output both a client and a server version of that component. So if it needs to be rendered on the server, it runs and renders a string, which is shipped to the client. If it needs to be rendered on the client, then it has all the code that it needs to, you know, mount everything to the DOM and do all the updates and hydration and stuff that it needs to do. But the point is all of that is taken care of by the compiler. You can write the same component for the server and the client and not have to worry about how exactly that works on the backend.
 
Steve:
So within your component, you don't have to run a check for is this client or is this server? I don't know if for instance, the older Nux 2 at least, for instance with Vue, in your async data, you would have a check, okay, there was a context value that says this is running on the server, this is the client. So that's not something you need to do with, at least with SvelteKit.
 
Elliott Johnson:
So that exists, I very rarely have to use it. So we do have like a check that you can import to say like if browser or if not browser, run this code. But most of the time I find myself not having to use it because if I need something to run on the browser when it's mounted, I'm gonna put it in on mount. Which like implicitly is a check for his browser because on mount doesn't run during the SSR cycle because again, there's no mount. And there's also like onDestroy, which very rarely, if ever, needs to get used. But yeah, if you need to access, I think the few times where I do have to use the like, isBrowser or isNotBrowser checks, or if I need to access browser primitives, right? If there is some sort of primitive window dot something that is not available on the server and it doesn't make sense to run that on mount, then then I may have to check to see if I'm on the browser or the server.
 
Steve:
Okay, so we've established, I think, the mechanics and the why and sort of the how of progressive enhancement. Is there anything else we're missing in terms of what's involved with progressive enhancement?
 
Elliott Johnson:
I think that the fundamental like tick point for me where it kind of crossed over into understanding was like, it's really easy to start your web development journey in a front-end framework, right? Like I think that my introduction to front-end development was React.
 
Steve:
Mm-hmm. Mine was
 
Elliott Johnson:
Which
 
Steve:
angular.
 
Elliott Johnson:
was really
 
Steve:
Right.
 
Elliott Johnson:
cool, right? Yeah, so like a lot of people get introduced through these frameworks and it's really cool because it gives you a low barrier to entry into web development, which is awesome. But at some point you need to step back and learn how web fundamentals work. Like how does HTML work? How does CSS work? Try to build a website with no JavaScript. I'm not saying to do that because I want you to go build websites with no JavaScript because JavaScript is frickin awesome. But because that understanding of like, what are the different failure modes of websites and you know, how do these three technologies, HTML, CSS and JavaScript interact with each other? Understanding that and being able to understand like, well, when everything explodes, this is like where I'm going to be that. Being able to look at things from that direction helped me a lot. Definitely backing out of the framework game and figuring out how the web works, and then coming back into it gives you a fresh set of eyes.
 
Steve:
Yes, it's amazing how understanding the fundamentals of something actually helps you understand
 
Elliott Johnson:
Yeah.
 
Steve:
what's being added on top of it, you know, an area in which I am still lacking, but now are you familiar with the guy named Maximiliano Fertman?
 
Elliott Johnson:
The name sounds familiar,
 
Steve:
He's a Brazilian
 
Elliott Johnson:
but I'm not connecting
 
Steve:
guy. We've
 
Elliott Johnson:
it.
 
Steve:
talked to him before about progressive enhancement. It's been a while. He was episode 415 of Fertman. Yes, it was his name episode 415 of this. So this is about. three and a half years ago. So yeah, PWA has been around for a while. I can remember going back to my early Drupal days where the term that you used earlier, the graceful degradation, I think, was the term you used to add your jQuery back when it was jQuery before Angular and for any of these frameworks came out, was right in such a way that it'll still work even if jQuery can't load. And jQuery, obviously, and it was always pages loaded. OK, now I'm going to throw in my JavaScript. I forget what the hook was, the way we always check to see if everything was loaded. But yeah, the concept is certainly not new by any stretch of the imagination. And like you said, I think a lot of people fall into the trap of assuming that everybody's got the same killer latest iPhone or Android phone or M1 or M2. chip in your MacBook or a desk, you know, all the stuff that can easily handle JavaScript. And you forget that there's a lot of people that don't have that, those great connections and great hardware.
 
AJ:
May the technology gods have pity on their souls.
 
Elliott Johnson:
Right?
 
AJ:
If you don't
 
Elliott Johnson:
Gotta
 
AJ:
have
 
Elliott Johnson:
get better
 
AJ:
an M1
 
Elliott Johnson:
wifi
 
AJ:
or an
 
Elliott Johnson:
on the
 
AJ:
M2,
 
Elliott Johnson:
subway.
 
AJ:
you're not living the good life.
 
Steve:
I don't know, man, after getting, I still have my own computer is still an Intel chip MacBook and then I got an M2 for my work laptop and M2 has got its advantages, but more getting it working sometimes is painful. That's all I can say.
 
AJ:
Look, I we should talk offline about that. I've never had a problem that I can recall other than you have to install Rosetta by right clicking on terminal and checking Rosetta or get info and then Rosetta anyway. Other than that, it's been smooth sailing. And the first week that the new M2s were out, there was an update that you had to get for sleep to work.
 
Steve:
Oh, okay. Yes, we will talk offline off the hours I've spent chasing that down. Uh, all right. So before we move on to pick Sally, was there anything else? Uh, we, uh, we're missing.
 
Elliott Johnson:
No, go check out Svelte, it's pretty fun.
 
Steve:
All right, so with that, we'll move on to picks. Picks are the part of the show where we get to talk about anything other than tech, or you can talk about tech if you really, really that much into it. Let's start with AJ, you got any picks for us today?
 
AJ:
I'm checking to see here if I've got anything. Oh. I've been listening to Star Sight, which is the second book in the Skyward series. I actually just finished it last night, finished the epilogue in the last chapter that comes after the last chapter. That's new. I've never had an epilogue and then a chapter after the epilogue before. But Brandon Sanderson Trailblazer. Uh, so that's, uh, it's, it's a really good. So far, it's a really good series. I've really enjoyed it. It's sci-fi fantasy, girl out in space. Well, post-apocalyptic earth. Actually, we don't know what happened to earth, but they're living on a different earth. And she's a fighter pilot and goes through a bunch of... I don't know how to give a synopsis. You'll have to listen to somebody else, but it's... It's been a good book and it's very kid friendly, I would say. This one doesn't seem to have too much in there in terms of swearing or awkward moments that you'd have to worry about. It's very enjoyable as an adult. It's not juvenile, I don't think, but it's also very family friendly. But just Brandon Sanderson is that way in general. I love the way that Brandon Sanderson does swearing. I just love it. because he makes up an alien language, just kind of like if you ever watch the TV show Firefly. Well, in that case, I think they actually swear in Chinese in some cases. So I think they are actually, anyway, but in their in their made up language, they have their own swear words that come from essentially their own religions and deities. So in the Stormlight archives, it's the storm is the is a swear word because the gods of the storms essentially are, you know, they're deities. And so they it's. And then I don't know where it comes from in, in star site, but scud is there. They've got a couple of other words, but scud is their main swear word. So I appreciate the way that he handles that, where you can still see that people are being vulgar and expressing anger or contempt, but, uh, it does it in a way that is not so, uh, that, that can still be family friendly anyway. And then.
 
Steve:
When I hear Scud, I think Scud missiles from the gopher.
 
AJ:
And that may have something to do with it as to why that word was chosen. I don't know. That's not really explained. Whereas in the other books, you can tell where the swear words come from, because as the book progresses and more of the plot unfolds and you understand more about the world, you recognize that one of their sacred symbols or one of their, you know, one of their things that people revere is X. And so then either X or a related word becomes the. the curse word much as it is in our human Earth languages. The other thing that I might pick, oh, actually I will. Al City came out with a new album. I ordered it, Amazon shipped it, and it was cracked because something had obviously gouged through the Amazon packaging and through the CD packaging and cracked the CD, so I haven't listened to it yet, but I will soon. And Al City, I love Adam Young. He's one of my man crushes. He comes out with just excellent music. And that's it. That's all I got for now.
 
Steve:
Today is definitely a day to write in the calendar for short picks for AJ.
 
AJ:
And you know what? I've got another pick, which is a certain finger on my hand for Steve.
 
Elliott Johnson:
It's this one.
 
Steve:
Yes. All right. I will go next and we'll save, uh, the guest for last, although not the best for last cause the best for last is always the dad jokes, but, uh, first off as a blog post that happened to see on hacker news by a guy named Jeff Geerling. Um, I recognize Jeff's name from. Do you Drupal world and he's really big open source Linux and that he, uh, created a environment called Drupal VM that you could use to, uh, use containers and Ansible and. I forget what else, to be able to just spin up and run a site. He's got a post that says he's done with Red Hat Enterprise Linux. And the gist of the post is that Red Hat and their use or rather abuse of the license is really they've already killed CentOS, I guess. And
 
AJ:
Really?
 
Steve:
yeah, and they're
 
AJ:
Huh.
 
Steve:
trying to. to force others to buy licenses, use their distribution. And he talks about thing that distros that spun up in the absence of CentOS, I think it was Alma, and I forget what the other one is, oh, Rocky Linux and Alma Linux. Anyway, it's on his site. He's an interesting guy. I think he's from Missouri, a very prolific open source developer, just an interesting post, especially as it relates to open source software and licenses. And now for, I'm sorry, go ahead.
 
AJ:
I think this is just indicative of the problem with open source. It seems that it's maybe the. The expectation, right, because we all know that you have to get paid in order to produce something, you can't produce something for two decades for free. But the open source is kind of a false promise of, oh, this is going to be free, but then eventually reality has to hit and they have to start offering paid products. And if the offering of paid products doesn't. do it, then they have to require paid products. And then people feel like they were lied to. And I don't think that was the intention. But that's the reality is that, you know, if you don't get paid, do you eat? Do you pay rent?
 
Steve:
Yeah,
 
AJ:
Red
 
Steve:
there was
 
AJ:
Hat
 
Steve:
a
 
AJ:
2.
 
Steve:
guy, there's a guy I remember hearing about another podcast and I forget the library had it was some, I want to say it started with the C. And he was like, I maintain this library that's used by everybody in the world. And I get nothing for it. You know, I get like 65 bucks a year out of people donating or something like that. He's like, and I can't remember the, the outcome of it, but he's like, I gotta, you know, I gotta make some money if I'm going to put all this time in it, you know, for free for everybody else. Elliot, you were nodding. Do you remember? what I'm talking about.
 
Elliott Johnson:
I was thinking of Faker.js. I think something like that happened to that.
 
Steve:
Yeah.
 
Elliott Johnson:
That was like the mocking library.
 
Steve:
Right.
 
Elliott Johnson:
I seem to remember something very similar to that happening with them.
 
Steve:
Yeah,
 
AJ:
There's
 
Steve:
that's
 
AJ:
dozens
 
Steve:
I.
 
AJ:
of projects at this point. Core JS, Faker JS. Yeah.
 
Steve:
CoreJS, that's the one. That's the one I was thinking of was CoreJS.
 
AJ:
And that one, Oh, that dude has got the worst story ever because he, I believe he's a born of Russian parents went back to visit Russia. Now he's trapped there, can't leave. And
 
Steve:
Oh geez.
 
AJ:
then, and then all of this, you know, propaganda means that nobody is in the U S at least is legally allowed to donate to him or pay him for work. because then you're a Russian sympathizer.
 
Steve:
Right, right. It's like Wimbledon banning Russian players and stuff like that.
 
AJ:
like those are these are not these are not our enemies these are not the people that are out there killing others and even the people that are actually pulling the trigger they're not the ones that are the enemy they are just the ones that are pulling the trigger and we might have to pull the trigger back depending on who we happens to be on the given day
 
Steve:
Right. So anyway, before we get off on too much of a tangent, uh, it's interesting post on Jeff gearling.com. Uh, and then finally the, uh, the dad jokes of the week. Um, so thinking back, you know, when I first passed my driving test to get my license, when I was 16th, I actually got a nine out of a 10. I did pretty good. That last guy managed to get out of the way. Right?
 
AJ:
Hahaha!
 
Steve:
So, you know, I live in a neighborhood, sort of a cookie cutter neighborhood where houses are somewhat close together. And if I'm reading their lips correctly, my neighbors are arguing about some creepy guy next door. Although I'm pretty sure it's not me. And then finally, for those in the dental profession, I never understood why I said a false teeth is called dentures. I mean, they really missed an opportunity to call them substitutes.
 
AJ:
That one took me a second. Actually, it's taken me more than a second, but I'll just be that guy, I guess.
 
Steve:
Substitute, substitute in case you missed it. All
 
AJ:
Ah.
 
Steve:
right, so with that, we'll move on to Elliot. Elliot, what do you got for us for picks?
 
Elliott Johnson:
I just went and saw the new Spider-Man into
 
AJ:
Oh!
 
Elliott Johnson:
the Spider-Verse movie for the second time Like a couple of days ago and like if you haven't seen that movie if you haven't seen the first one Well, you're just buying and you need to go What you need to do is you need to sit down for the first one and then go to the second one immediately after
 
AJ:
Okay, I will do
 
Elliott Johnson:
It's
 
AJ:
it.
 
Elliott Johnson:
just art. I mean just pure art one of one of the I mean it's up there like with if you've seen arcane like it's just up there with the best animation that's ever been produced. Incredible art from beginning to end, great voice acting, the story's great. Yeah, totally worth it, go see it.
 
AJ:
Yeah, and they did the style on the first one. It just totally drew me in. And
 
Elliott Johnson:
Mm-hmm.
 
AJ:
I love watching the behind the scenes stuff. And they talked about how they actually swapped out the frame rates. So the bad guys
 
Elliott Johnson:
Yep,
 
AJ:
are
 
Elliott Johnson:
yep.
 
AJ:
on a, what, a 20 frames per second and the good guys are on a 30 frames per second. And so this
 
Elliott Johnson:
Yeah, 24
 
AJ:
gives
 
Elliott Johnson:
and 12. Yeah.
 
AJ:
20, yeah. And it gives you this jarring effect where the bad guys are more, yeah. Oh.
 
Elliott Johnson:
Yep. Yeah, so if you're going to go see it, I'll give you one thing to look out for. There is a scene where they are sitting upside down, and you're looking at a skyline of New York. And if you've seen those movies before, you know they do the 3D animation, and they do the line work over top of it to make it look. very comic book-y, there's a lot of stuff they do, but they do the line work over top of the 3D work. And if you look at that skyline of New York, for one shot of it, about a second and a half, right in the middle, there is just the corner of the side and top of the Twin Towers in the middle of the skyline. There's no tower, just the line work for the corner. Really cool little Easter egg they threw in there.
 
AJ:
How
 
Elliott Johnson:
Yeah.
 
AJ:
do you notice that if you've only gone it to the, or if you've seen it in the theater, or are you just watching reviews?
 
Elliott Johnson:
I've seen it twice. I went the first time to watch it, and then I went the second time to just look at all the stuff in the background and see what I can see.
 
AJ:
But you could, you can see one frame. You can.
 
Elliott Johnson:
No, not a frame. I mean, like it's a shot like you see it and is there for like a second and a half. I mean, it's not
 
AJ:
Oh,
 
Elliott Johnson:
like it's not like it's
 
AJ:
okay.
 
Elliott Johnson:
not like boom. It's like you see it and then it pans away.
 
AJ:
Okay,
 
Elliott Johnson:
Yeah.
 
AJ:
okay. I for a second,
 
Elliott Johnson:
No, no, not like that.
 
AJ:
I misunderstood what you said. I thought I thought you said that it was in there in a second and a half shot. It was in there for one frame.
 
Elliott Johnson:
No, no,
 
AJ:
Okay.
 
Elliott Johnson:
no. It was there for a second and a half or so, yeah.
 
AJ:
Okay,
 
Elliott Johnson:
But you'll,
 
AJ:
got it.
 
Elliott Johnson:
if you get to that scene and you're watching for it, you'll see it because it's right in the middle of the screen, but I missed it the first time. Yeah. And then I guess second one is, if I can just show you right here, I really love these keyboards by Keyboard IO. Where are you? Come on camera. There we go. These guys are so cool. This thing has saved me so much carpal tunnel. It is a two-sided keyboard. with an ergo layout and they just make the coolest stuff.
 
AJ:
Interesting
 
Steve:
That
 
Elliott Johnson:
Yeah,
 
Steve:
is truly a split keyboard.
 
Elliott Johnson:
it is a split keyboard and the case is walnut which has been great because I have sweaty hands and it doesn't make them sweat. And the company, yeah, the company is called Keyboard IO and they make lots of really interesting like micro layouts and ergo layouts and stuff like that. So, yeah.
 
AJ:
want to get into that. But my problem is then I would have to have a second one to carry with me everywhere and it'd be very bulky.
 
Elliott Johnson:
I actually have no trouble switching back and forth between this layout and like my normal QWERTY on my laptop.
 
AJ:
You're not committed enough.
 
Elliott Johnson:
Yeah, well, maybe I'm just it's just because I'm young I've still got that neuroplasticity you know.
 
Steve:
and no
 
AJ:
Maybe
 
Steve:
gray hairs.
 
AJ:
I can't. Yeah, I have a hard time. I have a hard time. But I'll pick one more thing. The M2 Mac studio, by the way. I'll throw that in there. That's been great. Side tangent. Nevermind. My thought process went to 10 different things. And then I just blurted something else. Normal, normal me. Normal me.
 
Steve:
Is there a difference between a tangent and a side tangent?
 
AJ:
Yes.
 
Steve:
Oh, okay.
 
AJ:
One
 
Steve:
Is that a
 
AJ:
is
 
Steve:
tangent
 
AJ:
to
 
Steve:
off a
 
AJ:
the
 
Steve:
tangent?
 
AJ:
side of the tangent. So tangent, you can see where it connects a side tangent. You can't see where it connects. You have to be in the other person's head.
 
Steve:
That's a scary place for you. Okay. All right. I'm guessing I'm gonna get the finger here real quick. So before we get to Unfamily Friendly, we're gonna wrap up this episode for today. Before we leave, I'd like to say once again, thank you to our studio audience. They've been sort of quiet during this, but I know they're there. I can feel them in spirit. Thank you, Elliot, for coming in and enlightening us on progressive enhancement. If people want to follow you and see what you're saying and doing and give you money, what is the best place to do that?
 
Elliott Johnson:
Well, I have a Twitter with 16 followers. It's at underscore gruntled.
 
Steve:
Ha ha ha.
 
Elliott Johnson:
So you could be like 5% of my followers just
 
AJ:
doing
 
Elliott Johnson:
by
 
AJ:
it.
 
Elliott Johnson:
joining.
 
AJ:
I'm
 
Elliott Johnson:
Yeah,
 
AJ:
getting in while it's
 
Elliott Johnson:
you by yourself. Yeah, and if you wanna do some further reading, I have, or further watching, I've put a great video by our own Rich Harris in our chat here. So hopefully they'll include that somehow
 
AJ:
This
 
Elliott Johnson:
so you
 
AJ:
is
 
Elliott Johnson:
can
 
AJ:
just
 
Elliott Johnson:
go learn
 
AJ:
a picture
 
Elliott Johnson:
some more.
 
AJ:
of a cat.
 
Elliott Johnson:
Sorry, I like to tweet once.
 
AJ:
You literally tweeted once.
 
Elliott Johnson:
This...
 
Steve:
Oh,
 
Elliott Johnson:
Hey,
 
Steve:
really?
 
Elliott Johnson:
all I'm saying is if you want to get in touch with me,
 
AJ:
What did you
 
Elliott Johnson:
you
 
AJ:
just
 
Elliott Johnson:
can DM me.
 
AJ:
turn
 
Elliott Johnson:
I'm not
 
AJ:
18
 
Elliott Johnson:
DMing you. Hahaha.
 
AJ:
and now
 
Elliott Johnson:
I'm not
 
AJ:
your
 
Elliott Johnson:
DMing
 
AJ:
parents let
 
Elliott Johnson:
you.
 
AJ:
you
 
Steve:
Hahaha.
 
AJ:
join Twitter? What what's going on?
 
Elliott Johnson:
I, you know, I just prefer my people in person.
 
AJ:
That doesn't sound like an 18 year old. You must be 80.
 
Elliott Johnson:
Sorry, the disguise worked really well.
 
Steve:
All right. Okay, so with that, we will wrap this episode. Thank you to Elliot, thank you to AJ, and thank you to me. You're welcome for coming, and we will talk at you next time on JavaScript Jabber.
Album Art
Progressive Enhancement with Elliott Johnson - JSJ 591
0:00
1:01:42
Playback Speed: