Tailwind CSS: From Side-Project Byproduct to Multi-Million Dollar Business
adamwathan.me
adamwathan.me
When I started my paid online editor for Tailwind CSS ( https://tailwind.build ) in November 2019, and someone posted a link to my Show HN on Discord, Adam replied:
"bums me out when other people get stuff released using my tools before me because i have to invest so much time into building the actual OSS its all built on :/"
And this ruined my happy launch day :)
When I read that they make much more money, I am again in an emotionally neutral state ;)
Congratulations!
This seems like such a destructive approach to software development, and especially open source. It seems pretty obvious that having additional tooling will only boost the popularity of the original project.
What happens a lot of the time is that authors choose open source licenses because they know that's how their project will attract attention. I'm not saying that's necessarily what happened in this case, but it's not uncommon to see authors of some OSS projects seemingly being surprised about how OSS works or what the mentality is expected to be in the project.
Actually I agree with you and it doesn’t make sense to rant and pity oneself on the Internet, but I think this is a natural consequence of what is being made of OSS in general.
I think it's valid to be annoyed about something you specifically allow in your license... So long as you don't try to stop it?
I love that other people are building things on top of Tailwind and I think it’s great. I was only describing my own emotional state and how much pressure it makes me personally feel to finish our commercial projects, and how stressful it is to feel like there’s not enough time because my time has to be split instead of being able to just focus on the commercial tools.
Purely just me commenting on my own stress and being vulnerable among friends, not any sort of commentary on the ethics of other people building things on my OSS.
there's a middle ground. You can be "bummed out" by some of the side effects of say OSS, but also appreciate other positive things about it?
I wrote "ruined my launch day" because I understood him. He (& team) worked on their premium (paid) project at the same time but couldn't release it because they had a lot to do to maintain the main project.
This is a good thing, right? You want to use technology where authors will not sacrifice quality.
It didn't ruin the launch in any other way. My Show HN had ~300 upvotes and #2 Product of the Day on Product Hunt, so pretty good results thanks to the technology & community that Adam created!
You can achieve the convenience of taildwind with plenty of css in js libraries and not make an utterly unreadable un-composable UI component library.
Libraries like this basically exploit the "stick to the platform" mentality in which developers rather accept a poor methodology than a proper one that deviates from the "web platform"
Any chance you can/will integrate the TailwindUI components for those that have purchased them? For me, that would be killer for quick mock-ups and starting points.
Edit: So after looking into it a bit more, and specifically the section in the documentation about extracting components, I understand where they're coming from a bit better. Extracting repeated compositions of utility classes into reusable components or named classes is exactly how I use other CSS frameworks such as bootstrap or foundation. I'm seeing the major difference between tailwind and other CSS frameworks as being the lack of pre-defined UI components. The minimalism is obviously a big advantage for performance, but otherwise I still see little difference between Tailwind and other CSS frameworks.
BUT! This proves there isn’t a “right” way to do things and developers have differing preferences—enough to make 7 figures of revenue.
I think everybody reacts like this at first (including me) :) If you put styles directly in the attribute, nothing is preventing your from using a color that's not part of your palette, nor using sizes that do not respect your UI "flow". Tailwind comes with a (customizable at build time) well-defined sets of colors and sizes.
I recommend watching the 17-minutes long talk "In Defense of Utility-First CSS" for those curious about Utility-First CSS: https://www.youtube.com/watch?v=R50q4NES6Iw
bg:white is exactly the problem. What if I want to change all my white backgrounds to #FCFCFC? I've got the option of going through and updating all my components individually or updating bg:white to be a non-white value.
It's part of the selling point, that config file becomes your design system. They provide a decent one but you are free to overhaul it as you see fit. It works really well.
Read the docs for a few minutes and try it out, you may come to different conclusions than your current assumptions.
This may be the stated point, but it breaks down in many cases. Tailwind, Tachyons, etc. are often a more straightforward, maintainable approach.
One main benefit is to constrain the actual power of CSS specificity.
The other main benefit is that these micro-styles map closely to design semantics, not functional semantics. This is covered in the OP. At a certain scale, the number of distinct functional semantics grows huge, but the design semantics remain bounded.
You get 1 class apply to many nodes relationship.
You only write the css once more (or never again if you use tailwind or tachyons) and reuse it many times.
More thoughtful reply to similar question from Adam Morse of tachyons: https://github.com/tachyons-css/tachyons/issues/12#issuecomm...
Spacing, button styling, border radius, shadows, font sizing - basically the things its easy to get wrong - are already decided for you so its easy to make something that looks decent pretty instantly.
I have also been using Tailwind Builder[1] which is pretty helpful for learning Tailwind and also generating things like menus and basic page layouts pretty quickly.
(1) You have to think less. Try "margin-top medium", look at the result, "oh it's too much", try "margin-top small", look at the result, ok fine. No px-fiddling.
(2) It produces more consistent results (i.e.: things tend to look nicer).
What doesn't win me is that, while I see the increase in development speed this brings, I don't see how would you handle maintainability (i.e.: what happens when the design needs to change?). I suspect the trade-off here is that you just renounce to such redesigns and commit to the idea that you'll rebuild the entire thing if/when the time comes (tech advances so quickly in this space that you may want to do it anyway).
margin-top: margins(xl);
- Once you are in the "margin-top: xxx" part, nothing prevents you from saying "just this time" and writing some px (or whatever) value, either because you don't remember the options at your disposal, because none of them feel exactly right or whatever. Using tailwind you would have to create an entirely new size definition, which is a big hassle. That is, using scss does not actively push you to this particular "pit of success" whereas using tailwind does.
- Responsive handling is much more verbose in scss. Consider "sm:mt-2" versus "@include responsive(sm) { margin-top: margins(2) }"
Once you get over the small learning curve, it gets to be VERY productive. Think of it as writing CSS at a slightly higher level of abstraction. That abstraction being in not having to edit two separate files or areas of your HTML document (unless you want to abstract further with @apply).
Not having to go through the 'define identifier in element, then define in StyleSheet' workflow. With Tailwind you get the most commonly used style definitions pre-defined. But not so high level that it LOOKS pre-defined. Giving you room to customize greatly. How could it not be faster?
I recently completed a theme in Tailwind, mostly to get the hang of it: https://planflow.dev/free-themes/. And managed to go from idea to finished theme in about 4-5 days. That's the fastest I've ever done it.
Thanks for the heads up!
But the web environment has changed. React and Vue introduced modularity of style and structure with components. So I can just use a Button component across the website instead of a CSS class. This means CSS is mostly written only for that specific component or file. So tailwind and those other css-in-js have sprung up to bring both into one file.
And I’ve been using tailwind for about a year now and can very quickly throw together most layouts. It feels very smooth to be able to define the div and it’s style on one line at the same time. And short classnames like “m-4” and “w-full” are also more succinct than the raw html style property.
It also works perfectly fine with server-rendered pages in my experience. Any templating engine worth its salt will allow you to extract fragments or partials.
However, please avoid the snark. It diminishes the discussion. It took me a long time to come around to the idea, and the snark of (some of) its supporters was precisely part of the reason for that.
Positioning, sizing and styling is very easy, especially when you can control all those aspects with variables in your view classes.
You have to try it to understand it.
Keeping your CSS and HTML completely separate just doesn't work in practice though e.g. we still need to throw in ad-hoc wrapper `div`s because CSS isn't powerful enough to do what we want, we have to pollute the HTML with class names that have little semantic relevance outside of styling as we're creating the styling, and it's a pipe dream that designers can jump in and help with the styling without help from the programmers.
It's a nice idea but keeping HTML and CSS 100% separate hasn't panned out - people need to accept that and stop promoting the separation of CSS and HTML dogmatically. The reason there's so many CSS frameworks and different ways to do the same thing on the frontend is a strong evidence we're still figuring out the best way to do things. CSS has been out for around 20 years now and it still doesn't do what we need it to.
Also, if you're keeping your data (like blog posts, product information) in a database, your data is already separate from your UI/styling. What are you gaining by splitting up your styling further? Is a similar level of splitting up done in other (non-HTML) UI frameworks?
<div style="padding: 20px;" />
and <div class="p-2"/>
it's like variables for styling. Instead of throwing some random numbers developers can bump the numbers up p-3, p-4 or text-red-200, text-red-300. It helps to keep things consistent.For a simple website semantic HTML or SMACSS can work, but for any semi-large scale websites with many variations of components it'll quickly descend into specificity hell. Using atomic classes keeps the specificity flat, and it avoids an entire category of errors that haunts many large projects just by making the styles sort of self-contained (you still need the stylesheet).
Of course there are other approaches to this problem such as "namespacing" your CSS using BEM and dynamically generating class names using CSS-in-JS, but using atomic classes is a very maintainable way to style HTML, if a little hard to read.
IMHO it is really quite similar to using HTML attributes for styling or inline styles. Maybe those wheren't actually such terrible ideas. They are the easiest thing for a beginner to understand, so maybe they are actually the easiest way to reason about styles for non-beginngers too.
What makes it different is: - higher level component frameworks: wether you use react, vue, web components or use a templating engine in a component pattern, that is all the abstraction you need. Introducing an additional layer of abstraction/reuse with shared CSS classes is uneccessary overhead. - constraints: the scales for spacing, color, typography and everything else that you configure for tailwind lead to nice, consistent designs without much effort. I think that would be a key problem when just using inline styles.
I'm reminded of LogoJoy - a single founder company that started sucking in huge amounts of cash revenue, which the owner spent on employing people and offices and growing a company and getting investors who recommended they rebrand, destroying much of the value and revenue of LogoJoy. I bet that founder is wishing he stayed a single person company and just banked all that cash. https://betakit.com/looka-lays-off-80-percent-of-staff-as-fa...
So I wonder which way these guys will go. Will they bank the cash and buy houses and have a quiet and happy life, or will they spend it on employing people and growing a business and getting investors to try to make more money?
We keep a few hundred grand in the bank as a payroll cushion but everything else gets pulled out and put in our personal bank accounts. We're both millionaires and financially independent at this point, and are only continuing to do what we do because we really enjoy it. We're building a small team so we have more freedom to pursue other fun R&D-style projects while still delivering on what our customers and community are asking for.
It's entirely possible that this may be your one and only big financial win in your entire life.
So make sure you bank $5M cash each before spending the money ...
Consider cutting down to no employees if practical. I'm not saying you should do that, just that you should consider it. Employees cost huge money.
Then, once you've got all that sorted out, if you want to do the big expansion thing .... go for it.
It could help with the creation of interactive components for all ecosystems, like those that are tightly coupled to a specific ecosystem considering that it's not only frontend frameworks, but also backend frameworks that have their own LiveView version or way to do components now (e.g. Elixir Phoenix has Surface which is like writing backend React components, Rails has view components).
Supporting all those combination yourself seems daunting, and it would suck to see components for React or LiveWire/Alpine, but not other ecosystems that aren't covered by the skillset of your team.
So happy that we just bought a team license for Tailwind UI.
Too many marketplaces exist where there is no value-add instead of sitting in the middle.
One of the reasons I bought Tailwind UI is _because_ Adam & Steve knew what they were doing, had good attention to detail and because I'd already purchased Refactoring UI. I'd worry that with a marketplace the quality would drop, no matter how much guidance you give.
Hoping instead that we can find the right small team size that lets us do more of this in a first-party way, and selectively support the tools we find people ask for the most.
Could definitely see a world where we work with experts in different technologies to port our stuff over and maintain it under some sort of retainer agreement though, just don't see us ever giving up any of the actual UI design or initial implementation work.
I bought into it because as a designer I got interested in SaaS, and my impression was/is that you have a perspective on design edgecases that most traditional or semantic html devs lack because they're more focused on content sites and blogs.
Keep up the work, but don't forget smaller frameworks. Your last suggestion with the retainer agreement sounds good!
If you’re an open source maintainer, this is a pretty good example of how to monetize your work.
For simpler projects there's tachyons as well, which shares a similar philosophy and is a bit simpler in scope.
If you haven’t tried it, you should. It definitely looks really silly (inline styles?!?) but it’s so powerful.
I've been using Tailwind to build a moderately complex app, and for me the killer feature of Tailwind is that _most of the time I don't have to think in CSS_.
It's not that I can't think in CSS - I've written lots of CSS over the years. However, as someone putting together a UI, I want to think in terms of slightly higher-level constructs. With Tailwind I almost never need to think about specific pixels values, weird browser quirks, or how breakpoints are handled. Instead, I can think almost entirely about how to achieve the correct behaviour.
I work with ClojureScript so I have hot reloading and fast feedback, and I can build a moderately complex UI component in a few hours. Not having to context-switch into CSS really helps me to stay in "flow". If there's some very specific design feature that I need, then I can still write some custom CSS, but this is sufficiently rare that in a 10k SLOC project there are 33 lines of hand-written CSS.
I'm a backend dev and, while i can do frontend - and i usually am picky about design, i don't _want_ to design, especially during prototyping.
I'm planning on learning Tailwind for post-PoC styling, but buying the Tailwind Builder (Lifetime) for early PoCs to get styling out of my way.
I really like the offering of not just templates, but transitioning my templates into my final product _when i want_.
But, i haven't used any of it yet. We'll see, but it's definitely worth the $99 license (to me) if it even remotely pans out.
If I could figure out a value-stream like these two gents, then my OSS work would be on another level. This isn't your classic "Indie Hackers SaaS" or viral eBook stuff.
Hats off to you. I'll be the first to buy your eBook :-)
<div class="profile-card"></div>
.profile-card {
@include tailwind-css-1
@include tailwind-css-2
...etc...
}
This way your html has semantic classes but the definition of the classes uses something like tailwind instead of raw CSS. One level of abstraction. Seems the best of both worlds?TailwindCSS and TailwindUI have been huge time savers for my project. It’s nice to hear the origin story!
> One of those decisions was what to do about the CSS."
And it worked! Adam is living the dream.
We are really pleased for you.
You really are an inspiration to us that made us create the idea of https://Frontendor.com HTML Library and keep going to the end and not giving up about our dream.
Thank you so much. Frontendor Team
As a developer, Tailwind UI is a god send, I've been waiting for years for a great looking CSS framework with pre-made components
(Also, they had a pretty big audience already after selling Refactoring UI which is a really useful book for developers that can't design, like me)