Episode 418

LH, RLH, Shadow DOM, Developer Experience, and RUM

We read some blogs and have some questions of our own: LH vs RLH? What about styling the shadow DOM with CSS shadow parts? Should you focus your work on what's loaded in your brain already? What is the Developer Experience? RUM and making decisions with or without data.

Tags

, , , , , ,

Chris Coyier and Dave Rupert

This episode is with just Chris & Dave, ShopTalk Show's hosts. Chris is the co-founder of CodePen and creator of CSS-Tricks, and Dave is lead developer at Paravel.

Audio Player

Time Jump Links
  • 01:31 LH vs RLH
  • 07:55 Sponsor: Hoefler & Co
  • 10:02 Styling the shadow dom with CSS shadow parts
  • 17:26 Working on what's loaded in your brain
  • 26:17 What is the Developer Experience DX?
  • 45:01 Sponsor: Billsby
  • 46:21 RUM
  • 58:37 Making decisions without data

Episode Sponsors

Job Mentions

Check out all jobs over on the Job Board. If you'd like to post a job, you can do that here, and have it mentioned on ShopTalk for a small additional charge.

Transcript

[Banjo music]

MANTRA: Just Build Websites!

Dave Rupert: Hey there, Shop-o-maniacs. You're listening to another episode of the ShopTalk Show.

[Applause]

Dave: I'm Dave--at home with the kids--Rupert and with me is Chris--in the booth--Coyier. Hey, Chris. How are you?

Chris Coyier: Darn right. I like our repetitive intro.

Dave: Hey.

Chris: It just keeps being true.

Dave: For these times until I have bandwidth to be more clever, this is what we've got.

Chris: [Laughter]

Dave: Going through the next 500 episodes, it's going to just be this. Chris, I've got something for you.

Chris: Tell me.

Dave: This pertains to you, even.

Chris: Does it?

Dave: Surprise! Remember last week, we did a lot of RSS, talking RSS?

Chris: Don't regret it.

Dave: I don't either. We're down -- I was at, like, 2,500 when I started and 1,200 or something when we talked last week, or whatever.

Chris: Yeah.

Dave: I'm down to now, well, it was 18 when we started the podcast. Now it's 21 unread.

Chris: Hey! Nice.

Dave: I must confess. There are about 230 unread CSS-Tricks articles in there. [Laughter]

Chris: Oh, gosh.

Dave: But I went down and I'm down to like eight. There's been enough going on that I have questions. I figured I could pop quiz you on your own blog, about your own blog. Is that okay?

Chris: Oh, sure. Yeah, I'll do the same to you, just with different questions.

Dave: Okay. Okay, so--

Chris: Yeah.

Dave: LH and RLH units.

Chris: Yeah. Root.

Dave: I'd never heard of this. This is new. This is line-height units, right?

Chris: Yeah, right, but now I'm forgetting the exact nature of it. It's root line-height, right, so it's basing the line-height not on--

Normally, everybody knows you do unitless line-height, right? Does everybody know that? If you don't know that, you should almost--

I think it's very few and far between that you ever set line-height with anything other than just a float. Like no unit, like 1.2, 1.1, 1.0, 0.8, 1.4, 1.8. That's almost always what your line-height number will be because it just means it's a multiple of what's existingly there, right? Root line-height is similar. It's just like a REM in that it's based on the root.

Dave: Root like root line-height or whatever, the root.

Chris: Is that right, though? Now I'm doubting myself.

Dave: Yeah, so a root is usually going to be 16 pixels. In theory, it could be user set and defined, or if a browser came out at 12 pixels or something. I don't know what it is.

00:03:02

Chris: But the thing is, you don't use the LH unit to set the line-height. That's too weirdly self-referential.

Dave: Yeah.

Chris: You use the LH unit for something else. The something else is probably something that matters a lot to inline text. What's really cool about this is that a button with a login next to it. I'm looking at Zoom right now and they've got them all over. There's a button in the upper right of my Zoom that says, "Gallery View," and it has an icon next to it. I can tell that whoever set -- I mean this probably was written in not Web technology but to get an icon and inline text next to each other often requires a little hand finicky--

Dave: Vertical line minus 1.2 pix.

Chris: Yeah, because you always do vertical-align middle and then it's not right.

Dave: No.

Chris: Then you've got to nudge it one or something.

Dave: Yeah.

Chris: What tends to work is display flex and a line item center or whatever.

Dave: Right. That does work.

Chris: That works but it doesn't size the icon at all. The sizing of it is still up to you. The big use case for these LH units are, why don't you size the icon next to inline text as one LH and height one LH? That means it's not going to -- that's different than 1M. 1M is going to be kind of like the cap height of the text next to it, which is okay, but it doesn't feel quite as nice as the cap height down to the descender.

Dave: Yeah. Yeah.

Chris: It's going to look way more centered.

Dave: Well, and there's a little bit of letting above the letter too, right?

Chris: The letter, yeah.

Dave: No, this was very -- I immediately saw and you have an example with the icons. I'm immediately, like, height one LH, width auto for icons for the rest of my life, if this lands. Do you know the browser support for this? Is this something happening?

Chris: Um, I don't, but we could look it up real quick. Credit to the icon idea to Sime. I took this from Web Platform News. He does a good job of covering new stuff and has a knack for seeing a new thing and knowing exactly kind of the good use case for it.

Dave: Oh, this is a nothing. Okay. Very cool. It's in nothing at all. [Laughter]

Chris: Sure.

Dave: But this is good. Anyway, I think -- yeah.

00:05:35

Chris: It's just in CSS4. We've talked about this before. I think it's fascinating, the dance of how things get into browsers. Sometimes, they get into browsers because Chrome goes, "This is going into browsers," and then it goes into browsers. [Laughter]

Dave: Yeah.

Chris: Sometimes things go in because a ragtag gang of developers puts in tons and tons of time and effort to convince all the powers that be to get it done. Then they slowly, eventually get it done.

Sometimes, things just -- you know the CSS working group has this idea for something that they think is good. It makes it into spec first and then makes it into browsers. Who knows how things--?j

I think that's good. When something starts at the spec level, I think it's probably going to be the strongest implementation, eventually, once it happens. This could be kind of cool. Thanks for bringing that up. I'm the one who published it and I was already like, "Uh…" so the RLH is less useful to me, I think. I can't think of a great use case for RLH, but LH is clearly useful.

Dave: LH is more like an M. It's based on the current line of text or whatever.

Chris: Yeah.

Dave: RLH.

Chris: Maybe you have some icons in the footer that you wanted to feel spiritually connected to the document that you would size by RLH or something so that they would scale as you increase the text size at the document level. That seems like metaphysical. [Laughter]

Dave: Yeah. Yeah. Yeah, it's like, I get it, I guess. Somebody is going to write a blog post why RLH is better than LH. [Laughter] Somebody will write this post.

00:07:21

Chris: Yeah. This seems Polyfillable too, by the way.

Dave: Right.

Chris: Doesn't it? At least at the JavaScript level.

Dave: Even just, yeah, post CSS thing. If you just set one M and one LH or, say, like width one M and width one LH. It'll be wrong in a lot of browsers, but it won't be super wrong, if that makes sense. That's kind of--

Chris: Oh, yeah. You would do the fallback technique.

Dave: Yeah.

Chris: Yeah. Yeah, you could handwrite that too. I would….

Dave: Yeah.

00:07:55

[Banjo music starts]

Chris: This episode of ShopTalk Show is brought to you in part by Hoefler&Co. Welcome, as a sponsor. I am stoked about it. They are my favorite type shop out there.

The URL is one of the best URLs you could possibly imagine, typography.com. Nothing is more critical to a good Web experience than just clear, clean, attractive typography, which is good news because it's not particularly hard on the Web anymore. Type on the Web has just gotten so good. It's affordable and easy to integrate. Hoefler&Co. fonts are the designers of some of the world's most beloved typefaces like Gotham and Knockout.

You know the CCS-Tricks logo? It's just Gotham rounded, all caps, CSS-TRICKS. [Laughter] That's it and I've used for so long, I feel like it's striking. I feel like it's just coming into its own, really. I really like it, still.

All the typography on CSS-Tricks is also Hoefler&Co. fonts: Ringside, Sentinel, Operator. Ringside is the title, Sentinel is the serif'd body copy, and I've only been using it now for--what's it been--three, four months, and I just love it. In fact, my own team, just yesterday, complimented me on the typography of the site. I've been tweaking it forever. It's finally really beautifully come into its own. It's something I take really serious. Operator mono is just my favorite monospace font for code. Really. It was one of the first ones out there that had the kind of slight cursive look for italics, which was just genius and has been copied many times since. I love it.

At typography.com, you'll find nothing but the highest quality fonts. They're screen optimized for the browser, complete families, deep character sets, clever features to help you solve design problems. Then, on the site itself, there are free tutorials and stuff to help you become a better typography. Oh, thank god. I could use it.

Download their fonts to self-host them or it's $99 a year to get a cloud typography subscription, which lets you use the entire library for $99 a year. You get 15% off that if you use coupon code SHOPTALK at checkout. Just one word, SHOPTALK at checkout. Typography.com/shoptalk gets you that deal. Incredible deal. Incredible fonts. Thank you for the sponsorship. Love it.

[Banjo music stops]

00:10:25

Dave: This -- okay, there's a post by Ollie Williams. A shoutout to Ollie. Styling the Shadow DOM with CSS Shadow Parts.

Chris: Hmm. I have mixed feelings on this. Yeah.

Dave: See, I wanted to bring this up. I know Ollie specifically mentions style components or--what's your favorite?--CSS Modules where it makes computer-generated hash name.

Chris: I do like CSS Modules.

Dave: To just, basically, this is my scoping technique, computer-generated classes.

Chris: Sure. Yep.

Dave: But there's this idea of the Shadow DOM where you get encapsulated styles in your Web components. If I say my-element, I can write a style block inside of that that is only going to be used by that style block. In fact--

Chris: Yeah, the style doesn't leak out. It's a style encapsulation, which is a huge thing that Web components can do that nothing else can do unless they're doing it artificially.

Dave: It has a boundary and says no styles in or out, basically. Right?

Chris: In or out.

Dave: No styles in. No styles out. It's like an island on your Web page. This part thing is, basically, you can write whatever.

Chris: You can reach in. Yeah.

Dave: You can reach in. It's almost like a class syntax. It'd be like div part equals box spaced thing is the example you have. It's almost like a class syntax but you could say example component colon colon part parentheses box background color pink. That's the example you use.

Chris: Did I? Is it Ollie?

Dave: Or Ollie, yeah.

Chris: Oh, I see. Yeah.

Dave: It's basically like styling the box part pink.

Chris: Well, let's say Dave Rupert made a Dave Rupert Web component that had an H1 in it like a hero.

Dave: Mm-hmm.

Chris: You could put the part as he H1, opening up the styling capability just to that H1.

Dave: Yeah.

Chris: It says, like, I am intentionally opening a portal of styling just to this H1 via a name. It's like an intentional API for styling. I guess the controversial part, to me, is that that's so weirdly limited. There's no -- you don't get nesting then. I can't say the part if the parent component and then I can scope from there and reach in and style children of it. No, no, no. It's just the thing that you attach the part to.

Dave: Okay.

Chris: Which to me is a little antithetical to CSS. That's weird to me.

Dave: Because you destroy the cascade within that.

Chris: Yeah.

Dave: It's only one element. Yeah.

Chris: Even a basic hero unit is going to have five things in there, probably.

Dave: Yeah.

Chris: You've got to have five named parts with no namespacing or anything. Weird.

Dave: Yeah. No, I just was kind of thinking, like, we have this Web component we're using on the ShopTalk site for our audio player. A little bit of work has gone into it. It would be cool if we open-sourced that or put that up somewhere, whatever. But the thing is, all the styling is done inside the component and I just sort of, like--

Chris: Yeah.

Dave: I was thinking about, like, not everyone wants their audio player to look like our audio player, so how could I offer styling? Maybe this is a way through the part syntax.

Chris: Yeah.

Dave: But I guess my question is, A) can I use it? B) Is this good? I guess this is just what we have.

Chris: Well, you know what another way to do this is? This is fascinating to me, too, is that CSS custom properties penetrate Shadow DOM. They go straight through it. Another way to set it up would be to pick a bunch of custom properties. Style everything with custom properties and then just document it. Say, "These are the custom properties I use. If you want to set it or if you want to override something, just set these CSS custom properties on the parent element and they'll pop right through that Shadow DOM and be used."

Dave: That's good for -- well, that's good for, like -- hmm. Okay.

Chris: It's the same problem, though.

Dave: Yeah.

Chris: You can't -- now you're setting something really microscopic. You're not saying, "Here's just the name of a part." Now, because you have the name of the part, you can set the font size, the color, the background. It's unlimited to what you can style. You can't. It won't cascade, but at least you don't have to say, "You can just set the color. That's the only thing I'm allowing," because you'd be like, "Oh, well, I want to set the color, but I also want to pull in the letter spacing."

Dave: Mm-hmm.

Chris: Dave didn't set up a letter-spacing variable, so I guess I'm just poop out of luck.

Dave: Yeah. I was going to say layout and stuff like that, you don't get to change. You're just stuck with the variables it offers. Yeah.

Chris: Right. Right, so part might be better. You're right. Say, this is the parent part. This is the play button part. This is the slider part. Just say these are all the parts. If you want to change it, style the parts.

Dave: Right…. Yeah. Yeah.

Chris: You're right. That is a little better.

Dave: I don't know, though. It was all just very interesting to me, just this idea of the part. I had heard musings that it was a thing being built, but I hadn't seen it in action, so this is kind of neat. I don't know. It's neat that that's out.

00:16:21

Chris: Also, doesn't it hang out with theme? I think it hangs out with theme, but I don't understand theme as much.

Dave: Yeah, I don't know.

Chris: It's ::theme is what I'm talking about. Well, let's just leave that hanging then. Somebody, write in and tell us why theme is cool or if it's dead or what.

Dave: Write a ::theme post. [Laughter]

Chris: Styling of Web components, though, is a -- [mind blown] that's a thing. It's a thing.

You know what? Here's another thing to know about it, though, is, just because you use a Web component doesn't mean that you absolutely have to do this no in, no out thing. You can just be like, "Nah, I don't care about that," and just have the global styling affect it.

Dave: Mm-hmm.

Chris: You don't have to make a Shadow DOM like that.

Dave: Yeah, I guess you can have an open or closed DOM, basically, right?

Chris: Yeah. I forget. But there's a setting where you set it open or closed. That's not the thing that does it, I think.

Dave: Oh.

Chris: I forget how this works.

Dave: Now I'm confused. Yeah.

Chris: It's not loaded into my brain, which is an interesting concept by itself. Not to -- maybe we're done with that anyway. Do you have--?

This is a big thing at Code-Pen when we're like, if we're working on something, the way we talk about it is like, "Okay, well, we're in there. All of us have this loaded in our brain anyway. Let's do what we need to do in there," because it's a little hard to jump context. If you're in database mode and you're munging data, moving it around, and stuff, and you know the next project two weeks from now also has data munging stuff going on, it's almost like you should do it all at the same time.

Dave: Yeah.

Chris: If you're big time in CSS mode, just stay in CSS mode for a minute because it's hard to change context. You've got to reload everything into your brain.

Dave: I've been on icons for, like, a month. I don't know.

[Laughter]

Dave: It was like somebody wanted an icon fixed. Then it was like okay, or the sizing was all kind of willy-nilly. Just enough variance it was like, "Let's tighten that up." Okay. Go through. Tighten it up. Okay. Now we go through an accessibility review. Some of the icons at small sizes absolutely fail, so we have to go and figure out a banned list or a deny list for all these icons. Then somebody shows up and says, "Hey, I have 200 new icons." It's like, okay, cool. [Laughter] What do I do?

Chris: Mm-hmm.

Dave: Literally, like yesterday, it was sitting through a spreadsheet. I just was like, "I've got to do this all in one day, in one shot because if I show up tomorrow and I'm halfway through a spreadsheet, I've lost it. I've lost it all."

Chris: Yeah.

Dave: I just sat--

00:19:11

Chris: That's interesting. They're short-term and long-term too, right? You're worried about losing it even after a day. Isn't there another version, too, where you're like, after a week or a month, everything related to icons is just going to be totally disposed in your mind. [Laughter]

Dave: Oh, all the time. I've learned React probably five times.

[Laughter]

Dave: Vue is the same thing, three or four times. It's mostly because I'm not using it day-to-day.

Chris: Yeah.

Dave: Now I have weekly exposure to a Vue project I'm noodling on but it's not my primary thing. I can be at least conversational in Vue, if that makes sense.

Chris: Yeah.

Dave: Exactly like the language stuff, like Tom Preston-Warner was talking about. If you don't practice it, you just don't; you just don't get it. Yeah, I feel like every time I open a React project it's like all my knowledge is lost or whatever.

Chris: Yeah. I mean I have an active React project, but I haven't been doing a lot of that. For weeks, I've been doing more node stuff in relation to some WordPress stuff. That's kind of loaded into my brain. If I had to jump over to do heavy React work I'd be like [loud exhale], you know. Almost like I don't want to until I can spend at least a couple of days in there. You know?

Dave: Yeah. Back in the day, we used to have, like, it cost $5,000 to open Flash or whatever fee.

[Laughter]

Dave: I don't even know if that's true, but we had contemplated having a Flash fee to open Flash because we were doing so much Web stuff. If you showed up and were like, "I want a new doodad in Flash for my Flash site, we'd have to be like, "Oh, my god. I have to reinstall it." That's how bad it is. Or update all of Adobe at this point, you know.

We at least contemplated a Flash fee because it's a different paradigm at some point or different enough that you're going to lose some skills. Web components probably falls into that too. I don't use them enough. I'm a big fan. I'm an advocate for them, but I don't--

Chris: It's smart to do it at the business level to know that you and your employees are going to have a hard time doing a huge context shift to a new technology, so you're going to charge for that.

Dave: Mm-hmm.

Chris: It's really going to pull their brain into a weird place. Just like early in my thinking about this, but I think there's that. There's dealing with yourself and your employees. Then kind of at a micro level too, how you manage your day. If you accidentally do too much context switching, you're going to be less productive. Being aware of that and not doing context shifting on purpose because you already have stuff loaded into your brain, leave it in your brain.

00:22:11

Dave: Yeah. Sophie Shephard has a really good blog post on this. It was "The Road to Burnout is Paved with Context Switching."

Chris: Mm-hmm. That's great.

Dave: It hit me because I was wanting to write a similar post. She's in GitHub management. She does management, front-end engineering management, I think at GitHub. Had switched over to that but she was finding if she was doing a one-on-one, then a big team meeting, and then a this and that, she just was losing the week or losing a foothold on everything.

Her thing was more, "I'm going to set up these days like Mondays for thinking and planning, Tuesdays for communicating and one-on-one, and Wednesdays are for helping and coaching. On Thursdays, we're kind of hodgepodge," but she's checked off most of the boxes by this point, so she can kind of figure out what's going on. Then Fridays was design and building, so she can just kind of keep her skills sharp.

Anyway, I don't know if that sustained. That's two, three years ago now. That post was just, yeah, if you switch context and going from A to B to Z, you burn out. It hurts.

Chris: To me, I'm just thinking it just makes you worse at what you're doing. I'm more into the idea of harnessing, doing a good job. If you're there, just stay there for a minute. That's because I have some privilege of being able to do that sometimes. My day isn't as filled with meetings and responsibilities as everybody else.

Dave: You know how I think about it? Have you ever surfed, Chris? You seem like somebody who has surfed.

Chris: I literally never once. Sorry.

Dave: You never surfed? Okay. Well, when you're surfing, I think when you first start or whatever -- I'm not a pro surfer by any means. I popped up once. [Laughter]

Chris: [Laughter]

Dave: When you surf, if you paddle for every wave, you just get destroyed because you're like, paddle-paddle-paddle. Get over the break. You're exhausted. Then you see a wave and you're just like, "Oh, I'm going to hit it," and then you just wipe out. Then you have to paddle over the break again.

Chris: Yeah.

Dave: Then you're like paddle, paddle, paddle to get on a wave. If you try to ride every wave, you just get obliterated. You hurt and out of breath and it's dangerous, to be honest, because you could literally drown.

You see the good surfers. They just effortlessly paddle out. They figured out how to do that. They sit out there until a big wave comes. They know how to find a big wave. Then they say, "Yeah, I'll ride that big wave because that big wave is worth my time."

Chris: Mm-hmm.

Dave: They don't waste energy. All energy is put towards good surfing.

Chris: This is the best metaphor ever.

Dave: Isn't it?

Chris: Do you think surfers naturally extend that to their business lives as well?

Dave: [Laughter] Running a skateboard shop and smoking weed. I think, yeah, they do. The minimum effort, man. Nah, I don't know.

Chris: Yeah. [Laughter]

Dave: I think I wonder, too. I don't know how it translates. I think it does translate into that lifestyle. You're just kind of like, "I'm just going to do the minimum so I can do the fun part. Optimize my life for the fun part or the part I'm good at."

Chris: Yeah. That reminds me of Alex Sexton's don't caffeinate a low but caffeinate when you're already productive, if you can.

Dave: Yeah.

Chris: Ride those highs instead of fight the lows. Yeah, I love that. Okay, cool. Do you want to do one more here?

00:26:21

Dave: I've got another one for you.

Chris: Yeah.

Dave: This was a big one. You recently posted an art-directed post called "What is developer experience?"

Chris: Hmm.

Dave: We've sort of talked about this on the show before but I think you really, like--

Chris: Probably.

Dave: --kind of rounded out the whole conversation.

Chris: Well, to me, it came from one place. It came from the positivity of that term versus the negativity of that term. The positivity is so obvious. We're all developers and we all care about our experience and probably spend a good part of our lives trying to optimize that experience. Just think of posting a tweet showing off some code and having somebody be like, "What's the font? What's the syntax highlighting?" The tip is one thing but they're almost concerned more about, "Ooh, that looks beautiful. I want to have a beautiful coding environment too. Please give me those tips." That's what's on their mind.

Sometimes it's annoying, but I think there's some interesting subtext there, which is, people are so into getting their code editor beautiful and learning about the little tools that other developers use and little shortcuts and little stuff. That to me is kind of the positive aspect to it.

What I mean by the negative aspect of it is, you know, largely part of the bigger client-side JavaScript conversation, although this can apply to any tech. This is what I know is that it gets dunked on. People think of one kind of good DX is having a lot at our fingertips in client-side JavaScript and feeling very powerful there as a developer at the cost of how much JavaScript it's shipping to our users.

It's kind of like not caring about UX by caring too much about DX. That's the negative connotation that gets thrown around a lot. I was like, "Wow, that's funny how it's the same term being used in very positive ways and very negative ways at the same time."

Dave: Yeah, okay, so DX can mean the fonts, the API.

Chris: Yeah.

Dave: Or having a CLI, you talked about.

Chris: Right.

Dave: That for a lot of developers is a huge developer experience bonus. I don't have to go to a website to configure this. This is great. Then there are often DXs that negative offset.

Chris: The highest level version of this is, React is bad for the world because it's only for developers, not for users.

Dave: Mm-hmm.

Chris: You gave yourself good DX at the cost of shipping this library. I know that that has no nuance in that statement. That's not Chris Coyier saying that. I think there is a lot more to this because the easy response is like, "Yeah, but it helps us build really fast. It makes us build these really -- it means we can hire really easily and have people to maintain the site. It means there are less bugs on the site. It means once the page is loaded, it's really snappy and fast to jump around."

There are all these positives that come from it. I'm just saying the easy ax to throw at that is just that, no, that's for you, not for them.

Dave: Yep. No, I mean I do think there are inherent tradeoffs there. But it's sort of like -- I wrote about this a little bit recently, but not React specifically. It's like, what's being handed off to the user a cost or a benefit. As code users, it's very much like, "Oh, yeah. This is very much a benefit." Or managers, that's very much a benefit. But what's being handed off to the end-user, is that a benefit?

I don't know that it's always cut and dry but I think there are tradeoffs there. I think the first question I asked Developit, who does Preact, was just, "How is it so small?"

Chris: Mm-hmm.

Dave: React plus ReactDOM is like 100K or something like that. It's probably gone down in size of gzips up nicely, but it was like 100K. Then Jason strolls in and is like, "Well, here's Preact. It's only 3K ever." I'm just like, "How?" you know. I think there are small -- a lot of code golfing or whatever that goes on. But then even--

He just was like, "We are Web-native, so we don't have this abstraction for input events." That's a big gain there because he's just like, "We're not catering to developers who want to go to React native or whatever, so we've saved a lot of kilobytes doing that."

But then you talk to people who have tried Preact on projects. If you have a successful Preact project, that is awesome. I have heard, literally heard this week, stories where people were like, "Oh, we went Preact and then we had to back out because the community of plugins, the ecosystem, the React ecosystem, the Preact ecosystem, I guess, isn't as strong as the React ecosystem."

Chris: Yeah. The second you have one problem, it's like, "I don't know how to solve this," but it seems trivial if I just switch to the other library. That happens enough times and you're like, "Screw it. I'm just going to do it."

Dave: Yeah.

Chris: "I don't care anymore. I need to solve my problems, not theoretical problems."

Dave: Yeah, but I don't know. I always -- I'm hopefully. There's one thing people try to strawman. They're like, "Oh, these, when you measure, talk about the performance hit of React, you're not considering the 300,000-page clicks they're going to do." That there, they're going to save.

Chris: Which may be true.

Dave: Which may be true, but I don't think you can -- unless you have a plan to measure that, you're just guessing. You know?

Chris: Right. Right. Right.

Dave: You're straw-manning and you've come up with a theoretical benefit.

Chris: Yeah, it feels good to say…. Right.

Dave: Yeah. Then I know some browser people are working on this over multiple pages sort of perspective. I've heard some musings but what's interesting is, you're like, "Well, what about over multiple things?" You're like, "So, that's better and I don't even need to listen to this stuff."

That's okay, but you're still guessing. Unless you have a metric that you're talking about there, you're just guessing. No one is measuring that. I don't know. [Laughter] That's all to say, I hope we're talking about real things, not fake things. That's what gets me is the theoretical hit to people or something.

For me, the tradeoff, React does have main thread performance issues. It kind of jams up the main thread, especially if you have a lot of components rendering. I think it's based on the number of components, basically, and the up-days it has to make.

00:34:23

Chris: I have an interesting waterfall if you look at CodePen, which is more and more React powered. Even the homepage, nothing will render at all until React has done its job. I looked at an interesting waterfall chart just yesterday where, at about one second -- this is synthetic. This is using a performance tool to look at this. At one second, the CSS has downloaded enough to paint. It paints and what you'll see in the waterfall is just gray because that's the background of CodePen. Then at 1.7 seconds, you see the stuff pile onto the page. That's because React has ran. It's got its data and it's decided to render.

There are 700 milliseconds there of time and, at the same time, you know how in these performance charts, dude, you can see other stuff happening, like, what's the CPU doing? Well, the CPU is pretty chill in the first second. Then in that 700 milliseconds before the gray and the rest, the CPU is freaking out. It's doing all kinds of stuff. It's main thread happy because it's just got a lot of work to do.

I don't know. That's just the nature of the technology. There's not much I can do about that.

Dave: Yeah.

Chris: But it is interesting to pair those together. That's what you're talking about. It sure as hell makes the browser busy while it's doing what it's doing.

Dave: Yeah. I don't want to throw anyone under the bus. I was on somebody's blog. Not either of us. I was on somebody's blog today. I was on a post and I clicked to go to another one of their posts and my browser just locked up but I could see a little scrolly happening. I just assume it's in some kind of JS framework.

I just was like, man, how--? This is a blog. I'm going from text to text. When I'd hit the back button, it would just freeze up again. I just was like, how is it getting this jammed up, an iPad Pro, which is a pretty high-end device? It's very interesting. These problems are all interesting.

The post I mentioned, I wrote, it's just about tradeoffs. Nothing is free. At a certain point, you've reduced all the complexity. You've taken out all the images, GIFs. You've fixed as much as you can. Eventually, you're going to hit an irreducible amount of complexity.

The examples I use in the post were managing scoping styles. You can either do that in HTML or with BEM or something. You can do that with CSS and JS. You can use a utility CSS library. But you're going to start passing bloat around somewhere or the problems. You go to Utility CSS to manage style scoping--

Chris: I love this.

Dave: --well, now your HTML is jammed up. You know?

Chris: Yeah.

Dave: Now your HTML is hard to work with. You use BEM. Well, now your CSS just looks like a phonebook. Then you go over to CSS and JS. That's cool but now your JavaScript is all jammed up. You're putting a lot into that thing. That may work for you. I'm not--

Chris: None of these are free. Wherever you put the complexity, it's going somewhere.

Dave: It goes somewhere. Even spacer components, which are a big, popular thing. Oh, man, we hate spacer components. That's inaccessible or something. Okay, cool. But they add chunks of spacing pretty efficiently. Or you can style, add to the parent, but now your parent has to be responsible for every single layout that could ever show up ever imagined. Or you add padding-top and padding-bottom classes to everything. Well, now every component needs to accept that. If you're putting it in a CMS or something, now every block in your CMS needs a padding component or padding option.

Chris: Mm-hmm.

Dave: The complexity lives somewhere. At some point, you're not going to escape it. The thing I'm saying in the post is, we don't exactly make rational decisions. We make it based on the experience we just had.

Oh, I just worked with utility libraries. That sucked. I'm not doing that again. I'm doing CSS and JS now.

Chris: Mm-hmm. Sure.

00:38:54

Dave: But I don't know. The complexity has to live somewhere. I feel like a lot of these problems, the complexity is going to live somewhere. We have a few tools. Last week, we talked about using the edge. That's something that doesn't really impact the user. It adds complexity to your life as a developer because now you have the client, the server, and then the edge now kind of doing things. That adds complexity to your organization's life, but the user getting a free trial popup banner if they don't have a cookie, that would be a perfect place for the edge because the user doesn't have to wait for it. The server doesn't have to think about it all too much. But the edge could just slip that in there.

Chris: Yeah. it's just moving complexity somewhere else. Hopefully, where you've moved it, you're comfortable with. You feel powerful there. The tradeoffs are good. There's still a lot to measure about this. It's not just like, "Eh, it doesn't matter. The complexity goes somewhere, so just pick one."

Dave: Mm-hmm.

Chris: What you pick still matters.

Dave: Yeah, and that's the second part of Tesler's Law, which is this complexity can't be reduced at a certain point. But the question is, who inherits it and is it a cost or a benefit or a value that's passed on to the user? That doesn't always -- you know, it's not always clear but then the other question I would ask is, is this a cost or a benefit? What about people who aren't wealthy or able-bodied?

Chris: Yeah.

Dave: What about those people? You have to consider those people in your metric.

Just this week, Twitter blasted out a new feature, dude. Audible tweets, man. Now you can mouth blog on Twitter, which just sounds like a nightmare. They've obviously never used Xbox Live video game chat. [Laughter] This is just going to go terrible.

But the big thing is there are no captions, so deaf users are just left out. Just like blind users were left out with no captioning of GIFs and no captions in general. Awesome, you were able to move fast and you made this thing that made these little videos of audio and stuff. Awesome, you made that. But the cost -- a cost was passed onto non-hearing users. Bummer, right?

Chris: Well, the extra subtext was some of the people kind of doubling down saying, "Yeah, of course, we want to do that. We're just going to do it later because," what, do you not want this until 2022? It just kind of was like a little incredulous, like, "We ship and then we put accessibility in. That's how the Web works." [Laughter]

Dave: Yeah.

Chris: You know a lot of accessibility are people are like, "No, you make it accessible. Then you ship it," or you think about accessibility from the beginning. Of course, speaking of dancing, this is the dance we dance. We will dance it forever.

Dave: Well, and I think there are good ways and bad ways to play it. Even saying, "Unlocking captions is one of our top priorities," is way better than, "Hey, I've got eight or nine things I want to do here, pal. I've got a lot of features I want to roll out, dude."

Chris: Yeah. Yeah.

Dave: There are different ways to approach it.

Chris: That's kind of funny. The one I saw was just Cassidy screaming into it and then saying "poop" at the end, which is, like, shut it down. That's the best one.

Dave: Yes.

Chris: [Cough] But then, some of her replies said that you can go to studio.twitter.com and then upload some kind of captions file to the thing and add it. There's some kind of way to do captions but it's just a little obtuse, perhaps.

Dave: Wow. That's interesting.

Chris: Just for journalistic integrity here, not that we're journalists.

Dave: Oh, yeah. Okay.

Chris: We'll try.

Dave: Well, that's very interesting. They do have a video studio or whatever that they can add. Okay.

00:43:28

Chris: Yeah, and then there's an article on CSS-Tricks about this. I forget. That's why I publish blog posts because then it doesn't matter if I forget. There is a file format for captions for audio and video.

Dave: VTT, right?

Chris: Yeah, I don't know, but it's XML-like, I think, and it has time stamps and what's happening at what part. I think in the case of video, it will actually literally display the captions in the video. I don't know if you all turn this on at home, but my wife Miranda likes to have the captions on all the time, so it's just the way it is.

Dave: Captions all the time.

Chris: Yeah.

Dave: Yeah.

Chris: It's just the way it is.

Dave: Yeah. I don't know why, but we do. Yeah.

Chris: I don't know why exactly either, but I've learned to -- at first, it was a little annoying and now it's just the way it is. I don't mind it because if you get a little distracted, you get a little more nuance out of it, you know, I think.

Dave: Mm-hmm. I think, with kids, it was like, "Hey, if we wanted to watch a grownup show, we can't watch it at loud volume because the grownup show has loud murders at loud volume. [Laughter]

Chris: Yeah. [Laughter]

Dave: We needed a little bit more chill. But when you do chill and then the AC kicks on, you're just like, "I don't know what's happening."

Chris: Mm-hmm.

Dave: I think subtitles bridge the gap there.

Chris: Yeah. I've heard this is way more popular. Most people have captions on these days, which kind of blows my mind.

Dave: My kids insist on it. Otis does because he's starting to read and--I don't know--he'll hear a word and want to know how it's spelled.

Chris: Yeah.

Dave: That's the easy way for them.

00:45:08

[Banjo music starts]

Chris Enns: This episode of ShopTalk Show is brought to you by Billsby. Whatever your subscription business, rely on Billsby for easy and accurate reoccurring billing. It's the most powerful, customizable, and easy to integrate subscription billing software used by hundreds of companies worldwide to simplify revenue operations.

Billsby is a simple, affordable way to handle reoccurring billing for your Web application. Don't have your developers do noncore stuff like billing. Let them focus on your core product. Billsby handles invoices, dunning, replacement cards, self-service tools, and more for you. You don't even need to monitor usage, as there's a real-time usage API for billable allowances.

You can get started with Billsby and start generating revenue in minutes with drop-in checkout and account management. It's dramatically easier to scale thanks to features like real-time usage APIs for billing allowances, feature tags to manage access control, and a simple hierarchy of products, plans, and cycles.

ShopTalk listeners can sign up with a $50,000 free trial, so you can make the first $50,000 of revenue without paying for Billsby. There's no credit card required. Afterward, it's only 0.8% of revenue with no minimum fees. Visit billsby.com/shoptalk to find out more. That's B-I-L-L-S-B-Y.com/shoptalk. Our thanks to Billsby for sponsoring this episode of ShopTalk Show.

[Banjo music stops]

00:46:34

Chris: Well, we were talking about metrics or performance stuff for a minute, and I have some things that I think would be interesting to talk about there, if that's okay.

Dave: Sure.

Chris: It was either last week or I don't know. It all blends together. We talked about Google's new initiative here, which is a big deal because they're not only saying, "Hey, this is a new initiative for us," but these are the ones that are going to be tied to your SEO, so get used to it. They're called Web Core Vitals and there are three metrics: LCP (Largest Contentful Paint), FID (First Input Delay), CLS (Cumulative Layout Shift).

Notice, these aren't size metrics. These aren't number of request metrics. These are an evolution of how we think about performance. They are like, "Oh, yeah? How long did it take for the thing that matters on the page to paint?" Probably your hero image. They got this from SpeedCurve's hero idea.

FID is like, "How long until I can type something, until I can input stuff on the page?" If the main thread is locked up and I can't do stuff, I need to know that. How long until that delay?

Cumulative Layout Shift is like, "Does your page move all around because you're a jack-wagon and load a bunch of ads and didn't account for the space for them and the page moves all around and that's awful and everybody hates it. Yeah, well, you're going to get a bad score then and that's going to hurt your SEO.

It's just those three vitals. What I think is really interesting about these is that one in three, LCP and CLS, you can do synthetically. You can just load the page, watch it, and see how long it takes for the largest area to paint, see if there's any shifting while it's loading, and get a metric and you know it.

First Input Delay, you can't. First Input Delay, you need some JavaScript on the page that can do stuff and watch for that delay so it knows what's going on.

That brings up this kind of interesting idea that's a little new to me in my thinking about Web performance is that some performance can be done synthetically, synthetically meaning like Lighthouse runs, it gets some metrics, and it shows them to you. Some performance monitoring cannot. It needs to be monitored in real life. They call that RUM. Have you heard of that?

Dave: Yeah.

Chris: Real User Monitor.

Dave: Real User Metric. Yeah, monitoring.

00:49:03

Chris: Metrics or monitoring or something. That requires you having some JavaScript injected onto your page so that it can measure stuff for the purpose of analytics watching. It tries to be chill about it, deferred, async, being very -- not trying to affect the performance while measuring the performance. I don't know how perfectly it does that, but I think it's pretty darn good. With that on the page, then you can measure First Input Delay.

This brings up a couple of interesting things. It's not just those but think about Largest Contentful Paint. That's just algorithmically trying to figure out, "Hey, what's the most important thing on this page?" and measuring it. Well, that's nice because when Google does this and says it affects your SEO, they have to do it algorithmically. They have to just assume that the world is not going to help them and they're just getting these metrics very generically.

LCP maybe doesn't matter as much to me and you measuring one individual website. What I think is cool about analytics, and I was just talking with Mark at SpeedCurve about this, they have some tools for this that are really cool. You can put an attribute on an HTML element that says, "This is a big thing on the page that's important to me. This is my hero graphic. This is my editor page. This is my first tweet on the page. This is something that matters to my company. I want the measurement to not be LCP. I want it to be this fricken' image, this element."

Dave: Wow.

Chris: You just put the attribute on it and that's what it measures. That can be your performance metric.

There's another thing. You can fire off a JavaScript event that says, "Okay, the JavaScript is loaded. The most important thing in the JavaScript lifecycle of this page has now happened. Measure that. Measure how long it took for that to happen." That's awesome!

For us it would be like, "Okay. The editor is now ready to work," so we write one line of JavaScript that fires off that analytics event. Now our analytics aren't generic anymore. They're not just like, "Uh, measure synthetic everything." It's like, "How long did it take for that important thing to happen on my website?" I think we're talking about performance analytics. This is how you would think about other analytics on your website too. I don't care--

When you're integrating analytics on your website, you're expected to add events that matter. I bought a pizza. I uploaded an asset. I wrote a tweet. I liked a tweet. I uploaded a photo to Facebook. Those are events that happened. When you're using analytic software, you're expected to write a little JavaScript into your app that says, "That event happened. Please track it for me."

You can do a good job with that. The idea is to do it anonymously and carefully, but everybody does this. You track the events so you can make your software better, so you can know how people are using your software. That's expected in that type of analytics. But I like lifting up and using that same type of thinking for performance analytics too.

Don't just do everything generic. Just synthetically monitor my stuff. That's all I care about. Doing a little bit more effort and putting in these, "What painted and when? When is this JavaScript thing done and useful?" It requires very little effort and then gets you way better, more interesting analytics.

Dave: There's a lot you could do because I tend to just think about, okay, when is it painted and when is it usable? But there's stuff I don't know like, how long does my CSS take? How long does my Web fonts take?

Chris: Sure.

Dave: I think I had that post about why I added 33 seconds to do oopsy-doopsy on a Web font. Problems can arise and you don't really know it, but they happen. You move two things and now three things are broken. Yeah, I don't know. It'd be interesting to see.

I'd be curious to see how people are extending it. I see it very much in, like, when does the discovery or the most popular feed show up? When does the editor load? How quick can people enter code? When is the editor focused?

Chris: Doesn't seem obvious now that that's what you should be doing?

Dave: Yeah.

00:53:41

Chris: I feel like, yes, of course. It's kind of like the only analytics that matter, you know, after a while.

Dave: It's kind of like top tasks, not to get Jerry back on the show. But you know. It's like, what's the thing that matters? Just look at that. Pay attention to that.

Chris: Right. Now you have to care about Web Core Vitals too because it's SEO, so you kind of have to care about those.

Dave: Yeah.

Chris: But then beyond that, you should care about -- with your team, you should think about what matters. Say if you're a news website. Well, the thing that matters is how fast did the headline and the copy render?

Dave: Yeah.

Chris: Measure that, which is really easy because companies like SpeedCurve have made it tremendously easy. You put a fricken' HTML attribute on it. There you go. You're tracking it now.

Dave: Yeah.

Chris: Do that. I love that. I just love it. I think it's so interesting because I've been trapped in synthetic thinking forever. How many requests? How long, like, how big are the images? Are you optimizing the stuff? Is it cached? All stuff that matters, but they're red herrings, you know. They only matter because they affect the metrics that people actually care about, the perceived performance.

Dave: Yeah. Yeah, you can get kind of tied up in these fake or just misleading. If you want to do some research, McNamara fallacy is what it's called, but it's Robert McNamara. He was the Department of Defense, whatever that guy's name is. [Laughter] He's the director of the department.

Chris: Secretary of Defense?

Dave: Secretary of Defense during the Vietnam War. There you go. He was basically, like, looking purely at kill/death ratios. Are we killing -- which sounds terrible but that's what he was looking at. He was like, are we killing more bad guys than our guys are dying.

Chris: Yeah.

Dave: If we are, then we're winning. We're going to win. But he wasn't paying attention. There were a lot of things he couldn't see or couldn't measure, like he didn't understand that they were fighting for their homeland and they would do anything to protect their land and their freedom, which was Communism in this circumstance, you know, in the Vietnam War.

He had had success with data-driven stuff in WWII, but then, in the Vietnam War, he just kind of got blinded by his own data. Obviously, that didn't go well and a lot of people lost their lives - a tragic number of people. It's interesting.

Chris: In this thing, it would be like if you only cared about your JavaScript bundle size, you're kind of missing the forest for the trees.

00:56:43

Dave: Yeah. Let me see. McNamara fallacy, here it is.

Chris: I realize I just explained a metaphor with another metaphor.

Dave: Yeah.

Chris: Sorry.

Dave: The fallacy comes when Daniel Yankelovich--that sounds like a fake name--about corporate priorities, a study of new business demands. It basically is summed up as, the first step is to measure whatever can easily be measured, and that's in every business book. That's in Measure What Matters. [Laughter]

Chris: Yeah.

Dave: By John Doerr -- or whatever. This is okay as far as it goes. The second step is disregard what can't easily be measured or give it an arbitrary quantitative value. That's the synthetic stuff you're talking about. This is artificial and misleading.

The third step is to presume what can't be measured isn't really important. This is blindness. Again, back to the whole user DX experience. We don't really have a great way to measure DX or UX or whatever. If you just ignore those things, you're blind.

The fourth step is to say what can't easily be measured doesn't exist. If you can't measure it, it doesn't exist. That's suicide is what the McNamara fallacy says.

It's all very interesting and just the historical context, too, of this guy who had success following data in WWII and then did data in the Vietnam War and it failed him. He did not have the right metrics.

Chris: What's funny is he had one final. You always have to have one final metric. For him, it was winning the war or whatever. Hopefully, what you're measuring in all this stuff is in service of that, although, this is twisted, I realize. We can probably end with this because it's been a hot minute.

Dave: Yeah.

00:58:52

Chris: We just released a new feature at CodePen. This is really cool. You might even like it, Dave.

Dave: Uh-oh.

Chris: We've been working on our assets a bunch, so the assets feature has gotten a lot better on CodePen now, uploading assets and using them and stuff. That's been out for a little bit now. But let's say you've got an avatar of your face, Dave. But it's big. It's 2,000 pixels.

Dave: Oh, a big head.

Chris: Big deal. CodePen will take it. Drag and drop it onto CodePen, it'll upload, and you'll get it. It's gotten a lot better recently and you can crop it as you upload it. You can upload lots of stuff at once. There's some interesting stuff that happens.

Okay. Fine. It's uploaded now. You have a URL for it. We recently changed the URLs for them too in that it's a much nicer looking URL and we put a CDN in front of it, so now it'll faster and your Australian users, instead of it coming right out of a bucket that's in Oregon, it's on a global CDN, which is like, wow, took your time there, didn't you? Yeah, sorry about that.

Dave: [Laughter]

Chris: It's good. Then we can intercept the requests along the way and make sure they for sure, 100% of the time have the right core headers on them. The headers aren't cached, yadda-yadda. Text edits or text assets are easily editable, yadda-yadda. I'm giving this pitch.

Here's what just shipped yesterday is--

Dave: Oh, boy.

Chris: At the end of an image URL, like dave.jpeg, you can now put URL parameters to control the image. You've probably seen this before and Netlify offers it. Cloudflare offers it. Cloudinary offers it. At the end of the URL you just put ?width=200 and then it'll serve that image as 200 pixels.

Dave: Whoa! Nice.

Chris: You could say, format auto at the end of it and it'll just try to serve it in the best possible format, which is WebP. It'll try to. If you're in Safari, it will know that you're in Safari and it won't. It'll just serve it as whatever the original was.

You can crop it, kind of, because you can scale it and say, "Crop it in this particular way." You can rotate it. There are eight things it can do, or something like that. It's just through URL parameters. Okay?

Dave: Wow.

Chris: That's cool, right? We want to know. There are product decisions that go along with this that have to do with analytics and this kind of McNamara idea. Our final metric at CodePen is and always will be, can we get you to go pro? Can we get you to stay pro or even upgrade pro plans? I want you to be pro on CodePen. You get this feature if you're pro and you don't if you're not pro because you just don't have asset hosting at all.

Dave: Mm-hmm. Mm-hmm.

01:01:32

Chris: Okay. Fine. Then we were considering all this other stuff along with this feature. Here's another sub-feature of this. You're not just playing with the URL. We built a whole UI around this. You can drag sliders. You can turn on and off checkboxes and all this. It's manipulating the URL and showing the image of what's happening at once.

You click a button to rotate it. It shows you the rotated image. Then there's a button that just says, "Copy the URL." You've done it. You've manipulated the image. We've shown you a preview about it in real-time. We've also shown you how much more optimized it is than the original that you uploaded. It's really neat.

There's another button that says, "Save this as a new image." Then you click that and it reuploads it again to your bucket but with all those manipulations in place. Before this shipped, I was the captain CodePen dad who swooped and pooped on it. I was like, "You know what? Why do we even have this? It's so much cooler to use just the URL format because then you can manipulate it on the fly. Why would you want to save a new copy of the image?"

But you know what that way? That was me just being McNamara or whatever. I don't know that. I don't know how this -- I was just guessing that that's a good idea.

Dave: Yeah. You don't have the data, so you just say it's not important.

Chris: Yeah. Even if I wanted the data, where would I get the data? How could I possibly track this all the way up to, did I convince you to go pro and did you stay pro because of it? Even if I can track some usage data, that doesn't tell me that.

Somebody made up a good point. They were like, "Well, we also have storage." If you upload the image again, that's a new URL. In some kind of weird way, it gets you to stick around CodePen maybe a little more because it's all the more URLs you have that are different. It's not just this one graphic you need to move.

Maybe they're right. Maybe you will stick around more because you have more URLs that are hosted on CodePen. I didn't even think of that. I don't have any data anyway, so it's kind of, like, interesting, you know. My guess is not the thing that should inform whether we should have that feature or not. Even if we track it, the tracking is complicated. Just because somebody used one feature doesn't mean that it's necessarily going to make them a stronger pro user. It's just interesting.

Dave: No, it is. Well, and even just -- there might be data where you could figure out what core features pro users use. Okay, not a lot of people are duplicating or reuploading assets. But a lot of people are editing assets, or a lot of people are private Penning. I'm sure is a huge one.

Chris: Right.

Dave: That's 90% of my Pens. That might help your decisions in terms of like, "Oh, okay. We see the kind of features that people like. Private Pens are very popular. What are other private features we could develop, or something like that? I think there are a lot of--

I think data helps. Date informs. I think I've read about this recently. Data informs but it shouldn't drive the decision.

01:04:58

Chris: That's a good way to think about it. You should have the data, but it doesn't mean that you have to blindly follow it.

Dave: Yeah.

Chris: There's still a heaping helping of intuition involved.

Dave: There's a lot of, like, A/B test stuff. You could actually make it go down but I don't know. If you know you're shipping less code or something, you just know it's better or it gets you on a step to be better. I can't run your business, but--

Chris: I like your thinking there. No, I like it. I think that's smart. I think that's how we do it anyway. We try to get as much data as we can and then I don't think we've ever made a decision that was just like, "Well, the data says this so do it." For one thing, you're right about pro or privacy. That's the top seller in every metric: in usage, if you just ask people, if you interview people, all that stuff. We have ideas for it, but all these years later have we let that guide 100% of our development and said, "Oh, we're just going to make privacy better on CodePen"? No, we haven't. So, whoops. [Laughter]

Dave: But maybe it's possible. This is where the research and all that. I mean it's possible the feature is perfect as it. It's just the right amount of privacy or it's just the right amount of you know.

Chris: Yeah, that's true too. Why mess with it if it's working well? [Laughter]

Dave: Maybe there's just something. Maybe there's one more brick to unlock or something when you start untangling that. Have you thought about audio CodePens?

[Record scratching]

Chris: ShopTalkShow.com.

More episodes!