The Hidden Value of Magic (and Tailwind CSS)

As I’ve begun the full rewrite process of my hobby project, I’m astounded how much I’ve been learning from all kinds of things every step of the way, by carefully analysing the old, and making lots of effort in engineering and designing the new. What follows is one of my latest learned lessons that connected some dots between 15 years of working with the Web.

Python is my favourite programming language, and I’ve always stayed firmly with the Django camp as opposed to Flask or any other gazillion alternatives. In the early days of Django (like 15 years ago) I also had lots of reservations against Rails, mostly because I was young and stupid, but also because it had too much magic. The more I’ve worked with JavaScript the more I’ve learned about good architecture and best practises from bad examples, and my views on magic have changed somewhat.

JavaScript is a fascinating language. ECMAscript 2020 is the ultimate lipstick on a pig. The core language is such an awful mess, yet the new syntax is pretty powerful and the modern tooling built around it is truly amazing and wonderful to work with. And as the tools have gotten so much better in a very rapid pace, the community is starting to get the libraries and coding conventions in a better shape as well.

Vue 3 is a great example of this. It’s built totally from ground up using TypeScript, designed with an open RFC process taking feedback from the whole community, and Evan You has done a lot of work shaping the end result into something that’s actually designed to be used and not only something that looks good.

The work on my new Vue 3 project template has advanced to list screens which need various list components, preferably in a form of a powerful datatable component. I had to completely drop the project for a while to get a better understanding what I’d really want here. Today I finally had an epiphany; the thing that’s most wrong in the current Slipmat design are the numerous different random third-party components that even though styled to look somewhat (but not exactly) similar, they all feel different. And this exactly is my issue with glue-in frameworks like Flask as well. Even though the various parts can be easily used together, there’s always something missing compared to tools like Django where everything is built to work together.

So now we get dangerously close to the infamous not invented here syndrome. If gluing up various third-party solutions yields bad results, then surely we should write all components ourselves? Well, no. Firstly, always prefer an existing ui library (like Vuetify for Vue/Material Design) over building anything yourself. Secondly, –and this is again something I realised today– properly architectured third-party components can be not just almost but precisely tweaked to fit your design. And whenever using them, you should take the time to do that design work properly. The main problem with inconsistent Web UIs is handwritten CSS. Whenever a non-designer needs to invent their own styles, the end result will end up looking something that almost matches the thing they did yesterday, but only almost. And this is where Tailwind CSS shows again how brilliant the utility-first idea really is; there is close to zero handwritten css needed for most Tailwind projects which automatically restricts you to a relatively small amount of professionally curated choices. The end result looks automatically not-very-bad and with some tweaking it’s not hard to get absolutely spot-on. (To be fair, it’s not easy either, but unlike trying to manually come up with CSS, it’s way easier!)

After I watched Adam Wathan build this select component, I was convinced that this would be the way I should build the few components (button, toggle-switch, modal, toast, data table / list component, datepicker, tag input) I need for the Slipmat rewrite.

(Yes. NIH. I’d love to use some third-party library here but at the moment there just aren’t too much to choose from for Vue 3 and Tailwind.)

Datatable experiment

The first iterations don’t need to be anything too fancy so I’m confident that building all of these from scratch instead of trying to modify third-party alternatives won’t be an issue. I’m also fully prepared to switch to using @tailwindui/vue or some other library in the future if maintaining these eats too much time. Just to get a feeling of what the API would maybe feel like I created an experiment project and pushed it to GitHub (not GitLab because on GH I get Dependabot updates automatically).

So this story has been a bit of a rambling journey from back in the early days of Web frameworks to Vue 3 and Tailwind CSS. What I’m finding common between all these projects is the meticulous attention to detail regarding almost every aspect of the tool, especially to API design. Great tools aren’t born by accident, they are engineered. And after working with JavaScript for few years now I’m starting to appreciate the metaprogramming powers of Python which makes it possible to write super clean —and somewhat magical— APIs. A good amount of magic really makes a difference in developer experience when it’s done right. I still do think that having a pluralization engine that automatically fetches one Octopus and many Octopi is way too much but I also do appreciate the attention to detail in Rails the more I get to see language restricted not-so-beautiful designs in JavaScript land.

So the lesson of the day: invest in API design and the most value from magic comes from those situations where you can’t see it.