Typewind: The magic of Tailwind combined with the safety of Typescript
A type-safe and zero-runtime version of Tailwind CSS

I am a developer from Delhi, India
Search for a command to run...
A type-safe and zero-runtime version of Tailwind CSS

I am a developer from Delhi, India
I think Typewind will have a sequel... Because it's been so long awaited. And this is just the beginning...
Typewind works with CVA. Just use tw instead of tailwind and you should be good to go!
https://www.youtube.com/watch?v=B6FrDu2Qbt0&t=11m24s
Just replace the string classes with their tw equivalents.
Like bg-white text-text would be tw.bg_white.text_text
DISCLAIMER: This might not be the most well-written article since I haven't written in a while and I just wanted to get back to writing with a short article about my experience of the day, so sorry about that I previously used this repository for my...

The release of NextJS 13 brought about a plethora of new and impressive features, with one standout being the updated data fetching and management process. The fetch API replaced the more complicated functions, including getServerSideProps, getStatic...

Looking for a safe and reliable way to authenticate users? Consider implementing magic links. They offer a secure alternative to traditional passwords and can help mitigate the risk of password leaks and forgotten passwords. Magic Link authentication...

Neovim is a powerful text editor that can be customized with plugins to enhance its functionality. In this article, we will explore the top 10 essential Neovim plugins. These plugins can help improve your Neovim experience by adding features such as ...


Well, the people who've read my previous articles know how much I love type-safety, hence someone who loves the t3 stack. Here's Typewind, a typesafe and zero-runtime version of Tailwind CSS, a utility-first CSS framework that can be composed to build any design, directly in your markup.
Typewind is a powerful utility-first CSS framework that combines the magic of Tailwind with the safety of Typescript. It provides a typesafe environment over Tailwind CSS, enabling developers to work with autocomplete, prevent typos, and catch errors at compile time. With zero runtime overhead, Typewind generates custom type definitions based on your app's tailwind.config.js file, making it a top choice for developers who value type-safety. Here's an example of how Typewind works:
https://twitter.com/Mokshit06/status/1617880004846825474
import { tw } from "typewind";
export default function Button() {
return (
<button className={tw.}></button>
)
}
The moment you type tw., you will get autocomplete like so, based on your own custom tailwind.config.js

And, the moment you make a typo:

And it has absolutely zero overhead runtime! Will talk a little more about the features below, but before that, let me talk about how this started!
The whole thing started with one tweet.
https://twitter.com/stolinski/status/1613699772111638530

Then Colin McDonnell tweeted on what tailwind with type safety and proper autocompletion would look like.
https://twitter.com/colinhacks/status/1615154756204523521

Mokshit, the creator of Typewind, sent me this tweet and both of us, at first look were having confused thoughts but the more and more we saw it, the more and more we started getting convinced of it. Looks like Theo had similar thoughts.
We discussed it for some time and he decided to start working on it. Overnight, he was done with the transpilation part and I was just hovering along with him, looking at the things which were being done understanding only 70% of the things happening.
I started working on the docs and working a little on the tailwind transformers started getting me interested in build tools (probably something I want to give a try in the future).
Fast forward to just a few days later, he was done building the package and I was done setting up the docs and the examples and decided to release. However, we had one issue. We couldn't think of a logo. After playing around for hours with different combinations, I thought of a wavy line under wind but said it looked bad and discarded it. Turns out only the font and the structure of the wavy line was bad cause the final version turned out way better.

He released it overnight and it got a lot more response than we had expected! So here's about Typewind, and how you can get started with it:
Zero runtime
Type-safety and auto-completion
CSS docs based on your config
Apply variants to multiple styles at once
No need for additional editor extensions
Catches errors at compile time
Typewind, generated type definitions on Tailwind classes custom to your app's tailwind.config.js after running the npx typewind generate command.
Typewind has currently been tested to work with Vite (React) and Next.JS and you can find them in the examples.
The installation page in the docs is a very good place to start with Typewind.
Install via your favourite package manager (npm/yarn/pnpm).
npm install typewind
npx typewind generate
This will go through your tailwind.config.js and generate types and css docs custom to your app.
After setting up Tailwind, make the following changes:
.babelrc with the following contents:{
"presets": ["next/babel"],
"plugins": ["typewind/babel"]
}
const { typewindTransforms } = require('typewind/transform');
/** @type {import('tailwindcss').Config} \*/
module.exports = {
content: {
files: ['./src/**/*.{js,jsx,ts,tsx}'],
transform: typewindTransforms,
},
};
And you're good to go! Just run npm run dev next time and you should be able to use Typewind inside your app.
Make the same change in the tailwind.config.js file as mentioned in the NextJS example, but the babel change has to be done in the vite.config.js like so:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react({ babel: { plugins: ['typewind/babel'] } })],
});
And, you'll be done setting up Typewind in your Vite application.
Here's just a trailer to show you what it's capable of:
import { tw } from 'typewind';
export default function App() {
return (
<div
className={tw.flex.items_center.justify_center.h_screen.bg_white.text_["#333"].dark(tw.bg_black.text_white)}>
<h1 className={tw.text_xl.sm(tw.text_3xl).md(tw.text_4xl).font_bold}>
Hello World
</h1>
</div>
);
}
All the utility tailwind classes are available in the tw proxy, and can be chained one after another. They can be found in the Tailwind Docs. The - in the tailwind classes are replaced with _ (for eg. bg-red-500 can be accessed as tw.bg_red_500)
import { tw } from 'typewind';
export default function Button() {
return (
<button className={tw.bg_blue_500.text_white.rounded.py_3.px_4}>
Click Me
</button>
);
}
Pseudo-classes like :hover and :focus, Pseudo-elements like ::before, ::after, ::placeholder and ::selection, Media and feature queries and Attribute Selectors are available as a function (for eg. :hover can be accessed as tw.hover(tw.some_class) )
Typewind also have a dark function which is used to apply styles when the user is in dark mode.
import { tw } from 'typewind';
export default function Button() {
return (
<button
className={tw.bg_blue_500
.hover(tw.bg_blue_600)
.text_white.rounded.py_3.px_4.md(tw.py_4.px_5)
.dark(tw.bg_sky_900.hover(tw.bg_sky_800))}
>
Click Me
</button>
);
}
Note that Typewind does not have
tw.2xl()but hastw._2xl()because object keys cannot start with a number 🫠
Tailwind JIT Mode introduced the feature of arbitrary values. You could now apply classes like bg-[#2977f5] and specify arbitrary values for classes by yourself. This can be done with Typewind as well!
import { tw } from 'typewind';
export default function App() {
return (
<button className={tw.text_['20px'].py_3.px_4.bg_blue_500}>Click Me</button>
);
}
This has been answered by Mokshit in this tweet:
https://twitter.com/Mokshit06/status/1617506874773082112?s=20&t=erkUIb_bUjty0KfXzGlrDw

Hope this gets you interested in getting started with Typewind, and gets you to use it in your next project!