Adam Wathan, Creator of Tailwind CSS

Ben Orenstein:

What's up, dude?

Adam Wathan:

Oh, you know, just hanging out, doing a podcast, doing a podcast.

Ben Orenstein:

Yeah. I just recorded with Derrick Reimer, few days ago, and I'm recording with you. So, like, my, streak of recording with people I've hosted other things with continues.

Adam Wathan:

Nice.

Ben Orenstein:

Yeah. That's cool. So sounds like what podcast is this really?

Adam Wathan:

Yeah. It's, yeah, it it feels like you're not putting in a lot of effort to find guests is what it looks like.

Ben Orenstein:

We call that tapping the network, actually. It's a very savvy business move.

Adam Wathan:

Yes. Yes. Yes. Instead of something we like, sorry, we don't have a Windows version. It's like, no.

Adam Wathan:

This is exclusively for Mac OS.

Ben Orenstein:

Yeah. It's all about the positioning.

Adam Wathan:

It's all about the spin.

Ben Orenstein:

Yeah. Exactly. And we're we have a Windows version, by the way. I think we're gonna launch Tuple Windows clients open open. Just like done out of beta.

Ben Orenstein:

Let's go. Pretty soon.

Adam Wathan:

Amazing.

Ben Orenstein:

Yeah. It's pretty cool.

Adam Wathan:

DHH can keep using it then.

Ben Orenstein:

Yeah.

Adam Wathan:

For the one pairing session he probably does every 3 years.

Ben Orenstein:

Yeah. Just a sprinkling of sprinkling of pairing.

Adam Wathan:

Yeah.

Ben Orenstein:

Alright. So we had a plan. I well yeah. My team and I had a plan to talk to you about Rust. And you were like, "oh, bad news. I haven't written any Rust, basically."

Adam Wathan:

Yeah. Barely. Not enough to, like, talk about it. Let's put it that way. But maybe, like, there's conversation to be had that stems from that insight.

Adam Wathan:

I don't know.

Ben Orenstein:

Yes. Yeah. Yeah. So you did you're you rewrote tailwind in Rust. Is that done?

Ben Orenstein:

Is that shipped?

Adam Wathan:

No. So that's not true.

Ben Orenstein:

Haha, great. We're crushing it.

Adam Wathan:

Yeah. So so we did rewrite all of Tailwind, which is kinda just like an interesting interesting story, I guess, in general. Everyone says don't rewrite anything ever. My experience has been, like, rewriting things is awesome, and it's always super fun. And, it is it's super fun, and it turns out better.

Adam Wathan:

And yeah, I don't know. So we had Tailwind, the code base. It's been around since 2017 in various incarnations. It's been rewritten twice before, really, depend depending on how you think about it. It was originally written in, like, LESS, the CSS preprocessing language, before it was ever even released.

Adam Wathan:

That was unsustainable because there's no way to, like, write tests or do anything. And as as it just got more complicated, it just was getting out of control. So we rewrote it in JavaScript, plus CSS, and, with no no real sort of deliberate effort to make it fast or or anything, you know. It was just make it work, was the mindset then. And then eventually, we rewrote it again because we had to change how the whole thing worked.

Adam Wathan:

So back in the day, Tailwind used to generate a giant style sheet, and then it would look at all your class names in your template files and delete all the classes you didn't use. Tailwind 3 kinda does the opposite: where it looks at all the classes in your templates and then only generates the classes that you need, which ends up just working out a lot better. But we had to rewrite it to do that because it's just like a totally different approach to to doing the entire thing. Tailwind 4 is a rewrite again, but I kind of see it as sort of like the final form rewrite where it's like we really deeply understand what Tailwind is now and what it does and what the mental model of the whole system is. What if we just wrote code that actually represented that instead of, like, continuing to evolve this hodgepodge thing where we're, like, patching things on and figuring out just ways to add features without totally tearing things down and stuff like that.

Ben Orenstein:

Can we rewind a bit? I have, like, a story off or, like, a off topic kind of question, which is: I've been thinking about redesigning my personal website.

Adam Wathan:

Mhmm.

Ben Orenstein:

So it's not terrible. And I'm very tempted to just literally have an HTML file; like, no building whatsoever. This is literally a static file that I edit that has HTML in it. How bad is it to just throw the full Tailwind thing, minified, in the top there?

Adam Wathan:

There's no such thing as the "full Tailwind thing" anymore.

Ben Orenstein:

Oh, interesting. Okay.

Adam Wathan:

Because there's an infinite number of possible classes that it can generate because there's so much dynamic pieces to it. But there is like yeah. This isn't a good solution for you, but there's like a JavaScript version of Tailwind that you can pull in as like a script tag that'll generate the CSS in the browser based on the stuff that you're using.

Ben Orenstein:

Interesting. Okay.

Ben Orenstein:

And that that would let me skip a a build step, right, if I do that?

Adam Wathan:

You would have no you'd have no build step. There's a few, like, little downsides that will not impact you, which are details around like, the way that it works is it basically has to wait for the the classes to exist in the HTML, then it pulls them out and generates the styles for them. So if there's ever a situation where an element might appear on the screen before the JavaScript has a chance to figure out what class is there and apply the styles, you might see, like, a flicker of unstyled content.

Ben Orenstein:

You know? Like, if the if the class shows up after the element or something? Is that what you're saying?

Adam Wathan:

No. It's it's more like, say, you have, like, a dialogue that opens and when you open it, it inserts a new element that wasn't there before and you want it to say, like, fade in. It's not gonna fade in because, like, it's gonna the styles that apply, like, the fade haven't been generated by Tailwind. Like, it's gonna be, like, one frame late. You know what I mean?

Adam Wathan:

But it's enough that, like, the transition doesn't happen. But that's, like, the only situation where it really matters. The current JavaScript thing is kinda clunky too because we have to... It was built it was kinda built after the fact. We kinda took Tailwind, the CLI tool, and then tried to, like, basically, like, monkey patch anything that touched the file system and all this stuff and turn it into something that could run-in the browser. So it's a pretty big JavaScript file full of clunky stuff.

Adam Wathan:

The new code base, we've we have a very pure core now that doesn't know IO or any of that stuff, and we can ship just that core to the browser now, and it's extremely small and extremely fast. And yeah. So they are yeah. A lot a lot of interesting whatever. I don't know.

Adam Wathan:

We're we're all over the place already. But...

Ben Orenstein:

That's cool. No. That's great. I want a Patrick Collison style, like, personal website. Or just, like, one that's extremely bare bones.

Ben Orenstein:

It looks like a text file.

Adam Wathan:

Yeah. Where it looks like it would have fit on, like, the Apple computer that was in, like, the tech room at your high school that had a resolution of 640 by 480 or whatever?

Ben Orenstein:

Pretty much. Yeah. Exactly.

Ben Orenstein:

It would it could have appeared on any screen between like, from now to, like, 1980 Mhmm. And been totally fine and, like, would fit on a floppy disk.

Adam Wathan:

And you literally want it to be an HTML file? Like, you wanna write blog posts where, like, every time you start a new paragraph, you have to do angle bracket, p, closing angle bracket?

Ben Orenstein:

I mean, like, I don't really want to do that...

Adam Wathan:

When the rubber hits the road here...

Ben Orenstein:

Yeah.

Adam Wathan:

Or do you just want a nice theme for a CMS? I feel like the older I get, the more I understand the benefits of a CMS.

Ben Orenstein:

I feel like I want, like yeah. I guess, though. Like, I just like there's there's so much appeal to me right now and, like, I directly edit this file. It's, like, so simple. There's no generation happening. There's no build step. No JavaScript is involved whatsoever nor ever will be. Like, I just I want the simplicity of index.html .

Adam Wathan:

Yeah.

Ben Orenstein:

I don't know.

Adam Wathan:

If you were gonna yeah. I know what you mean, but then

Ben Orenstein:

But then do I?

Adam Wathan:

At the same time, I think you wanna write in markdown, you know.

Ben Orenstein:

I do actually wanna write in markdown.

Adam Wathan:

That's true.

Ben Orenstein:

That's why I want the Tailwind Prose plugin. Yeah. But that was that was peak Tailwind for me.

Adam Wathan:

You still need to compile the markdown to HTML.

Ben Orenstein:

Yeah. I know.

Adam Wathan:

So it's still a build step.

Ben Orenstein:

Yeah. I guess there is. Maybe I need someone who knows programming to, like, set me up a simple, staticky Yeah.

Adam Wathan:

Yeah. Personal like that. Some some eager young lad. You know?

Ben Orenstein:

That's right. Some new hotshot.

Adam Wathan:

Person who maybe would help you fix your printer. You know?

Ben Orenstein:

Exactly. Who, like, go yeah. Help me lift heavy luggage so I don't hurt my old back.

Adam Wathan:

Yeah.

Ben Orenstein:

Yeah. Okay. Yeah. Fine. So you ruined my life by getting rid of minified tailwind being a thing on a CDN.

Adam Wathan:

But well, here's the thing. I was gonna say, if your site never had new styles, like, you just kinda said, this is what it looks like. This is what our records look like. It's done. There's no there's no new visual anything that's ever gonna appear except new articles that look the same as the old articles.

Adam Wathan:

Then you could just compile the JavaScript once, throw it in the repository or sorry, compile the CSS once and pretend that it's a CSS file that you wrote by hand once and just sits there, you know?

Adam Wathan:

Yeah.

Ben Orenstein:

That's that's yeah.

Adam Wathan:

Okay. That's another move.

Ben Orenstein:

Yeah. I like that. That seems that seems better, I think. Okay. Cool.

Ben Orenstein:

Well, that's helpful. Alright. So Tailwind 4: how is this how is this a big reimagining of the system?

Adam Wathan:

Yeah. Okay. Good question. So we the original motivation for it was sort of 2 things. 1, it's

Ben Orenstein:

really a lot of it is kind

Adam Wathan:

of one thing, but the one thing has multiple pieces to it. The one thing is it sounded fun.

Ben Orenstein:

And Yes.

Adam Wathan:

And also it would the other piece to that is, like, this code base and project is really important to me, and I wanna be, like, obscenely proud of every corner of the code base. And that's just not the the state that it was in up until now. It's just kind of

Ben Orenstein:

These are the best motivations to do this kind of thing. I love it.

Adam Wathan:

Yeah. And and it was killing my motivation for the project in a lot of ways, you know, like, just feeling like if I poked around in there, I'd find, like, some horrible band aid fix we had to put in that was just I I just felt like we hadn't been treating, like, Cobas with respect. You know what I mean? And and I think everyone on the team was sort feeling the same way. It's like kind of like what do they call it?

Adam Wathan:

Like broken windows theory or something where it's just like, oh, well, we did something fucking gross there. So the code base is already done for. So what does it matter if I do a nice implementation here or a dirty implementation here? And it takes a lot of discipline to, like, fight that once it's already started creeping in. So I kinda just got everyone rallied around this idea of, like, let's, like, get in it a fresh thing and just, like, approach it with extreme care, you know, and just just try to make, like, the best thing that we can possibly make.

Adam Wathan:

Even, like, in in a rational ways, like, let's decide when we use, like, double slash comments versus, like, slash star comments and be consistent about that everywhere. Let's decide. Do we end comments with a period or do we not end comments with a period? You know, like, these sorts of, like, superficial things.

Ben Orenstein:

Did you have to convince people to do this? It sounds like every developer's dream.

Adam Wathan:

No. I don't I don't think so. The thing that I think is interesting about it from, like, a team dynamics perspective is, like, these same people on the team, myself included, who are totally willing to just say, like, fuck it. It's already a mess. Who cares?

Adam Wathan:

Take basically no encouragement to get excited about the idea of let's make the perfect thing and keep it perfect forever. You know? I think I think everyone wants to do that. So it it it's exciting for everyone on the team, I think, to feel like they work at a company that's gonna even gonna let them do that and let alone, like, like, put place value on it and almost hold them accountable for it. You know?

Adam Wathan:

Mhmm.

Ben Orenstein:

Mhmm. Right. Because because if we're doing this whole rewrite, it like, it's gonna be worth it. Like, don't even think about making it nominal.

Adam Wathan:

If if we screw up if we get off the rails, then, like, what was the point, You know? We have to, like, hold the line. I think back to that tweet that me and you've talked about in the past that Toby shared ages ago where he talks about, like, the hardest thing about, like, building a business is I can't remember exactly what he said, but the essence of it was basically, like, setting a bar for quality and, like, preventing, like, regression to the mean, you know, just, like, holding it, like, as tight as you can.

Ben Orenstein:

Yep.

Adam Wathan:

And, yeah, because, like, that's the natural state of of everything, including, like, myself, you know, which is honestly the the hardest part. It's easier to sort of hold other people to your standards than than yourself in a lot of ways.

Ben Orenstein:

You're more likely to extend yourself some leeway.

Adam Wathan:

Exactly. Yeah. Exactly. Yeah. Yeah.

Adam Wathan:

So that was kind of the big motivation for it

Ben Orenstein:

was just, like, let's make it as clean as possible. And then combined with that, it was, like, what's something that we could just

Adam Wathan:

put an absurd amount of focus on that would never be like a dumb thing to invest in? And we thought let's just make it the fastest possible version of Tailwind ever. Let's make it insanely fast, basically at the expense of anything. I I don't really care, like, what it takes, if the code is harder to understand but it's faster, I don't care. I just want it to be faster.

Adam Wathan:

And so that benefits users sort of, you know, tailwind was already pretty fast but, like, people love fast things. But it was more just like a really interesting challenge for us because it's it's just like a clear goal and gives you a way to sort of measure what you're doing. And it was also, like, everyone on the team is interested in performance. No one on the team has ever worked on a project where that got to be the focus to that extent. So it's a sort of a learning experience too.

Adam Wathan:

Everyone's just excited to, like, learn more about the stuff and get better at it and understand, like, when it's faster to, like, access something in memory versus recompute it or stuff like that. And we had this sort of tail one three's internals was like a lot of the speed came from like very aggressive caching. So we had this goal, like, how can we make 10 14 faster than v 3 with no caching, you know, which is

Ben Orenstein:

Because there's, like, too much over. There's, like, conceptual overhead for the caching. Like, it's it's hard to think about.

Adam Wathan:

It's a lot of complexity in the code. And and if we're gonna put any caching in, like, let's do it in a way where it's, like, layered on and not, like, just intertwined into, like, horrible places where you can't tell if it's a cache or not a cache.

Ben Orenstein:

Got it.

Adam Wathan:

You know? Yeah. So that was kind of, like, the goal, and that led to a few different things. Stop me at any point if you wanna, like, talk about anything in specific.

Ben Orenstein:

Totally. Yeah. Yeah. Well, so tail and 4 is, like, speed and beauty, it seems like, is the like, the kind of goals

Adam Wathan:

here. Yeah. And the other thing that falls out of it too is, like, part of the beauty thing is just modeling the problem as sort of accurately as possible based on our understanding of it. Yeah. And a major benefit of that is that a bunch of, like, features fall out of Tailwind for free that Tailwind didn't have before because things were not modeled well.

Ben Orenstein:

Got it. Yep.

Adam Wathan:

So some of these are, like, really specific and you you need to kinda be like a tailwind power user to even appreciate it, but I'll talk about them anyways and for the benefit of the audience even if like

Ben Orenstein:

Yeah. Yeah. I'll just nod like I understand what's happening.

Adam Wathan:

But there's like some things in Tailwind where have you ever used have you have you ever built a website with Tailwind yourself?

Ben Orenstein:

A bit. Yes.

Adam Wathan:

So there's, like, some sort of advanced features for styling things based on the state of other elements, for example. So we have features like group hover. So say you have, like, an element and you wanna say, I want something about this element to change when the parent element is hovered. You know?

Ben Orenstein:

So you

Adam Wathan:

could do that in CSS. Like, you can imagine what the selector is for that. But to do that in Tailwind where you're just sticking classes on things, you somehow have to, like, connect those. So in Tailwind, the way you do that is on the parent element, you could and it can be any parent up the tree. This is why it sort of needs to be specific, but you add this class called group that's sort of like a marker that's saying this is the group that we care about.

Adam Wathan:

Then on the child, you add a class that says group hover and then whatever you wanna do, like change the background color or add an underline or whatever.

Ben Orenstein:

Yep.

Adam Wathan:

And group hover is an is an example of, like, a group version of the existing hover modifier. So you can already change something on regular hover, on regular focus, but we added group hover, group focus. And the way all that was built in Tailwind 3 was we just hard coded those in. There was a group hover feature, a group focus feature, a group active, group disabled, group whatever. Like, the whole list goes on.

Adam Wathan:

We just looped over them and generated them all. Yeah. With the way that the system is modeled and tow and and and sorry. The big downside of how that worked is that if someone added, like, a custom thing to Tailwind, because people add, like, their own little modifiers that represent different selectors, There would be no group version of it because we just hard coded in all the ones that existed.

Ben Orenstein:

Yep.

Adam Wathan:

Tailwind 4, because we've figured out a way to just model the problem better, now, like, group is this it's we call it like a compound variant where it takes, like, another variant as an argument. And even if that variant is registered after the fact by the user, it still just works. Yeah. So that's, like, an example of, like, a feature that just, like, exists in 21 4 that we didn't redesign Tailwind 4 with this thing in mind, but it actually kind of just happened for free. We literally just rebuilt it, tried to think, I don't wanna loop over all these things.

Adam Wathan:

How can we, like, model this better? What concepts do we have to invent that didn't exist before? And now we make it work and then you almost realize after the fact, wait a minute, that means this works now. You know, and it's just like such a exciting moment when you get features for free just because you sort of modeled the problem better.

Ben Orenstein:

Yeah. That feels like a incredibly strong feed like, positive feedback that, like, you made a good choice there. It's like stuff just happened.

Adam Wathan:

Yeah. Yeah. Exactly. Every time you can, like, delete a conditional because you do something better somewhere else, that just means, oh, that actually is just how it works now.

Ben Orenstein:

Right.

Adam Wathan:

You know, stuff like that.

Ben Orenstein:

Like, getting your data structures and the modeling, like, the problem domain modeling right should lead to that kind of outcome. Yeah. And if it doesn't, then well, like, are you are you going in the right direction at all? Like, that

Adam Wathan:

A 100%. Yeah. Yeah. So there's a lot of internal changes that we're excited about that gave us those sorts of benefits and and made things easier.

Ben Orenstein:

That's that's such an interesting heuristic to me, which is, like, are we getting things for free with this approach? Yeah. Yeah. Let's just, like, just ask about of the 3 approaches we're considering, like, what gives us what gives us things for free? Because that's a probably a really strong sign of, like, that's the right direction.

Adam Wathan:

A 100%. It's like swimming, like, up stream versus downstream, you know. Yeah. When things, like, start falling out of the architecture that you didn't expect that just start to work.

Ben Orenstein:

Yeah. I like that a lot.

Adam Wathan:

It's just a beautiful, beautiful feeling.

Ben Orenstein:

Right. You've got the right abstractions probably, like the right like, you've.

Adam Wathan:

Yeah. The code represents the problem accurately. You know what I mean? Like, it's just like modeled better, you know?

Ben Orenstein:

Right. Yep. That's cool.

Adam Wathan:

Yeah. So, like, that was like a big a big point of focus, like, specifically changes that we made to clean things up. In the old code base, class names were just like passed around just strings a lot and things that needed to, like, pull out little bits of them to detect like, oh, we need to apply the hover thing here or this is like a color that has a slash after it, so we have to change the opacity. That was all like string manipulation that just happened in random parts of the code base. And, like, the new version of the code base, the first thing that we do when we find a class is we parse it into, like, a abstract syntax tree that we have created ourselves, like a data structure that represents okay.

Adam Wathan:

It has an array of modifiers at the beginning. Each modifier is a data type that possibly has, like, an arbitrary part or a named part. And if it's color, it has, like, an opacity. And now it's just an object that gets passed around everywhere and you can get exactly what you need anytime you want instead of having to just like rip through strings and pull things out with regular expressions. Like, you wouldn't really even believe how bad the old code base was, I guess, you know, in in this sort of regard because it it just evolved over time from something so simple.

Adam Wathan:

So when you know the level of complexity of the needs, like, at the beginning, you can just do such a better such a better job.

Ben Orenstein:

Does is this did this ship yet? Is Fort Telefort out?

Adam Wathan:

No. There's an Alpha out, and that came out, like, 1st week of March or something like that.

Ben Orenstein:

Mhmm. How long has it been? When did you start working on it?

Adam Wathan:

As soon as, like, January 3rd or whatever, the first day back after, like, the New Year's kinda holidays were.

Ben Orenstein:

Okay. So you're, like, only, like, 4 months into this, basically. Something like that.

Adam Wathan:

Yeah. Only really 2 because and once we got the alpha out, we shifted gears back to some, like, commercial work that we need to get caught up on, and we're about to release that stuff, like, this week, next week. Then we're gonna spend probably the next 2 to 4 months wrapping up v four proper.

Ben Orenstein:

I'm it's interesting how I mean, it's interesting to me how fast that went. Like, I'm like, why didn't you get sucked into, like, some of the downsides of rewriting things? Is it because Tailwind is just kinda small?

Adam Wathan:

It can be small. Like, the code base is way smaller than it was before. I think the biggest thing is more of a it's more of a project management story than it is a code story. Alright. So we were just very well, okay.

Adam Wathan:

So it took 2 months, but it it took, like, 2 years at the same time because so many of the things that we did in those 2 months were things that we sort of prototyped in different repositories leading up to that time just to, like, know if they worked or not and then just kept that in the back of our mind. It's something we wanna, like, approach problems that just like our hammock thoughts, you know, approach problems that just like our hammock thoughts, you know Yeah.

Ben Orenstein:

Yeah. Yeah.

Adam Wathan:

That you need to just wrestle with for a long time. So this was a lot of this was very pure execution because we had much clearer ideas, I guess, of of how we wanted, certain things to work. And but in terms of getting it actually done in that period of time, we were very explicit about what was going to be in the alpha and what was not. So there's some big pieces that are not in there like backwards compatibility. So historically, Tailwind has had a JavaScript configuration file.

Adam Wathan:

The v 4 does not support that right now and we'll need to figure out how we wanna do that going forward. But we really wanted to write this, like, v 4 code base as if it was as if we were just gonna do, say this was the first version knowing everything that we know now and there was no baggage, like, what would it be? So anything that we kinda wish we didn't have, we just didn't build. And did it intentionally because I wanna make sure that when we add support for that stuff, it's layered on to, like, the clean core and not just mixed in with it because we tried to do it from the beginning. So if we just build for, like, the pure, happy, cleanest, exactly what we wish the code base was path, and then backwards compatibility is as much of a layer as possible, that to me just felt, like, more likely to end up with a project that we're proud of.

Adam Wathan:

Like, when v 5 comes around and we feel comfortable getting rid of certain things that, you know, are not really the encouraged path anymore. I want that to be like deleting a file. I don't want that to be like hunting around for all the places that cared about this backwards compatibility thing. You know?

Ben Orenstein:

Got it. So so you're kind of, like, constraining the mess into, like, a spot or, like, the the the wrinkles or whatever? Yeah.

Adam Wathan:

It's it's a deliberately small scope. It it's it's very complete in the sense that we we just finished up the headless UI 2 point o documentation site. It's a tail and 4 project. It's gonna be live at the end of this week, and it totally works and we were not limited really in any way, you know.

Ben Orenstein:

Mhmm. Okay.

Adam Wathan:

But but yeah. There's a lot of things, the hardest parts missing.

Ben Orenstein:

Yeah. Yeah. I mean, are you worried that all the beauty is gonna come unraveled when you are faced with these gnarly bits?

Adam Wathan:

I'm not too worried about it. Mostly because we are so determined for that not to happen. You know what I mean? Like, that is the goal. So I don't think anyone will settle for that happening.

Adam Wathan:

We will find ways to avoid that from happening. Even to the point where, like, one of the ways we've been talking about dealing with some backwards compatibility stuff is not to make the old thing work, but to just make it in possibly easy to upgrade to the new thing. So code mod tooling and stuff like that that can, like, go through your project and change things in a very bulletproof way, stuff like that where, okay, now we don't actually have to support the old thing because we've just helped you get to the new thing. And the more I think about that, the more I feel there's a lot of value in it. I I feel like if you let an old deprecated thing work, People will use it and be content in a way that they've been able to upgrade to the new version.

Adam Wathan:

But they'll also kinda just feel like that they're not done upgrading yet. You know what I mean? It's just like, okay. This feels like a stop gap temporary thing. I'm still not doing it the best practice way or the encouraged way.

Adam Wathan:

I'm kinda relying on this legacy thing. And, yes, technically, the version number of the version that I have installed is the latest thing, but I don't feel like I'm using the latest thing. So I kinda feel like just making the old thing work is not actually helping people with the core problem, which is they wanna feel like they're on the new and shiny. You know? So how can we, like, actually get them to the true new and shiny, not just Yeah.

Adam Wathan:

You know? So that's something I'm thinking about a lot, and that's something we're gonna be putting a lot of time into the next couple months is exploring some of this code mod stuff.

Ben Orenstein:

So So you say backwards compatibility, but you actually you're not gonna be backwards compatible. You're going to have new ways of doing things that people will have to change to get to?

Adam Wathan:

I'm not sure yet. That's the thing. Like, I I kinda think in a perfect world, we would have both. The old thing would work, but if you haven't done anything too too crazy, where we can sort of teach the computer how to upgrade your code base, that the computer can upgrade your code base and you don't have to use the old way. You know?

Adam Wathan:

Mhmm. Specific examples like the JavaScript configuration file. Now in 214, the encouraged path is to, like, set up all your colors and stuff in your CSS file. And we could totally ingest your JavaScript configuration file, figure out what the resolved sort of color palette and everything is that you've configured, and then spit out the equivalent CSS file, and then you don't need the JavaScript file. But, of course, people do crazy things in JavaScript files.

Adam Wathan:

And if we can't make that if we can't figure out a way to translate that into a CSS file, we probably should just let the JavaScript file continue to work. You know? That make sense?

Ben Orenstein:

Yeah. I mean, maybe. But then again, like, if you are doing a major version bump and you really value the, like, beauty and elegance of the new solution is hard, backwards incompatibility where you just remove this thing, like, on the table?

Adam Wathan:

I don't know. I kinda think no because I I just feel like my personal stance is that open source maintainers generally underappreciate, the importance of backwards compatibility even with major version increases. I'd rather make, like, very small breaking changes that affect barely anybody than and and use major versions as an opportunity to do that. Like, my general strategy that has worked in Tailwind in the past is sort of, like, do a major version, reintroduce a new way to do something, stop documenting the old way to do something, wait a few years, then make the old thing, like, no longer work when it basically affects nobody because everyone's forgotten that that was even a way to do things. You know?

Adam Wathan:

And I feel like that's sort of the most considered way to to do it. In my head, the way I imagine it working specifically in, like, the JavaScript configuration file case is there's just gonna be some code near the very beginning of, like, when the library starts to do its thing that looks at that file, turns it into the exact same data structure we'd get from parsing your CSS, and then passes that into the core. You know? So it's like an onion layered sort of thing. I I don't know if you ever I did a podcast with Michelle Boo, who I think she might still be at Stripe, but she was at Stripe at the time.

Ben Orenstein:

You were making me think of the Stripe the Stripe thing.

Adam Wathan:

Yeah. The Stripe API upgrade thing. Like, they basically try to keep, like, the core API nice, and they they write layers around it to preserve backwards compatibility with, like, the changing in the API data structures and stuff. And it just goes through this, like, pipeline of transformations. So if you're on, like, the 2013 Stripe API, they have, like, a layer that you hit that then upgrades it to, like, the 2014q21, that upgrades it to the 2014q41, that upgrades it to the 2016 one, you know, until

Ben Orenstein:

Yeah.

Adam Wathan:

Your request matches, like, what the expected input is of the current API.

Ben Orenstein:

Yeah. That's kind of insanely baller. I love that.

Adam Wathan:

Yeah. Totally. Yeah.

Ben Orenstein:

It's super cool.

Adam Wathan:

Yeah. So that's how I envision it though is that same idea. Like, how can how can we basically upgrade you on the edge, you know? Right. So that the core can stay clean.

Adam Wathan:

And obviously, until we actually do it, I can't know for sure that it's gonna be as, you know, perfect as I hope. But that's the that's the dream.

Ben Orenstein:

And unlike Stripe, you will eventually remove that edge translation.

Adam Wathan:

That is the nice thing about not running a payment processor. Yes.

Ben Orenstein:

Right.

Adam Wathan:

We will probably eventually remove it. Yeah.

Ben Orenstein:

Yeah. It's it's a bit less important to you to keep support a a way of doing it from 6 years ago.

Adam Wathan:

And again, I think the code mod stuff is valuable too. There's probably certain breaking changes we've made that would be better to just give people a code mod and don't even support the old thing because like, there's a couple things where, like, we've changed the order of 2 pieces of a class name, for example. And I could either give you a configuration option that preserves, like, the legacy one that now you have some configuration option that's staring you in the face saying, LOL, you're actually using the old version of Tailwind. Or I could just give you, like, a tool that generates the diff. You open a PR to your code base and just compare them, and then now it's done and I don't need to live with this configuration option in my thing for the rest of the time.

Adam Wathan:

You know?

Ben Orenstein:

Yeah. That's good news.

Adam Wathan:

I think we gotta think about it on a on a change by change basis.

Ben Orenstein:

Got it.

Adam Wathan:

But yeah.

Ben Orenstein:

So sometimes you're gonna add the compatibility, like, layer at the edge, and sometimes you're just gonna say, because this is an easily automated change Yeah. I'm just you're gonna have to do it. We're gonna make you do it.

Adam Wathan:

That's how I'm thinking about it right now, for sure.

Ben Orenstein:

This is pretty sensible. I like that.

Adam Wathan:

Yeah. I guess, like, in terms of the, the Rust stuff, just to kind of talk about that because I think that's what you're expecting us to talk about. I think, I can talk about what we used it for, but I think it's also interesting to talk about why maybe we didn't need to use it as much.

Ben Orenstein:

Yeah. So so toe and fore is not does does it have any rust components or no?

Adam Wathan:

It does have some rust. Okay. But it's carefully factored. So tailwind's the way tailwind works, there's a few stages to the processing. Right?

Adam Wathan:

So the the very first thing we have to do is find all the files in your project that have class names in them, pull out all those class names, and then generate the CSS for all those class names. So if you think about like just those two top level stages, the first step we are now doing in Rust. So we have a crate that we've written in Rust that can receive the paths to where all your templates are, either your configured paths. We've we've also been working on features to sort of auto detect them, which we're able to do in Rust quite fast, which is interesting. But that part we wrote in Rust, and get major benefits from it for two reasons.

Adam Wathan:

So the JavaScript version of this where we'd look at a file and try to find all the class names, the only way to do that and have it be fast in JavaScript is regular expressions because regular expressions are heavily optimized by the engine to, like, very native type code, you know. Mhmm. Mhmm. But they're insane. The regular expressions that we have to write and dynamically create and maintain, like, trying if you have run into a bug where it's like, oh, for some reason, this class, when I have this quoted brace in this one spot doesn't work, and I've it seems like it should because it's so similar to this other class.

Adam Wathan:

Trying to find the spot to add that allowed character in some regular expression is nontrivial and, like, highly terrifying because you don't know what the consequences are. Mhmm. In Rust, though, we're able to rewrite all that logic as like a byte level parser. So now we just open up the file and we just scan through a character by character with a state machine that we maintain that's just like, you know, are we currently consuming a potential class? If so, then there's all these rules about which characters are allowed and which spots and whatever.

Adam Wathan:

Otherwise, we just, like, skip characters until we see a spot that could be the start of a class and then start consuming them.

Ben Orenstein:

Mhmm.

Adam Wathan:

And we can write that with just pure regular human understandable loops and conditionals, you know, not regular expressions that are really hard to sort of figure out because it compiles to native code. So it's just as fast as the regular expression engine and node, actually faster.

Ben Orenstein:

Are you using a parser generator for this? No.

Adam Wathan:

It It says written by hand. We did try a parser generator, and it was much slower than writing it by hand. Interesting. Okay. But, yeah.

Adam Wathan:

So, you know, that's how that part works in Rust Now. But then, like, the other huge, huge, huge benefit is this is, like, extremely parallelizable work. Mhmm. Because all it is is, like, if you can get all these text files into memory and then just, like, spread that work across all the threads, pulling in all the class names and dumping them into, like, one shared set. So you only get unique copies of each class.

Adam Wathan:

You can do that across all course, and Rust has concurrency and JavaScript does not. You know, Node does not. Mhmm. Mhmm. So that instantly makes that, you know, whatever, 12 times faster or something compared to how it would be in JavaScript and then also just way faster because the it's faster to do the same work even single threaded.

Adam Wathan:

Yep. But there was even even there, there's all sorts of just, like, interesting little things that we had to test and benchmark to figure out the fastest way to do stuff like so, of course, you don't want Tailwind to try and, like, generate the CSS for the same class name multiple times. So if the flex class exists in 10 of your files, you don't wanna pass it to Tailwind 10 times, because that's wasted work. You already know what CSS that generates, and it's only gonna appear in the final CSS once anyways. So, you know, figuring out what's the fastest way to end up with a unique list of of class names is an interesting problem.

Adam Wathan:

Do we put them all into like a list and then like de dupe the items in that list in rust, especially since you have to do this from across threads, which is kind of interesting or do we create a set, you know, which is like, okay, well that's interesting because a set, a property of a set is that every item is unique. Can we dump things into a shared set? And that worked and that was pretty fast. But then we also discovered that by default, like the way that a set works right is it has to like under the hood it's using like hashing algorithms to like figure out where things should go and stuff because it's not just like a continuous list of things in memory, it has to like, so under the hood in Rust by default, they use, like, a cryptographically secured hashing algorithm because that's important for some use cases, but it's not important for our use case. So realizing, hey.

Adam Wathan:

We can swap out the hashing algorithm with, like, a faster hashing algorithm that's not cryptographically secure. You get, like, a ton of, you know, performance benefits from that. So these are like the sorts of little knobs and dials that we're, like, tweaking and playing with and just bench benchmarking everything. It's totally gamified, right, because you're just running these, like, measurements in the command line. You're saying, can we get this under 10 milliseconds or can we get it under 5 milliseconds and comparing implementations and stuff.

Adam Wathan:

But that's the only part that happens in Rust is just like pulling the class names out and then all of the work to actually take a class name, figure out what all the different parts mean, generate the CSS, turn that into like a big CSS file. All that is happening in in Node still, and that's by far the bulk of the the code. And then the other interesting, like, constraint is, okay, we wanna ship a browser based version of this like we were talking about before, like the script tag. Well, if we start writing things in Rust, how the hell do we ship that to the browser? You know, we have to compile it to WASM, which has this huge size overhead.

Adam Wathan:

Now we're gonna ship, like, a 7 megabyte, like, JavaScript file or something to the browser. That's horrible. So we also had this constraint in our heads of making sure that anything that had to hap anything we did in Rust was work that didn't ever need to happen in the browser. So in the CDN based version, we don't have to, like, look at text files and pull out strings. Right?

Adam Wathan:

We can actually just, like, look at the HTML tree and look at literally the class attribute on each element and pull those out which you can just use like existing browser APIs to pull out the class list from each element. And that was like a huge unlock because it it let us it it helped us understand what could go in Rust and what could go in JavaScript because in, in a regular project that's written in React or whatever, a lot of class names appear in places that aren't the class attribute because you're doing the work to figure out the class in some function somewhere and then putting it in the class attribute. But in the browser, that's just like the finished HTML, you know? The classes are in their final place. So we don't need to look at the whole file.

Adam Wathan:

We literally only need to look at the the class attribute, you know. So that was like recognizing that it gave us this clear line of, like, what could happen in Rust, what could happen in JavaScript. Anyways, I, I feel like I'm just blabbering about stuff. No. No.

Ben Orenstein:

No. No. No. You're not. That's great.

Ben Orenstein:

That's super good. Well, what's I'm curious what the testing story is in tone 4. Mhmm. There are a lot of tests?

Adam Wathan:

There's a lot of tests. Yes. There's fewer tests in v three because I think we're a bit more intentional about how to test different different things. So everything is using this tool called V test, which is just the current kind of flavor of the month JavaScript test runner and it works quite well. I'm pretty happy with that.

Adam Wathan:

There's a lot of sort of pretty outside in tests where like the input to the test is a list of class names and like the CSS file that contains some of the configuration information, and we just sort of test given this list of class names and, like, this color configuration, this is the CSS that should be generated. And that's where we get probably the most confidence in terms of how like the overall system works. But there are parts of the system that are unit tested too. And that's mostly a developer experience decision because a lot of time you're working on like a little function and I just want to know that when I put this into it that this comes out. I think the way we've generally decided when to unit test something versus when to sort of test things at the system level is could I imagine this function being a package that I installed, you know, because if I did extract it as a package, well then I would write unit tests for it because I would want the package to have its own tests.

Adam Wathan:

So I find that to be like a useful heuristic for deciding if something feels like useful to have unit tests for versus test it a bit more black box where you have a bit more flexibility to sort of move things around and refactor things. You know?

Ben Orenstein:

So if so if you would extract it as a package, you will write unit tests for it? Is that the heuristic?

Adam Wathan:

If I could imagine, almost like if someone else had written this, would I have just installed it as a package? You know what I mean?

Ben Orenstein:

Okay. And then when if if the answer is yes, then you do write unit tests for it?

Adam Wathan:

That's yes. Yeah. That's when anything that we have unit tests for generally fits that criteria. It's not really deliberate, but, like, if I just look out and look at things, that's what they seem to have in common. Like, a very specific part of the framework that has quite a few unit tests is we have this one function whose only job is to take a string and split it on a certain character into all the different parts, but in a way that's like aware of, braces and quotes.

Adam Wathan:

So you can imagine, like, in Tailwind, if you have, like so something we have to do a lot is if you have, like, hover colon focus colon active flex, we have to split on all those colons, get all those parts out. 3 of them are modifiers. 1 of them is like a utility class. But some utility classes in tailwind, like the content utility, which is the sort of thing you use with a lot of, like, pseudo elements and stuff, content can take, like, a string as its argument. So you could you could have, like, a a colon inside the two quotes of the content property.

Adam Wathan:

So if we Got it. If we have, like, hovercoloncontentdashsquarebracketquotecolonquote square bracket, and we try to split that on colons. We don't wanna split on the last one because it's like quoted colon. You know?

Ben Orenstein:

It's in the string. Yeah.

Adam Wathan:

Yeah. And similarly, we don't wanna split on colons that are within braces or anything either. So we can't just use, like, the regular string split function in JavaScript. We had to write our own function that sort of traverses the string, detects when we're inside, like, a pair of braces and ignores the split character there. And so we have this function called segment is what we called it, that did that.

Adam Wathan:

And I just looked up synonyms for the word split and,

Ben Orenstein:

Yep. I like segment. I'm gonna say that's a good name.

Adam Wathan:

So it segments the the string into these different things. But, yeah, it's aware of sort of, like, nested structures basically in quotes. And that's, like, a good example of something that I could see being an MPM package. You know?

Ben Orenstein:

I see.

Adam Wathan:

Yeah. So that has unit tests because we knew exactly what it needed to do. It's used everywhere. It's useful in a lot of different ways. And we just threw a bunch of test cases at it.

Adam Wathan:

And it's also, like, an interesting place to, like, do an insane amount of performance optimizations and benchmarking because that it literally runs, like, thousands of times in in the code base. Yeah. So yeah.

Ben Orenstein:

Right. And I can imagine, like, oh, you discover a bug in a certain edge case and, like, you don't wanna throw that in like a end to end test probably.

Adam Wathan:

Yeah. Literally just had merged the PR to do that yesterday, where we had a bug where let me remember exactly what it was. It was to do with, braces in quotes. So we weren't accounting for that properly.

Ben Orenstein:

Okay.

Adam Wathan:

And we could have written, like, some test that has, like, a tailwind class that sort of does that and make sure that it works. And we actually did do that too just to sort of prove that. But we all but for that one test, there's like 9 unit tests that show, like, all the different characters that could possibly in quote in quotes and stuff like that and and hit them properly. And that fix actually made it faster too, which was kinda interesting because we realized that, once you're inside of a quote, you don't need to keep track of the braces and make sure they balance because, like, you know you're in quotes. These are just characters that don't syntactically matter.

Adam Wathan:

So we could just, like, skip processing every character until we find, like, the matching quote. So that was, like, a delight to fix a bug that makes the code faster. You know? Yeah.

Ben Orenstein:

Do did you know it was faster because you're, like, checking the benchmarks after you do it, or are there some, like, automated benchmarking that happens?

Adam Wathan:

We benchmarked it after, which is how we knew, but it was also the sort of thing where when you're writing the code, you sort of just have a sense. It's like, oh, I'm doing less work now, you know. Yeah.

Ben Orenstein:

Nice. So when what do you think tailwind 4 comes out?

Adam Wathan:

I had a goal originally for end of June. I don't think that's gonna happen now because we're a little bit behind on the stuff we're supposed to have out this week, and we have a team retreat coming up in 2 weeks. So I kinda think we're not gonna start on anything new till after the team retreat. We won't be back from the team retreat until, like, May 20th. And then I've got another trip in June.

Adam Wathan:

So I think we're gonna try to get a beta out at the end of June, which is basically gonna be hopefully all the features are there, but we haven't updated the docs site and redesigned the website and stuff like that. And then do more of the more of a marketing project focus for, like, July, August, and do, like, a proper release then. But I don't know. I can't wait much longer than that because we have other other work to do too. Thankfully, it is good for business, for us in general to, like, release open source stuff.

Adam Wathan:

Even if we've released nothing new or changed nothing about the commercial stuff, there's just a lot of sort of activity and excitement that comes around with the open source things. So

Ben Orenstein:

Right. Yeah. So sales go up when you release a new

Adam Wathan:

Sales go up when we release open source stuff, which is, yeah, thank god because otherwise it would be a lot it would be scary to be investing time in the open source stuff. It would it would it would feel stressful. You know what I mean? Whereas in at least now we sort of know that, yeah, the open source stuff is good for business, thankfully. So

Ben Orenstein:

Yeah. That's so nice. You live you live a charmed existence business wise.

Adam Wathan:

I do. Yeah. In a lot of ways. I take it for granted a lot and, big time.

Ben Orenstein:

Like, you're working working on the core free thing is, like, doing marketing? Yeah. Like, that's most people don't have that, I think. Like, marketing is separate. It you know, it doesn't doesn't it's not an out, it's not an outcome of working on the core thing.

Adam Wathan:

It's kinda separate, though, because I think there's a world where we could work on it and never talk about it until it was done and not get any of the benefits. You know?

Ben Orenstein:

Well, once you launch it, that's probably there's gonna be a significant benefit. Right? Like, tailwind 4 will cause a lot of buzz inherent.

Adam Wathan:

Yeah. That's true. But even when we're working on v 4 and I'm tweeting out benchmarks and stuff like that, sales are higher on those days. Yeah. Yeah.

Adam Wathan:

Totally.

Ben Orenstein:

Yep. So That's beautiful. Yeah. Yeah. So there is a separate marketing effort, but it's really it's it's the it's using the sawdust of the improving the core thing.

Adam Wathan:

Yeah. And that is really just, like, by necessity. When you're this small, I feel like all you can really do is you have to just, like, try to hit as many birds with that stone as you can, you know.

Ben Orenstein:

Mhmm. Mhmm.

Adam Wathan:

And thankfully, it's good. It's the right type of content for our audience too, you know, a lot. Right. I don't know. There's a lot to be thankful for in terms of things just, like, happening to happening to be the right way to do things in our situation.

Ben Orenstein:

You know? Yeah. But, yeah. Totally. I mean, when every time I tell somebody that, like, the tailwind origin story, I just feel like it's the most preposterous thing.

Adam Wathan:

And what's your version of the tailwind origin story?

Ben Orenstein:

I actually was I was gonna say, like, I I kinda wanna run the story by you to make sure I'm not just, like, spreading this, like, fake narrative. But the the way I say it is you were trying to make a SaaS, I think, to sell info products. Yep. Kite tail. Yep.

Ben Orenstein:

And you had this little set of, like, CSS utility classes that you would copy between projects Mhmm.

Adam Wathan:

To, like,

Ben Orenstein:

let you go faster as you're styling things. And you were doing live streams to try to, like, market the thing. And people kept you like, what's that CSS framework? And you're, like, it's not a framework. It's just, like, this little file I have.

Ben Orenstein:

And then, like, stop talking about that. I like that you would keep going and they're, like, no. What's that CSS framework? And it's, like, the framework. What's the framework?

Ben Orenstein:

And, eventually, you're just like, goddamn it. And you gave up. You're like, fine. It's a framework. Here you go.

Ben Orenstein:

And, like, you released it, and that was the start of Tailwind.

Adam Wathan:

Yeah. That's a 100 a 100% it.

Ben Orenstein:

Yep. Nice. Okay. Cool. Yeah.

Ben Orenstein:

This is so crazy.

Adam Wathan:

I know. It's awesome.

Ben Orenstein:

Like, it's so funny. So yeah. I like this is like I often tell people this story in the con like because I'm trying to, like, tell them, like, to just go do stuff.

Adam Wathan:

Yes. Exactly.

Ben Orenstein:

Or, like like, make like, work like, if you hadn't worked in public, you wouldn't have known that this thing was that useful.

Adam Wathan:

Yeah. And and and even if I hadn't worked in even for people who aren't working in public, I do generally feel I think, like, Matt Wensink tweeted this once. It was like, come up with an idea, build it, run into some really hard problem, solve that problem. The thing that you did there, that's your real business, you know.

Ben Orenstein:

Totally. Yeah. I think there's some real wisdom in that.

Adam Wathan:

Yeah. Just do anything, and you will encounter real problems. You know?

Ben Orenstein:

Right. Exactly. Yeah. Like, the real problem was the problems we found along the way.

Adam Wathan:

Yeah. Exactly. The real business was the businesses we found along the way. You know?

Ben Orenstein:

Yeah. Because yeah. And, like, that first idea, like, maybe you're really good at this, but, nah, probably you picked something stupid. Like, you never launched Kitel. That never worked.

Adam Wathan:

Never. And I never would because it had to have, like, PayPal integration. I don't wanna maintain that code, you know, and there's taxes and, like, all sorts of horrible things. But I'm so glad that and and and I was real serious about it too, which I think is maybe, like, another reason why that was I did go, like, very all in on it. Like, I did wanna build it for real.

Adam Wathan:

I wanted it to be a real thing. I really believed that's what I was doing, which I think is the only reason that I did the live streaming and and all this other stuff and encountered what the market actually wanted from me. You know? Right. Totally.

Ben Orenstein:

And this is not like an isolated thing. I think there's a number of good examples of these. Like, Segment comes to mind Yeah. Or, like, the Segment Analytics Is that

Adam Wathan:

Slack too? You know?

Ben Orenstein:

Yes. Yes. Totally. Yeah. Yeah.

Ben Orenstein:

I think so as well. So it's it's just I think this happens kinda frequently. Yeah. Definitely. So so I often when people are, like, saying, like, oh, I can't like, what do I do for business ideas?

Ben Orenstein:

How do I find an idea? I'm often kind of, like, look at the things you're doing at work. Like, what are the what are the internal libraries you built that are actually useful Yeah. That people like? That you though you'd be sad if they went away.

Ben Orenstein:

Like, pay attention to those. Maybe, like, commercialize that.

Adam Wathan:

Yep. A 100%. Yeah. It's it's it's crazy that the problems that you run into when you just try to do a real thing. Like

Ben Orenstein:

Mhmm.

Adam Wathan:

Yeah. I'm itching to build, like, a hiring tool now because we've been hiring. You know what I mean?

Ben Orenstein:

Yeah. Yeah. Are you gonna do that or what?

Adam Wathan:

I don't know. I am thinking about it. It's definitely I'm telling myself it would be good for Tailwind if we did it because it would it would be the most real sort of application that we'd ever sort of worked on. But obviously, it's a big big project to work on. My concern around doing it, I think, is that we do it so little that I don't think it's reasonable to, like, pretend to be an authority on it.

Adam Wathan:

But maybe that's not a reason to not do it. I can always learn. You know?

Ben Orenstein:

Yeah. I get to me, the biggest risk is actually just this. Like, it's just so different than what your core business is. That's like it's almost like a new company.

Adam Wathan:

Yeah. But in some ways, that's kind of, like, the thing that's that's fun about it too. This is, like, a whole whole other topic. This is, like, an other a topic for other podcasts. But I do I do often wonder if, like, my long term best play is to keep pushing hard on the tailwind business or to recognize that the tailwind business is my opportunity to build the next bigger business.

Adam Wathan:

Like this is the thing that will fund the next thing and it won't last forever and I should probably maybe I should take advantage of that, you know? Mhmm. It's so hard to know. Do you Is it like this is working, why would you get distracted and work on something else? Or is it like you have this amazing cash flowing thing and like a bunch of runway.

Adam Wathan:

Now is your opportunity to invest before, like, that goes away. And historically, that's what I've always done. You know? Like, first book funds me building the next course, which funds me and Steve doing refractory AI, which funds me and Steve building Tailwind UI, which I run forever Yeah. Or funds the next thing.

Adam Wathan:

I'm not sure, you know. So

Ben Orenstein:

Yeah. Yeah. Yeah. I mean, I almost feel like it's like, the way you're framing it feels wrong to me sort of where you're like, oh, should I do this while I have this runway? And it's, like, okay.

Ben Orenstein:

Like, you already have a successful enough business. You already have it's, like, this is not a money thing. It's not like to, like, make enough money to live anymore.

Adam Wathan:

Sure. Yeah. There's multiple pieces.

Ben Orenstein:

Now it's like, how do you want your life to be? And so to me, it's like, if you want your life to be a thing where, like, you work on a new business, like, like, if you're, like, feel called to and compelled to start this new thing, then, like, absolutely do it regardless of what the like, whether or not it's like a financially whatever thing. I don't know.

Adam Wathan:

Yeah. That's true. I guess I guess in my head I feel like I've seen it happen to other people in the past where they had like a good thing going and they should've like made the leap to like go all in on it but then it didn't they didn't and then it the thing kind of like fizzled out a little bit and they sort of missed their chance to sort of like go all in, you know?

Ben Orenstein:

To go all in on something else, you mean?

Adam Wathan:

Even to just, like, go all in on on the first thing so they had the chance to do, like, the next thing. Like, the comparison, I guess, I'm seeing in my mind with this is, like, does does Tailwind is there enough people and this is the whole fucking lifetime pricing conversation forever. Right? But, like, do we run out of programmers eventually who, like, are wanting to buy the templates and stuff that, we sell, you know?

Ben Orenstein:

I just think no.

Adam Wathan:

Yeah. Maybe no. So maybe we could just do this same thing forever, you know. But Mhmm. Eventually, Tailwind's not gonna be cool anymore, you know.

Ben Orenstein:

Yeah. But I mean, like, I don't know. Good luck competing with tail and 4. It seems like you're just kinda keep

Adam Wathan:

I know. I I just have to remind myself that it's our job to, like, keep it cool. Like, React is still cool and it's over 10 years old at this point, You know? And that's by continuing to evolve it.

Ben Orenstein:

You reach a point where you become immortal as a technology. Like, 10 years into Tailwind, you're probably like, just forever, there will be, like, Tailwind projects.

Adam Wathan:

Yeah. There will be Tailwind projects, but will there be, like, people choosing Tailwind for new projects? That's

Ben Orenstein:

Yeah. That's that's true. Yeah. Because you're only yeah. You're you're pretty much making money on the people that are new to it, most likely.

Ben Orenstein:

Yeah. But I but, again, I I don't feel like they're like, what if the gravy train stops and, like, we no more money comes out? It feels like the wrong motivation for you to pick the next thing or not.

Adam Wathan:

I I agree. Like, I'm fine. Yeah.

Ben Orenstein:

Yeah. So Exactly. Yeah. So just choose what kind of life you wanna have.

Adam Wathan:

Yeah. I don't know that I wanna have a life where I run a SaaS business where I have to have, like, 20 customer support staff and all that sort of thing, personally.

Ben Orenstein:

Mhmm. You can go go up your levels level stuff.

Adam Wathan:

Yeah. Maybe but maybe that's just like you don't need to do that. Maybe you can still build can you think of off the top of your head? I know we gotta wrap up in a couple minutes here. But can you name a successful SaaS company that you think is doing at least 7 figures a year, say at least mid 7 figures a year that is, like, super lean, you know, like, in you know, like, 10 people or less.

Ben Orenstein:

I mean, we're we are close to this parameter.

Adam Wathan:

Yeah. But others that come to mind, like, is there is there is there, like, oh, that shining example that, like, we're, you know what I mean?

Ben Orenstein:

I I feel like that almost doesn't matter. Like Sure. You could just decide how you're going to build this business and probably make it work. So if you say, like, I'm never gonna have more than 10 employees, and I don't care what the trade offs are involved in that, like, that's just like a that constraint is important to me, and I won't relax it, then, like, maybe you just hit this thing. And maybe no one else has even if no one else has, you might just anyway because you just actually decided that's what you care about.

Adam Wathan:

Yep. I think you're right about that, actually.

Ben Orenstein:

And you're Adam fucking wadding. Plus, like, the whole, like, headcount thing too now. It's like if you're like, oh, yeah. We are never gonna go above 10. So we're gonna, like, leverage, like, AI Sure.

Ben Orenstein:

As hard as possible all the time. And, like, it'll be ridiculous for us to add even one new person to this company. So, like, we're gonna be, like, 3 people for, like, for years before we, like, surrender and accept we have to have 4, and we'll just, like, automate, like, crazy people.

Adam Wathan:

Yeah. I I think that can sort of work. I'm sure there's good examples of that. I'm still struggling to see, like, where that totally replaces people. Like, I don't think that totally replaces a programmer.

Adam Wathan:

I don't think it totally replaces a designer. I don't think it totally replaces even a customer support person. You know?

Ben Orenstein:

I I just I just really think if you go into this business and decide what your your deal breaker parameters are, you can probably still be quite successful even with those constraints. And if it limits some of that success then who cares because you've already decided that those constraints are more important so if it makes Yeah. $4,000,000 a year instead of $8,000,000 a year because you refuse to hire an enterprise salesperson, fine. Like, who cares? Like, are you having a good time?

Adam Wathan:

Yep. I think you're right. Food for thought.

Ben Orenstein:

Alright. Let's wrap on that.

Adam Wathan:

Yeah. Sounds good.

Ben Orenstein:

We did it. We made a podcast even though you didn't rewrite Tailwind and Rust.

Adam Wathan:

No. Yeah. That can be the episode

Ben Orenstein:

title. Not rewriting Tailwind and Rest. Sweet, man. Thanks for coming by. It was good to talk.

Adam Wathan:

Of course.

Ben Orenstein:

Alright. See you.

Adam Wathan:

See you.

Creators and Guests

Adam Wathan, Creator of Tailwind CSS
Broadcast by