669

September 20th, 2023 × #Svelte#JavaScript#Web Development

The Svelte + SvelteKit Show

Wes and Scott discuss their experiences building apps with Svelte and SvelteKit. They cover templating, data fetching, state management, actions, layouts, styling and more.

or
Topic 0 00:00

Transcript

Wes Bos

of Svelte and talk about them.

Wes Bos

Again, we've done some Svelte shows in the past, but now that I have built Two applications in Svelte and SvelteKit.

Wes Bos

I feel like we should do it again as also, like, kind of tell you as like my background is primarily a React and vanilla JavaScript developer.

Wes Bos

So give you my opinions on that type of stuff, like what I love, what I don't like, rid What what was a little bit weird? All of that good stuff. So we're gonna go through templating, data fetching, state, reactivity, library, rid. Request handlers, hooks, forms, routing, layout, styling, and things I don't like. I got a I got a couple of bones.

Scott Tolinski

Rid Double bones and bones. Okay. We'll see if I can, smooth out some of those bones too. Maybe, maybe it's a, user error thing or an education thing. You know? Sometimes it is.

Wes Bos

Syntax is brought to you by Century. Century is error exception performance tracking. One thing they just dropped is rid. Rage click detection is just the best.

Wes Bos

Sometimes you you just freaking like, a a rage click is when you just press a button a 1000000 times or or do something like sometimes you get it on your phone where you shake the phone and it's like, did something go wrong? That is really cool that they are now detecting rage clicks And dropping them in, to the timeline the event timeline. So check it on out. Century.i0.

Wes Bos

Use coupon code tasty treat 2 months for free. Yeah. That's funny to me. I know,

Scott Tolinski

we don't need to get too deep into the rage click state, but, like, when when Century dropped the user misery score for house bill your pages, I was just like, man, This company's got a grace that's a humor, not for, like, detecting rage clicks. It's like, yes. This is how people this is how people use stuff. And then when they get angry, They start clicking a whole lot. Ah. You know? So, shout out to Suntory for those fun ideas, whoever's coming up with that stuff. Rid. Alright. Svelte fundamentals. Let's start with templating

Wes Bos

out Svelte and SvelteKit. So maybe we should real quick go through it. So Svelte rid is the library,

Scott Tolinski

and It's it's considered almost like a language. I mean, it is A compiler. Yeah. Yes. Svelte is different from

Wes Bos

React in that rid. Svelte itself is compiled before it runs. So Svelte has its own files.

Topic 1 00:02:33

Svelte compiles to vanilla JS

Wes Bos

It has, like, a dot Svelte file.

Wes Bos

And in that you put JavaScript templates, which is kind of like your HTML and your CSS, whereas like React also is Kind of compiled because you write JSX, right? Like React itself can be written vanilla JavaScript, right? But most people write React via JSX, where you have your template tags and your on click handlers and whatnot, and that gets compiled actually running in JavaScript. So that's Svelte. And then SvelteKit is routing, data loading, Server side rendering.

Topic 2 00:03:21

SvelteKit for routing and server-side rendering

Scott Tolinski

What else? App building, really. You're building a website or a web app.

Scott Tolinski

You're reaching for a Svelte kid. And, primarily, Most of the time, 99% of the time, if I'm building anything of nature of any kind, I'm I'm reaching for Sveltekit.

Scott Tolinski

And if I'm just doing a demo or I'm experimenting with a language or something, I'm writing Svelte. But I think it's important to note too, like, coming from React, If you're a React developer who doesn't have a ton of information here, one of the big differences between something like Svelte and like something like React is that Svelte has rid. Compile the straight up JavaScript that you can read as JavaScript, and it's it's just modifying the DOM.

Scott Tolinski

So unlike React that tries to control the whole rendering of your app and you have to worry about rendering cycles and how much how many times is is This function, this component being rerendered, you don't necessarily have to worry about that as much with Svelte because it's it's interacting with the DOM itself. It's making changes directly to the DOM. There's not a virtual DOM that is, controlling how the website is essentially rendering itself.

Scott Tolinski

So there's no virtual DOM. You don't have to worry about things like memoizing.

Scott Tolinski

You largely don't have to worry about Many of the things that you have to worry about with the virtual DOM. And because of that, one of the big things that people they get hung up on when they're learning Svelte rid learning or coming from React World is that they say, well, where's the Svelte library for x, y, and z? I I You know, there's a react library for doing this. But in Svelte world, you almost not often as much need a Svelte specific library Because you can work directly with the DOM. You don't have to avoid using the DOM. You get to work with the DOM.

Scott Tolinski

So, therefore, you can Have most of the the straight up JavaScript ecosystem to work with the DOM as you as you typically would, and therefore, rid. You know, you don't have to avoid browser APIs in the same type of way. You can embrace them. You don't have to use the React way of doing things. You can just do the web way of doing things.

Topic 3 00:05:23

Svelte is mostly just JavaScript

Wes Bos

Yeah. I found that my my biggest hurdle to learning Svelte was just understanding How to do if and else loops and whatnot.

Wes Bos

Honestly, like, the rest of it was just like, oh, yeah, that's just JavaScript.

Wes Bos

That's just how it works. And rid. There's not a lot of weird stuff or not that I still really like React, And it's well worth your time learning those weird things in React, because once you know them, you know them. Right. But I find in Svelte, there was a lot less of that Templating in Svelte is very similar to how you would template in a normal thing. You Just use curly brackets. You put your variables in there.

Wes Bos

I don't love the if else and, like, 4 loops in Svelte as much as I just want to I found I don't know if it's because I'm used to just using maps, But I find myself wanting to just use regular JavaScript, ternaries and if else and mapping over things and returning values.

Wes Bos

And it was a little bit weird. And even like I was inside of a loop and I wanted to programmatically Put a few pieces of data into a variable.

Wes Bos

So I had to use the at const inside of a curly bracket to do it. And I found myself rid Like so there's a script tag in Svelte, and then there's your template. And then below that, you have your CSS. Right? And in your script tag, that's often where you'll, If you need to do a little bit of data massaging for that component, you'll often do it there. And I found myself wanting to do the data massaging a little lower in the loop.

Wes Bos

Yeah. And I found myself saying, okay, no, like, go back, loop over the data and make it look like what you want.

Wes Bos

And then then do the loop and then go into it because I was, like, making variables at cons inside of the loop. And I was like, you know what? This is This is muddy. I'm gonna I have to

Scott Tolinski

make it proper. And then some notes on that, I found the act the act const is a newer addition to SALT. So, it it is kind of largely like an escape hatch or like a nicety. But in in the terms where, like, if I'm doing a loop and I wanna massage each item Of that loop, I'm almost always making a component and then just doing it in that component.

Scott Tolinski

Oh, yeah. A a subcomponent and then doing it that way. But But it's interesting that you would say that you'd prefer, like, a a map. You know, the thing that I like a lot about the templating language is is get having Or getting to avoid the double ampersand thing inside of React where you would do the, you know, variable double ampersand to To essentially do an if statement, if this variable is true, then render this code. To me, it makes so much more visual sense to say if Var, you know, is true rather than variable ampersand ampersand, especially when you're just parsing it to have that if If there, is way more readable to me personally and, like, also with, like, the dot maps not having to Have a function that has a return statement and all this. Like, I can just do a loop. I I don't know. Maybe it's because I I was so used to the same Type of simp templating language in Meteor for so long. The the Blaze framework in Meteor used space bars, which was rid Handlebars like templating language, very, very similar to this.

Scott Tolinski

For me, it was like coming home. I'm I'm I'm writing Svelte. It was like, I've been dealing with all these functions and maps and and worrying about arrays and keys and all this stuff. I'm coming home to that, like, loops.

Topic 4 00:08:49

Svelte templating is like Handlebars

Wes Bos

Yeah. Maybe maybe just like some sort of shorthand.

Wes Bos

You know, like if this thing exists, then rid. Render either render this component or put a paragraph tag that says like for mine, I had 2 pieces of data. I had the summary of the Syntax podcast And what that had it was it had timestamps of all of the major topics, you know? And then I also had rid The entire transcript where every single utterance, which is like a sentence or 2, went through and said who it was. And I wanted to rid intersperse those, meaning that, like, I would loop over the transcript. And if there was a topic that needed to go in between those utterances. Then I would have a little if statement and I found myself going back and merging the data first, grouping it and then looping going into it rather than just checking if it right inside of it, which I think makes a little bit more sense. Like, get your data in order first And then the template itself is pure pure template. Right? It's pure you just you just template it out what it should look like. And and with React, I found myself rid. Mixing

Scott Tolinski

the data logic and the templating logic a little bit more. Yeah. Totally. One thing that that aspect has saved me from rid. It's something I never loved in React where where, people would put templating code in the function code. So the, the the stuff that was above your return of your react statement, people are putting functions that then returns markup upwards in all various aspects, and I found myself always, like, jumping around a file. Like, oh, I'm going way up here to look at my and at least with the Svelte, you have your Your script stuff and then the template code and then the style. So it's like you always kinda know where to look Yeah. In terms of you're not having to jump around.

Scott Tolinski

Rid. To me, that was like a little bit a nice thing. Another thing

Topic 5 00:10:52

Multiple components per file in React is nice

Wes Bos

which I found a little bit weird is that you can only do 1 component per file.

Wes Bos

And in React land, I found myself enjoying putting multiple components that are grouped together In a single file, I found it much quicker to dev on that type of stuff when you're like, Okay, well, I'm working on this utterance And the speaker of the utterance and the link to when you click on that, it will jump the audio to that specific time. You know, like, that that probably should be its own component because there's click logic in there and there's custom formatting and all that stuff.

Wes Bos

In React Land, I would just kind of like take it out, go above it, make a little thing. It's like, alright, well, these things go together. Right? Like, it's an utterance component inside of the utterance. There's the utterance header, and then there's the utterance body.

Wes Bos

And I found myself being like, I don't want to make a whole another component for this another file. Totally, especially if you're just prototyping. Exactly. I found it to be a little bit slower to do that type of thing. And Maybe I don't have my editor.

Wes Bos

I should just have 2 files open at once. I haven't gotten into the groove of that type of thing, but rid. I certainly would like to be able to put multiple components

Scott Tolinski

in a single file. I I I set up a keyboard shortcut That you know, the the default behavior in Versus Code to split a pane, like, duplicates the file and has 2 files open. Yeah. I set up the shortcut to do hyper s, which rid. Takes the current file I'm looking at and moves it to a the another the other pane so that way I can easily split a pane really quickly. And I do find myself almost always having multiple files open split, at least 2 split, 1 1 on the left, 1 on the right. Especially in SvelteKit when you have the the server side information and the client side information or, you know, your API information, so to say, Your data loading, that sort of stuff.

Scott Tolinski

But, yeah, you know, I wonder if there's there's fix for this, You know, pain in in tooling in regards to editor functionality. Right? Like, what If you were in in in line typing and then all of a sudden you hit a a keyboard shortcut, it would make a new component.

Scott Tolinski

And if you typed in the name of the component, it would simultaneously create a file and insert

Wes Bos

that component in, and you could keep working without Yeah. And do, like, the props for you because that that's another thing. I don't wanna I have everything in my scope. I don't wanna leave my cozy of I know. I hear you. Now everything I need in the scope, I don't wanna leave the scope.

Scott Tolinski

So to to give you some some idea about where my brain is thinking on this, there's a A visual language that I learned from called Max MSP. That's all it looks like patch cables and boxes. Right? And one of the things I love about Max MSP As you could click and drag and select a bunch of these boxes, and you click 1 button as, like, f 12, and it does encapsulate.

Scott Tolinski

Rid. And what that would essentially do is move that into its own component because it's this is, like, Pre component workflow, but it's a component. It would move it into its own component, replace that with all of the inputs and outputs already assigned for you Exactly like you would what we're talking about with your props and your scope. So it allowed you to quickly prototype code. You wanted to move it out, select it. You know, you'd encapsulate it, so to say, and it would move it to its own thing. Like, I really wonder if there's some bit of dev tooling there that could make that process nice. Rid I always wondered that in React too. Because that's a nice thing about,

Wes Bos

like, React land because TypeScript the TypeScript compiler it. Understands JSX.

Wes Bos

So all of the tooling that is TypeScript based refactor, all of that stuff Works. It's just Java. Like I say, it's just JavaScript when in reality it's not. It's TypeScript and JSX, but the TypeScript compiler knows both of those things. So You can use all of the tooling and all the plugins that are built upon that.

Wes Bos

A weird thing was felt is that it's its own language, like you said. So any tooling that is built has to be custom

Scott Tolinski

custom made for Svelte and Svelte. Yep. Yeah. And part of the benefit of it being its own language, I mean, you're writing JavaScript most most always is just straight up JavaScript, but part of the benefit of it being its own language is you get access to, You know, niceties, like I I mentioned, not having to worry about memoizing and not having to worry about DOM updates and things like that. But you get access to niceties like, the reactivity syntax. So if you put a dollar sign in front of a variable name As a as a writable, you can now work with essentially a store, a global store rid as if it were just a straight up variable. You know? That store equals value instead of having to do that store dot update or whatever and having to do a a callback function or a passing a function in there like you would in, typical syntax. And under the hood, Swalt, as a compiler, can optimize that for you.

Scott Tolinski

And because it can optimize that for you, you don't have to worry about making it faster performing. You don't have to worry about the, rid. You know, obnoxious syntax for it. You can just act like as if it's a variable. And some of those things are the the reason why I think people rid. Really, when they try Svelte, they say, oh, man. It's so simple. I don't have to clutter my code with return functions or anything like that. I just do, you know, straight up equals, which is great.

Wes Bos

A really good example is the utterance that is currently being spoken. So we have a list of, 500 utterances throughout the episode, and I want to be able to highlight the current one based on the player time. Right? Rid. Normally what you do with that is you would create in Raglan, you create like a hook, you know, and You pass in the player time.

Wes Bos

And then when that time changes, then you would find the current utterance and you would set state and all of that stuff. Rid I literally just wrote a find function that says find the utterance where it is within the current Lead playing time from the player, which is coming straight off the audio element, and then return that to a variable. So that that's me finding the value once.

Wes Bos

Now. If I want to make it reactive whenever the current audio changes, what did I do that? I write a huge hook, Put it into its own thing. Memo wise the thing, you know, like, call an expert consultants. No, I put dollar dollar sign red. Colon in front of the variable and boom, that thing is reactive. And now any time rid. Anything in that find function changes, the find will rerun and and update the variable for me, which is I was just like, oh, this is amazing.

Topic 6 00:17:26

Making variables reactive with $

Scott Tolinski

Yeah. And other benefits of that are that, you know, Svelte 4 came out and, you know, user facing changes to Svelte 4, Nothing. But they've made changes behind the scenes to the compiler, and now your apps run faster. Okay.

Scott Tolinski

I'll take it. I like it. I'll take it. Yeah.

Scott Tolinski

I'll take anything that you make changes behind the scene. I don't have to think about. My app's faster. Okay. Yeah. Sign me up. Yeah. Yeah. So let's talk about the data fetching, and this is like a SvelteKit thing. So oftentimes, like, we're talking about, you know, these These templating languages are some of the reactivity stuff. These are all Svelte features. We're we're bringing in data. We're bringing in server side context or anything like that. We're talking about Svelte rid Server side stuff like that. And and so data fetching is being done largely through this concept of loaders. And the way that loaders work, it's essentially a, rid a function that can run server or client, depending on how you name your file. If you do dot, plus page dot server dot rid TS, it's only on the server. If you omit that server part, it's run on the server and the client. And, essentially, this is just a function that has access to your re Request information, any of the local information that you pass, maybe like user information or something like that, and you just return out of this thing, And that information is passed directly as a prop into your component, and you can stream out of here. So you can return a promise from a loader, And that will stream the data to your your client side, which is great, your template. You don't have to think about it at all. And for the large part, I I really like this API. You know? It makes working with loading data as easy as making a dot server file, rid Doing whatever maybe database calls you need to do and then returning directly from there. Bingo. Bango. Your information's in your Component. No no having to worry about fetching or any of that stuff. I don't have to hit another server. My my server information is Right there in my code base directly next to it. That's that's honestly amazing because, like, you think, oh, do they have a GraphQL API? No. Do they have a REST API?

Wes Bos

Rid. Not really. Kinda. Like, we can. We could with we could make it with loaders. No problem. But we what type of stuff do you do in a loader? We're literally running database calls ready. So we're using Prisma. So we just have like, for example, on a the show's page, our loader is just a function that is sync and it returns an object that has prisma. Show. Findmany, and then we pass it a couple of arcs of what pieces of data we should and should not include and it will return it all. It's awesome because you just pop into the file, run your database query, and boom. That data is immediately in your front end for you to go ahead and work with. And like Scott said, there's no fetch request. There's no caching, there's no rid. GraphQL queries. Nothing like that.

Topic 7 00:20:17

Load data directly in Loaders

Wes Bos

Beautiful. I absolutely love it. And this is not something that is unique to rid SvelteKit. No, this is making its way into Next. Js and remix and all of the frameworks because, like, honestly, This is the way. Yeah. This is the way. I think everybody's had enough of

Scott Tolinski

throwing a a fetch into a useEffect and having to worry about that and then, You know, eventually moving to libraries, various libraries to do all of your fetch queries from your templating code.

Scott Tolinski

The way is just having your data available From a server side function somewhere, whether that's how Remix does it, how Astro does it, or how SvelteKit does it, it's all really great.

Scott Tolinski

Rid. And like you said, if you need an API endpoint, there's a feature called endpoints. You just make, essentially, almost like a an express rid Dial route in your app directly, and it's available at whatever route. It's all baked into the routing code, and it it just straight up works.

Scott Tolinski

And another cool thing about, rid. You know, some of the way the loaders work is that you can access browser features like caching directly. You can set headers from there. You can set caching headers, and and anything that you would need to do is just available right there in the loader to make your rid your data load how you'd want us to load. So you can get as micromanage y as you want it, or you can just straight up, like you said, do a database query in there, return it, bingo, bango. You're done. Yeah. And like, I'm trying to think, like, there's nothing

Wes Bos

svelte about a loader, is there? No, not really. It's just A sync JavaScript function that returns data. Yep, that's it. There's nothing special. And like you said, if you do do headers, those are standard browser headers that either the browser will use to cache or a CDN that's sitting in front will use to cache the data as well. So You could take that's what I love so much about this. You could take that loader from literally anything else. Serverless function.

Scott Tolinski

Drop it in there. Boom. Boom. Boom. You're good to go. Yeah. And on top of that, which we haven't even talked about, is how well this integrates with TypeScript.

Scott Tolinski

Because in the past and, Wes, you might be noticing this. In some parts in the code base, we are importing, like, page data types and stuff like that. Well, you don't even have to do that anymore. It automatically infers your types. So if let's say you're returning a user object And that user object is typed. Right? As long as that user object is typed, your UI automatically gets that type now directly from the server side return.

Topic 8 00:23:34

Type inference from server to client

Scott Tolinski

So good. You don't have to import types. You don't have to do anything. If that type if it knows what type it is when you return it, your your Your client side code knows what type it is. And that to me is just like, oh, chef's kiss. I I I just you know, the amount of times I duplicating types Across my server to my client and my GraphQL API when I had them separated was like, alright. Is this actually the right type? Now I have no idea. I'm I'm I'm maintaining separate sets of types for all different things here. And now it's like, oh, it just is the type because it already knows what type it is. Rid. Yeah, it's wild. So we defined our database

Wes Bos

schema in the Prisma file.

Wes Bos

And then when in our loader, We return a query and it knows specifically which fields it doesn't return. There's no show type rid. And the thing there is there is a show data, but there is a show. Is it just a show with a URL or is it a show with the description? And like because there's Every query could be a little bit different, and it specifically knows sometimes it's a pain in the ass because you don't know which data is coming in or it's unsure of which fields are coming in. But in most cases it works really well.

Wes Bos

And the types generated from Prisma go into your back end query, And then the result from the query ripples through to your front end. And it's just I didn't write a line of TypeScript and everything is fully typed rid And type safe. That's my ideal

Scott Tolinski

form of using TypeScript.

Wes Bos

Just, having the types Just not writing any type Please have them for me. Thank you. Yeah. There's a difference between using TypeScript and like obviously the authors who made the stuff frickin went deep on it. But us. Users don't have to fuss too much about it.

Wes Bos

Let's talk about actions.

Wes Bos

So actions They sort of go alongside your loader, and they are things that can be sent From the client side to the server side. So if you want to import a show, like, an action for me is We have a table of all of the shows and I want to request a transcript for it. So we'll have a little form And you click the button and then that will hit the server side action for it. So again, there's no fetch request.

Wes Bos

You simply just say rid. Run this action called fetch transcript or import shows or delete show or whatever.

Wes Bos

And again. Just like the loader, you put all your JavaScript in there, all of the logic as to what needs to happen, and then you return rid like a success or a failure message from there.

Scott Tolinski

Yeah. And the coolest part about actions, besides the fact That you can write them right there next to your loaders is that they can work really well with, Again, HTML and JavaScript browser APIs straight up just normal form requests.

Scott Tolinski

So because of that, It works as just a, an action on a form, an HTML form, and It works without JavaScript enabled, but you can then toss in a little use colon effect helper on the form.

Scott Tolinski

And next thing you know, your form is progressively enhanced to the fact where it will do all of this without doing a full Page reload like what typically happens when you submit a form, but the form will submit with JavaScript. JavaScript isn't enabled. That form's still going to work. So you get automatic progressive enhancement into actual standard straight up HTML APIs.

Scott Tolinski

And, again, you know, people rid People shy away from things like Svelte because they worry that, like, oh, I like React because it's just JavaScript. Well, this is like this is using the browser to how it should be used. We're not, stepping in there and doing a custom fetch, and you can if you want to, but we're not doing that necessarily.

Scott Tolinski

Rid. The default behavior for it is to work with the straight up HTML forms like you should. Right? And and and cool part is too. Another thing rid like this is that with Svelte, you use the standard a tag. You don't use a a link component or an a component.

Scott Tolinski

And, likewise, you don't have to import a form component to get this functionality.

Scott Tolinski

You just use an HTML form. And one of the things I like so much about that is it it feels like rid with niceties sprinkled in here. It doesn't necessarily feel like you're abandoning your precious HTML.

Wes Bos

This is true. I rid. Really like that aspect of it as well. Like, there's nothing Svelte about this. Like, I find that to be the common Use case over and over again. Aside from like the SvelteKit stuff where you must have your folder directory structures in a certain way. And the if statements our customs has felt, a lot of it is simply just JavaScript, Right. It's just HTML and JavaScript, and then they add some sauce on top that makes it live reload and be able to back in and refresh the data and make things reactive.

Wes Bos

Like, all the benefits of vanilla JavaScript, but none of the annoying bits. Rid. Yeah. Make it nice. Make it fast. Make it easy. Let's talk about state. This is probably my favorite.

Wes Bos

Is it my favorite part of Svelte. Probably state and binding are my 2 favorite parts of votes, Svelte. And if you're comparing to React specifically,

Scott Tolinski

It makes date feel a lot nicer.

Topic 9 00:29:14

State management is easy in Svelte

Scott Tolinski

Maybe not my favorite part of Svelte overall, but, like, If I'm saying if I'm doing a comparison from React to Svelte, I think this is my favorite bit of change, is is state.

Wes Bos

And the reason why it's so good is because state.

Wes Bos

First of all, state variables can just be variables.

Wes Bos

Let Age equals 10, and you can just simply say age equals 11 or age plus plus. And You can just update state that way instead of having to have a set state hook and and whatnot.

Wes Bos

And then my favorite part about it is you can import and export states into the components that you want them instead of having to, like, throw them at the top of your application or high enough that you hope it's high enough and then pass them down via props.

Wes Bos

You can simply just import and export the state values wherever you need them. And it doesn't have to live like a different hierarchy, and you can just use them all the different parts. So we have some player state, right? And that will give us information about what the current show is and the current time And all the information, the volume, all of that good data speed, and you can simply just import it rid and use that data. And if you wanna be able to update it, you simply just

Scott Tolinski

set it. Right? Yeah. And you could set it with It's a dollar sign or whatever and then the equals. And and I I think the the big thing there is state by default lives outside of the component tree entirely. You know, you can create a writable or a derived state.

Scott Tolinski

You can create that state and then have it accessed completely outside of rid. The the component tree.

Scott Tolinski

And to me, that was always the the hard thing about React. Right now we gotta worry about context. We gotta worry about, rid where the state is living, now you have providers, and the state lives up top. But I don't even think about my state As being part of the component tree, I think of my state as being completely separate, and my state lives on its own. And you can access that state As you need it, where you need it without having to worry about providers or or what anything is.

Scott Tolinski

And, you know, I think some of the concern there with the simplicity of the syntax might be that it's not as powerful, but you can do resolver style, you know, state if you want. You can get in there and do some, like, really intense state. For instance, rid. You can have a basic state that's just a variable that you can update, you know, whatever that's a single variable, or you can have it be A giant function with methods that update the state from within the state. So Yeah. Both types. It's not all just the state dot variable is equal to whatever. Rid. You can do a state dot update status to playing, and that update status dot playing function is rid own function inside of the state that can do internal manipulations to the state, set state trees, or whatever you may do. And I found that aspect of working in it really nice because it can be very simple. You can make a single variable that's a state piece that can get passed on, or you can make this rid beast of a state that contains so much information about the player. Right? Is the player open? What's the current date? What's The current dom element that's being manipulated, all that stuff. Right?

Wes Bos

Binding value is also very simple.

Topic 10 00:32:42

Global state detached from components

Wes Bos

I needed the current time of the audio element to be bound into state because every time the current time of the audio element changes, I need to update The currently spoken utterance and display it on the page. All that good stuff, right? And I thought, okay, well, now I'm going to need some like event listener, Right, because you're going from like in React Land, you're say on time change. There's an event.

Wes Bos

And then when that fires, You get the event, and then you take the event. Current Target.

Wes Bos

CurrentTime, and you set state.

Wes Bos

And then you have a hook. And rid. I was I was like rolling up my sleeves to code something like this, and then I realized it was just Yeah. Bind. So I go to the audio element, rid. And I wrote bind colon as an attribute, current time equals, and then I just bound it to our state. The dollar sign player is our state that contains all the information about the player.

Wes Bos

And then now anytime that current time updates, rid. It will mirror that to state. And even further, I was reading in the SvelteKit docs is that instead of using the On time update event because apparently that doesn't fire frequently enough for Svelte.

Wes Bos

They wrote their own version of it that will allow to allow you to bind it, and it's even faster, which is amazing. Yeah.

Scott Tolinski

Rid The stuff I use binding the most for, anytime I wanna access a DOM element, you create a variable. Let's say I have a canvas. Right? I can say, let canvas, and that's the variable.

Scott Tolinski

And then on the canvas in HTML, I can say, bind colon this rid equals the canvas. And now anytime I want to access that DOM element, it's just bound automatically to that variable.

Scott Tolinski

So I use bind this To essentially

Wes Bos

it it's like a reuse for React. Right?

Scott Tolinski

Yeah. You're accessing a DOM element. Only this time you're accessing the actual DOM element. Right? Rid bind value for forms. You can bind a value for a form. You can attach an entire, form.

Scott Tolinski

You can bind an entire, like, form to an object of variables or individual variables so you never have to do the on change business To update a a state variable for a form makes working with forms extremely easy.

Topic 11 00:35:10

Easy form binding with values

Scott Tolinski

But here's another one, Wessette. I don't know if you've seen. There's a couple of special components inside of Svelte called Svelte colon window or Svelte colon document Oh, I haven't done that. That give you access to the window itself, and you can bind properties to variables.

Scott Tolinski

So for instance, if you wanna get, like, the scroll y position, You can do, bind scroll y on a Svelte window to a variable, then bingo bango. You have a reactive The variable for the scroll position.

Scott Tolinski

So we showed how how you can do parallax in Svelte Without a library and, like, one line of code just by binding to a variable and then attaching that to a trans a CSS transform, then bingo. You have a,

Wes Bos

rid. All the like window stuff that used to be a pain with server side rendering. You know, like if type of window is equal to quotes of undefined.

Wes Bos

Yeah. You can't run Windows stuff on the server rendering.

Wes Bos

Obviously, that's getting a lot better in all the frameworks, but You just don't fuss with any of that in SvelteKit either. Word.

Topic 12 00:36:21

Bind to DOM nodes and browser APIs

Scott Tolinski

Let's talk rid About hooks in SvelteKit. Hooks are essentially middleware.

Scott Tolinski

There's server side or client side hooks, and you can, You know, iterate through them. You can, do something before and after a hook. So if you want to, start maybe perhaps a Performance tracker before the request has completed, and then you complete the request, and then you can step in and check to see how long the request took. That's like no lines of code. But hooks are also great for authorization.

Scott Tolinski

I did a body parser hook, so that way you could rid parsed form bodies automatically send it along as locals to every single form request.

Scott Tolinski

But Hook's really super sim simple, And it's a really nice syntax. It allows you to sort of step in there. And this is a SvelteKit thing because, again, it's like the full platform for working in in Svelte apps. Rid But, you know, middleware is one of those things that I think frameworks neglect for some reason. And when they do neglect it, it becomes a big pain because You end up having to run a lot of wet code. That's good. Request handlers are

Wes Bos

pretty simple thing. We've talked in the past about rid. The fetch request response API Svelte response handlers are very similar. You don't need them A whole lot because loaders and actions take care of most of what you need. But if you are running a straight up like you want to create an API, For example, we have the Syntax API in the current site and we're going to need to replicate that API in SvelteKit so that anyone that's currently hitting that API still gets the same data rid Return to them. So you can create, a server route. And in that, you can You have get, post, put, patch, and delete methods, and those will respond to people get, post, put, patch, delete that specific URL. And then inside of that you get the request. And then they also provide you a bunch of, like, handy Like JSON responses because that's one of the things if you're going straight up request response, You have to set all of the headers.

Wes Bos

If it's JSON, you got to JSON stringify it yourself. You got to put the JSON header along with it. Rid. You got to create the response with the constructor and then you return that.

Topic 13 00:38:35

Helper methods for JSON responses

Wes Bos

So there's a nice bunch of just like handy helper methods You can import from Svelte and it will do all that for you, which is very similar to like Hano JS. So rid. Again, if you have code that's in a serverless function somewhere, moving it over will probably be almost nothing. Yeah. Totally.

Scott Tolinski

And, again, And you can return anything from this. So, like, doing a site map, hey.

Scott Tolinski

You can do all your database queries in one of these.

Scott Tolinski

You can return XML.

Scott Tolinski

You gotta say no.

Scott Tolinski

You know, it's, it's all pretty simple at the end of the day for for any of that stuff.

Scott Tolinski

Let's actually We talked a little bit about I'm gonna bounce back and forth from Svelte and SvelteKit stuff. I'm gonna talk about Svelte actions, which you gotta feel like there's gonna be a name change here. Rid. They did a a bad thing, which was they named something in SvelteKit actions, and they named something in Svelte actions.

Scott Tolinski

And they're 2 different things. So it feels like, you know, at some point, there's gonna be a name change. Who knows if that's actually true? But in Svelte, actions are these things that you see them proceeded with use, Like, use colon something and use colon anything.

Scott Tolinski

What it does is it gives you life cycle methods on a DOM element in direct access to rid And know the node element or that that node, that DOM node directly in a JavaScript function. So what you can do is you can write a function in the component or anywhere at all, you can write a function that has a single parameter that is just the node or perhaps arguments if you wanna pass an argument.

Scott Tolinski

And then now all of a sudden, you can do use colon your function, and now you have life cycle. You know, if that DOM element is created, updated, whatever, You have access to the DOM element itself and complete life cycle on that. I use this all the time, to for stepping in and basically giving rid. HTML advanced functionality.

Scott Tolinski

In fact, this is really similar to, like, directives in Angular.

Topic 14 00:40:42

Svelte actions similar to Angular directives

Wes Bos

Very much similar to that before. Directives just became, like, components and text essentially. This is what we use the for the toast and loading messages, right? Yeah.

Wes Bos

One thing Scott made was this he built like a site wide toast so that anytime you want to throw up a loader screen because something's happening, It can have its own internal state.

Wes Bos

And then when basically because the forms By default, we'll just do a proper HTML form submit and refresh the page. You can use a form action to rid. Intercept it and then send the request on its way and then get the request back and see what happens. So If the result is a success, then show a successful toast message. If there's an error, then display some sort of error.

Wes Bos

And then I even I extended it a little bit so that one thing I found really hard was that we had these buttons Where I wanted to fetch the transcript and I wanted to fire off like 6 of them at once and just click 6 different buttons. Right.

Wes Bos

And what was happening is We clicked it, and then the whole website would say something's happening. I would have to sit there and wait for it. So I made another one that just, like, put a spinner Inside of the button, and then I made a its own component. So instead of having to open a form tag every single time, I just made a little component where you can hit a specific URL, send the data along,

Scott Tolinski

and you're good to go. So I really like these form actions. And and not even just form actions. You can do this for anything, Les. So, like, another one I posted a link in the show notes is, an anchor. So we're using the popover API. In the popover API, it puts your your popover on a new layer, meaning that you can't do position rid Absolute and anchor something to a position relative container because it's now on another layer, and it doesn't see that container.

Scott Tolinski

So what I did with this anchor action was I measured the parent and then the child anchor. It's like setting that position automatically via just rid Straight up JavaScript. So because I get access to that DOM node, I can measure it directly in here.

Scott Tolinski

It it once you Once you get comfortable with these things, I think you're gonna go nuts on these things because it it's it opens up a whole ton of world here. So I'll post a link to to the anchor one that we have as well as the on click outside action, which is, like, a pretty classic one people write when they first get into these things. That's exactly what I need.

Wes Bos

So I'm using position sticky for a bunch of the transcript stuff, rid. And there's nothing in CSS that will say there's no sticky selector. So when something is stuck, You can't style it differently than when it is not stuck, right? And like, I wanted to put, like, a little Shadow underneath it when it is stuck.

Wes Bos

So what you have to do is you have to use resize observer or, intersection observer, sorry.

Wes Bos

And when something comes on and off the screen, you can add and remove classes. And I was like, I don't feel like dipping into that. Like sometimes in React land, I'm like, I don't want to have to write an entirely separate hook for that type of thing because you you cross the bridge from React APIs to vanilla JavaScript APIs.

Wes Bos

Rid So you're saying with with this, I could just have, like, a act like, a use colon sticky function that I could write.

Wes Bos

Mhmm.

Scott Tolinski

And what's even great about this is that some people, what they do, you'll see that in the onclick side is you're you're dispatching custom events on this. So you can dispatch you can you can dispatch a custom event, so meaning that you can now have an on

Wes Bos

colon on an actual dom node without making its own component. Oh, I like that. So you can say when this thing goes on the screen, off the screen, then dispatch fire an event from that dom node.

Wes Bos

And then I could I could set up a totally separate rid Handler for when that thing is fired because I might wanna add a class in one case and something else I might wanna do something entirely different. Yeah. Rid. The the this this API

Scott Tolinski

is the Svelte power user's best friend. I'm gonna tell you that right now. Oh, yeah. I didn't I had not realized that that was So powerful. I thought it was just for form actions. Yeah. And that's the whole thing. It's like they they had this powerful API, and they're like, oh, wait a second. We can rid Step in here and intercept the form request and do all the progressive enhancement using our own powerful APIs.

Scott Tolinski

Rid it's really, really just a cool, cool API overall.

Wes Bos

Routing is pretty simple. You have a routes folder, and then you can you have your all your folders inside of that. So we have an API My folder and login folder and a show folder. And then you can do, like, optional and nesting and all that good stuff in there. I don't love that everything is page dot svelte, because, like, I know Versus Code Controversial.

Wes Bos

We'll put the folder like if you have 2 pages that Svelte open at once, Versus Code will put the folder name in the URL.

Wes Bos

But if you have too many of them open, they get lost.

Wes Bos

So like maybe I need to I'm sure Versus Code can do this. It's like write a custom tab rule that instead of saying page that's felt it puts show number.

Scott Tolinski

Yeah. The folder.

Scott Tolinski

Yeah. I'm pretty sure that's This was controversial, and I I gave it a chance. I think the one thing that I like most about it is it makes it really easy to find, Pages and, like, routes specifically verse components because you can always do in Versus Code. You can rid. Start all of your fuzzy finds with a command and then just a plus.

Scott Tolinski

Or when you're look doing your fuzzy finds, if you start any of it with a plus, you'll know that you're looking for, rid Like a page, a route, essentially, rather than a component itself, meaning that you don't have to worry about naming things as much in that regard. But, again, I I agree. Like, just staring at layout dot server, page dot server, whatever. It's like, okay. What is all this stuff?

Wes Bos

Rid. Yeah. Definitely one of the more controversial API changes. When you're in the folder, it is nice to know that this is page, this is server, like, you know exactly where this where and when this is running.

Wes Bos

But finding the folder I find to be pretty tricky and jumping to it is pretty tricky.

Scott Tolinski

Layouts rid. In Svelte, you wanna tell us how layouts work? Yeah. Layouts are nice because it's it's slot based. So you have instead of a children like you have in React, you have slots Like you have inside of web components or Vue. Right? So a slot is essentially a stand in for stuff that goes inside of it. So inside of SvelteKit, anytime you want to have a wrapper around a given route, you inside of that route, you can do plus layout dot svelte.

Scott Tolinski

And then you can write your surrounding code, and then you just do slot.

Scott Tolinski

And because of that, rid You you automatically have that same style that we had in React Router where the contents inside of the layout change without rid The outside of it changing, or rerendering, like, that is such a concept that I got to abandon in React World. I don't think about, is this component rerendering? I'm thinking about, are these values changing? And because of that, you you no longer have to worry about, alright. I made Some change here. And now all of a sudden, my layout's rerendering, and I gotta worry about the effects of what's happening because that layout's rerendering.

Scott Tolinski

And and, you know, this kind of stuff is being solved in in modern Next. Js and stuff too, but, you know, it has been one of those things that, for me, was a nice life having situation.

Topic 15 00:48:44

Layouts and slots avoid re-rendering

Scott Tolinski

Anytime you know, I find myself especially if I'm, like, prototyping or boot rid Strapping. I'll just start you know, start writing right away. I'm in the page code. And then I get to a point where, like, alright. This interior stuff is going well. I need a header and a footer for this. Alright. I'm just gonna make a layout in the same folder. Boom. Header, footer, you're done. Okay? You got it in there. You just toss the slot, and now you have that. And this works at every single step down the, route tree so you can have as many nested layouts as you want, And all they do is essentially wrap all of the contents inside of there. And the the API works really nice, especially if you're building, you know, sub navigations or you're building any sort of like, for instance, on the new syntax site in fact, rid. The new syntax site will link up into the show notes here so you can paw through this thing. One of the things that I wanted to do is make a little bit of of our design system and our component library and stuff public. So I made a system page, and that system page is going to have its own nav so you can now all of a sudden nav within All of the system content, if you wanna see the colors, the layout system, whatever.

Scott Tolinski

And so to make that navigation for the system page, it was as simple as just making a dot layout Deeply nested within the routing structure, now all of a sudden, I just toss in a nav in a slot, and next thing you know, I got I have a nav there. It took, like, 2 seconds, and So easy, so fast.

Wes Bos

Styling in Svelte is, I guess, pretty straightforward. You Pop open a style tag at the bottom of your component and you can apply styles to that specific component so they can be very broad if you don't have a whole lot of items in there, or you can write little selectors in that style will always be scoped to that specific component so you don't have to stress over a naming syntax or class syntax or anything like that. And then you can also have global styles as well. Right? Like, you've you've come up with a whole, color system and font sizing system, and those are all global properties.

Scott Tolinski

Rid. Yeah. And, normally, global because they're defined inside of just a a CSS file that's being loaded the straight up normal way that CSS files are loaded. So that stuff's being loaded outside of Svelte entirely as just a straight up. But if if you wanna style an element That is not in the current page that you're accessing. You can use this colon global, the class name, or colon global whatever to access that stuff.

Topic 16 00:51:13

Scoped CSS avoids naming collisions

Scott Tolinski

And now, you know, it It it can be cumbersome, but what I found is oftentimes, if you feel like you need to use global, it's it's kind of a code smell for me sometimes. Now Now granted it exists for a reason, and I do use Global myself, so it's not always a code smell. Because when I use when I use something, it's not a code smell.

Scott Tolinski

That's Isn't that how it works? Need. If I need a thing, that's not a problem. Yeah. It's a deed. But if, you know, if somebody else doesn't, hey. I don't know. Rid. But yeah. So it it allows you to be able to style things, but it's really great because, in CSS, I think the majority of problems people have with CSS is Scoping. I think scoping is a huge problem for new new CSS folks. And if the CSS you write in a component is always scoped to that component and not outside of that component, Hey. It makes CSS really easy in my opinion.

Scott Tolinski

You rely on CSS variables to do any of your sharing of values, and then, the rest just takes care of itself. Rid

Wes Bos

What should I say? One kind of, like, weird thing that I ran into was, I have these squiggles in the transcript that connect the different transcripts together, and they're SVG paths.

Wes Bos

So they're a little bit complex in terms of how big and sizing.

Scott Tolinski

They're pretty sweet. SVG

Wes Bos

is so hard. Like people complain about CSS and whatever, but Drawing a squiggly line with SVG is so complex.

Wes Bos

Yep. Rid. It's Matt. And, like, you have to account for the width of the stroke in where it starts and then divide by 2 and the radius of the rid. Yeah. Yeah. Although I have all these custom bezier values and whatnot.

Wes Bos

So one kind of cool thing, though, is If you want to pass JavaScript variables into CSS, you just stick it in a CSS variable, which is not a Svelte thing. It's rid. It'll literally work anywhere. But I love that where you could just go from JavaScript to CSS by passing it via a style attribute On the actual element itself. So you say style equals, in my case, I said dash dash stroke.

Wes Bos

I passed in the JavaScript value of stroke And then all of a sudden that stroke value is available to me in my CSS, and I can use it in calcs and offsets

Topic 17 00:53:24

Pass JS vars to CSS with CSS vars

Scott Tolinski

and whatnot. I find that being a Sorry. I find that being like a a new Svelte users or somebody coming from React or even styled components bane. They they say, how do I pass a prop into my CSS? And it's like, well, typically, you just use CSS variable.

Scott Tolinski

You don't have to worry about Props, you just assign a variable and use it as a variable. So that that's often one of those, like, learning curve things. Oh, you're just using CSS. You're not using JavaScript. And you can't do

Wes Bos

like if statements inside of your CSS or any weird stuff like that. If that's the case, then you Conditionally add or remove classes.

Wes Bos

But I found that like in my use cases of Styled Components, I don't use any of the JavaScript in the CSS things anymore now that we have

Scott Tolinski

CSS custom properties. Yeah, there's an endless amount of new CSS features that have removed the need JavaScript. Yeah. And

Wes Bos

CSS. Yeah. Also, the problem I had was that that squiggle is I had 2 of them. I had a squiggle at the top And then I squiggle at the bottom and the bottom one had to be vertically flipped.

Wes Bos

Right. And so I have a squiggle component.

Wes Bos

And then I gave a class of flipped to my Squiggly component, but the classes don't pass to the child component. So the way that you have to do it is you have to pass a prop to the child component and then in the child component, you have to check for that prop And then conditionally add and remove the class, which is like 2 steps. You know, I kind of wish that there was a way to just like Pass down a class. And the way Svelte Doc show you is passing a CLA Zed at like a class, and then they transform the class into class. So I thought that was a little bit funky.

Scott Tolinski

Yeah. That would be fun to set a class on a component, but then it's like, what would that class actually be set on? Right? You don't always have wrappers in your template because unlike React, you don't have to have a wrapper around your Yeah. Dom elements.

Wes Bos

Rid. Yeah, I know. Template. That's a good yeah. You're right. Because, like, what happens if your component is just a paragraph tag and a strong tag? Where does it go? Rid. Yeah, there's no parent. Yeah, good point. But like, couldn't you like spread class? There's probably a good reason because you're You're going from one to another and but,

Scott Tolinski

I don't know, some sort of, like, class prop. The the only reason I even think about this, rid. I thought about this exact thing before, and I think I've reasoned about it to be like, oh, no. Yeah. I am, that would be hard to do for various reasons. But, yeah, I I totally hear that. It would be nice to be able Do that kind of stuff. Overall,

Wes Bos

big fan of SvelteKit.

Topic 18 00:56:11

SvelteKit is enjoyable, mostly just JS

Wes Bos

I find it to be very enjoyable to work in. I find it to be 10% Svelte things, and the rest of it is just my regular JavaScript, which I think can be said for a lot of JavaScript frameworks. If you are stressing about things changing all the time, framework out there, and you're going to be able to get up and running in anything very quickly. So it's not like, oh, Should I learn React? Should I not? It it doesn't matter. Yeah.

Scott Tolinski

Yeah. And I'll, you know, I'll have the link to the current rid. Syntax v two code base in here so you can check out exactly what's going on and and how we're using SvelteKit in a real production way For the new syntax website, a lot of the fun stuff that we've talked about in this show, you can give it a little little peek. Now it's part of the show where we talk about sick picks that are picks. If you haven't heard this, they're they're just things that we like, podcasts, shows, products, anything that we like.

Scott Tolinski

I'm going to sick pick today a lock, a smart lock. I had a couple of locks, a couple of smart locks. They were the ultra lock, and one of them you know what? I don't know if this was just a A lemon or if my kids sprayed it with the hose and it stopped working or whatnot, but my one of them stopped working reliably. Rid. In a smart lock, you don't wanna have it working unreliably.

Scott Tolinski

So this thing was like it was like 2 years old, so I you know, I wasn't to the point where I felt like I could, rid You know, returning, it's a bummer that a smart lock would only last 2 years, but I took a chance on the brand. They were, like, a newer brand.

Scott Tolinski

And, again, I have no idea if it was just a, You know, a a bad product or That's a bad product. A lock should be able to get wet. Well, yes, I agree. Yeah. I meant, like, This is an individually bad item. Oh, yeah. Like a, a lemon. So I I decided to get a new smart lock for this begrudgingly, and I rid I went with this Aqara because I I tend to like Aqara products. It's one of these Chinese smart home manufacturers, but they tend to make good stuff. They're like a kind of like a rid A good choice if you if you like to be able to play nice with home assistant.

Scott Tolinski

But I got this Acara one because it works well with rid Apple Home and Apple Key so that now what I can do with this thing is simply tap my watch onto it to unlock it, Or I can tap my phone, or I can, send someone else a key, a temporary key. So I can send someone a key that lasts for a week, And then they can just tap their phone and open up my my office. So I don't have to worry about passcodes, which there is a passcode on it. There's a fingerprint on it and all that stuff. Rid But it it's a really nice smart lock, and, features wise, man, this thing really rocks. And I gotta say, like, My hands are full. I'm trying to get into my office. Just being able to nestle up my little watch next to the the lock and have it unlocked for me has been a a really nice little thing. So check it out, Aqara. They make good products as far as I'm concerned. It's

Wes Bos

a $190. That's cheaper than most smart locks out there, And most smart locks out there don't have Apple Watch integration.

Scott Tolinski

Yeah. Wow. Yeah. Most of them don't have this particular feature, which is why I went with this one's rid. Brand new. Yeah.

Wes Bos

You know, and I was waiting for some reviews on it. But, yeah, this is I want this one because, like, I always want the pin pad because the pin pad is Is is what everybody can use, but then, like, it's nice to have a fingerprint as well. But then if you have a Apple Watch, you can just tap it. It has everything

Scott Tolinski

For less than Yeah. It has everything. And like I said, you can send temporary cards. So, you know, my parents have iPhone. Yeah. I could send them a temporary card to their phones and tap your phone. They could access it if they need to.

Wes Bos

Tap your phone. Yeah. That's cool. We don't have a smart lock at our new house yet because the handle rid is built into the deadbolt and the thing,

Scott Tolinski

so we have to replace The front house yeah. Dude. Same thing? Our front lock is like that. Rid. Yeah. Same thing. And, you know, I've been looking at this type of thing, and Level makes one that is just the internal components that you could use with any external lock face. Oh, rid lock face. Oh, yeah. Yeah. So it's just

Wes Bos

but it does not work with the touch, the apple, the phone, the top ones open. Oh, yeah. So I'm gonna Get like a new a new door handle, but the old owners painted around it. So it's one of these things where you buy a new one, all of a sudden you're painting the door, you know?

Scott Tolinski

Rid. Yep. Yep.

Wes Bos

I know. So I probably should do that before it gets too cold to paint the door. Yeah.

Wes Bos

Alright. I'm going to sec pick replacement ear pads for your headphones. So I have had the Bose QC 30 fives for, rid Probably 6 or 7 years now, and they're fantastic headphones. But like all headphones that ear pads eventually wear out. You're wearing them 40 hours a week.

Wes Bos

So I have replaced the ear pads on mine, I think 2 or 3 times.

Wes Bos

And I just every time I get a new set, I'm like, I should have done this earlier. It's like a brand new pair of headphones. And I I got a set called Wicked Cushions last time, and they were I it was a mistake as I got black camo, and it's like a very subtle Oh, yeah. But then everybody thought they were just like from afar. It But he thought they were just, like, from afar, it just looked like they're appealing because it's just, like, subtle white splotches on them.

Wes Bos

So don't get black camo.

Wes Bos

I I ended up this time by getting floral, which I'm not sure if I like it or not yet, but it seems kind of cool.

Wes Bos

Rid But for, like Okay. You're cute. These are $12.

Wes Bos

For 12, $15, you can get a new set of ear cushions for your rid headphones. Highly recommend it. It's not just Bose. Any any set of headphones you have that has busted ear cushion. Stick. I love it. Thanks for tuning in. Catch you later.

Wes Bos

Rid Peace.

Scott Tolinski

Head on over to syntax.fm for a full archive of all of our shows.

Scott Tolinski

And don't forget to subscribe in your podcast player or drop a review if you like this show.

Share

Play / pause the audio
Minimize / expand the player
Mute / unmute the audio
Seek backward 30 seconds
Seek forward 30 seconds
Increase playback rate
Decrease playback rate
Show / hide this window