Behind Franken UI: How Porting Saved My Decade-Long Knowledge

As you probably don’t know, Franken UI is just a “hack” so we can use its JavaScript while using Tailwind CSS. I think it’s a very cool idea and it fascinates me. UIkit JavaScript thinks it’s controlling its original CSS but in reality, that CSS is dead and it’s actually controlling Tailwind CSS. It’s kind of like a zombie! Hence, my framework name.

The idea originally started in 2020, back when Tailwind CSS was just getting started. As far as I can remember, it didn’t have a dark mode and JIT yet. Or maybe they were experimental features at that time. I really thought merging these two would be possible. So I tried it, and I was just really after Tailwind CSS’s utilities. No preflight or anything, just utilities. It somehow worked and I ended up having two builds: one for SCSS and one for Tailwind CSS. It was a mess and I eventually gave up.

The reason I was itching to switch to Tailwind CSS was that SCSS was painfully slow. When I was using Laravel Mix, changing a single variable would take me around two to three minutes before I could see the change. This frustration left me no choice. The only reason I became “efficient” was that I already knew what to change before I hit the save button and triggered the HMR. I really hated it! I couldn’t switch to another framework because I was already familiar with UIkit, and its JavaScript is truly amazing. The programmatic trigger, eventing, and other features are impressive. I don’t need to search NPM for a modal or a carousel because they’re already built-in. Almost everything I need is already there.

By September 2023, Tailwind CSS had become the darling of the frontend world, having matured significantly and offering more features than ever, with improved speed. So I revisited the idea. I had to make it work this time. I thought, why not expose UIkit as a plugin instead of using them together? I tried it, and it worked, but not without caveats.

First, I encountered an issue where some media queries didn’t work, but fortunately, the problem was simply that they weren’t being sorted properly. I resolved this by using the postcss-sort-media-queries package, and the issue was solved. Next, I aimed to make it more modular, allowing me to remove unused components and make the final build leaner.

However, making Franken UI modular posed a challenge: some components rely on others. For instance, the Modal component requires the Flex and Margin components to center it. But you don’t need all the classes from these components; you only need a few specific ones from Margin and Flex. To address this, I created “safety net” classes within the Modal component, which include the necessary classes. This way, you can safely remove the Flex and Margin components, as Tailwind CSS already provides these utilities and does them better.

Speaking of modularity, you can’t just safelist classes as UIkit’s JavaScript dynamically adds classes to your HTML. Moreover, you can’t just “watch” the JavaScript because some classes are generated dynamically. This will result in some components malfunctioning. At first, I manually safelisted all the necessary classes generated by JavaScript, but it was a tedious task. Eventually, I settled for modular components and the “pattern” that accepts RegEx. So, we just need to add the pattern /^uk-/. This means that any class starting with uk- will be included in the final build. This is also the secret sauce to our CDN installation.

The result? We now have a much leaner CSS compared to the original SCSS, and everything is working as expected. Plus, my development time is faster than ever. I’ve also manually added hooks, allowing you to “hook” into selectors and customize them as you see fit. With all these “hacks,” “safety nets,” and “hooks” in place, the problem now is that we’re locked into a specific version of UIkit CSS. Essentially, Franken UI has become a “fork” of UIkit. So, no, Franken UI is not a “custom theme” of UIkit. Fortunately, UIkit has matured significantly, making it unlikely that components will change drastically. Even if they do, I can adjust them easily. In fact, we now have components that aren’t present in the original UIkit.

Time for a Custom Theme

Now that we have UIkit as a Tailwind CSS plugin, which I refer to as the “base,” it’s time to “dress it up.” Last year, I was planning to componentize Flowbite. I really liked the design, but not the implementation, which relied heavily on utility classes. This made it painful to read and maintain. So, I planned to package it as one of my themes. However, halfway through development, it’s now January 2024, and I stumbled upon shadcn/ui. I immediately scrapped Flowbite and shifted my focus to shadcn/ui instead. And in April 2024, I finally announced it on Reddit and HackerNews.

Anyway, if you’re wondering why the early release of Franken UI required jumping through hoops before you could use it, it’s because this is essentially a “hack.” I didn’t want to waste years of my time learning UIkit. So, I invested a couple of months trying to port it, and in return, I saved almost a decade of development time and my learnings did not go to waste. Had I chosen to start from scratch with Tailwind and develop components like modals and notifications myself, it would have taken me years, which didn’t make sense to me when there was already a mature solution available.

Fortunately, installing Franken UI now only takes one command, and everything will be set up for you. Plus, we have a CDN, so you can “test the waters” and, if you like it, upgrade to a proper build later on in your development. And because they come from the same source, you can be confident that your app won’t break. In fact, you can even ship it already, since it’s only about 20k in size.

I hope you’ve enjoyed learning about Franken UI, and I’m thrilled to share it with the developer community. If you’re using Franken UI in your projects, I’d love to hear about it! Your feedback and support mean the world to me. If you’d like to show your appreciation, consider donating to support the project’s continued development. You can also help spread the word by sharing Franken UI with your friends and colleagues, or by starring the repository on GitHub. Every bit of support helps, and I’m grateful for your enthusiasm. Thank you for taking the time to read, and I look forward to seeing what amazing things you’ll build with it!


See all post