How I half-accidentally committed to an open-source library for the rest of my life

By Joonas Kykkänen, Software developerFeb 23, 2021 • Read time 8 min

Here’s how I went from a simple problem and an even simpler solution to owning and maintaining an open-source library for the rest of my life. This was something new and exciting for me, a first-time open-source coder, and it was very different from my work as a consultant where my audience is the client, not the entire programmer community. Read on to find out what I learned along the way (including the facepalm moments), and how I feel about the project now. 

What I coded and why

I started using the Tailwind CSS library in 2017 and back then it was rather new, though now it has developed a lot and gone pretty mainstream. Unlike component-based CSS libraries like Bootstrap, Tailwind CSS is a utility-first library. It doesn’t come with ready-made card components but instead has utility classes for things like spacing, typography and color that you can then use to build your own components. 

One group of CSS classes in Tailwind is for box shadows, a type of drop shadow. Tailwind has five variations of the drop shadow, which indicate the component layer hierarchy on the website or application.

I often use Google Material Design to guide my decisions if there is no other design language available for a project. One of the elements I often end up using is the elevation guidelines, which come with a handy table of default elevation values that I like to use to make sure my components follow some sort of elevation hierarchy. The problem is – or was – the Tailwind CSS library has only five hierarchy levels for drop shadows, where Material Design has 24. So, long story short, I coded a plugin that allows me to have all 24 levels defined by Material Design in my Tailwind library.


Making it open-source and gaining publicity

From the beginning, I decided to do this as an open-source project using Wunderdog-supported open-source hours. First I just added the elevation classes to Tailwind and used them in a couple of projects I was working on. I made them into a CSS library and published it as an npm package. From there, I added a feature or two to improve the library, while still keeping it very simple. 

I found the new tool very useful and began to wonder if it would be nice to have a few more users. I found another open-source project that listed handy plugins for Tailwind CSS so I submitted mine there and a couple of developers found it. I was off to a good start and had the few more users I was hoping for!

Soon after, I found out that someone had created a Material UI package for another JavaScript library, Svelte, that uses Tailwind CSS, and had picked my library to enable the drop-shadow elevation class feature, which increased my weekly downloads by a hundred. Yay, my plug-in was clearly in demand!

Then things started to get real. I noticed two issues reported in GitHub regarding my library, suggesting I add a few features and fixes. Now I was officially maintaining a publicly used npm library, so I had to start thinking about what to take into account in the process – this was something very different to the customer projects I’m used to working on as a consultant.

What I learned maintaining an open-source library

From the very beginning, I decided to commit myself to this experiment fully. A top priority for me was to signal high quality: I wanted my test coverage to be 100% and for my GitHub site to show a test coverage badge as a sort of quality certificate.

Another thing I had to study in order to guarantee high quality was semantic versioning and the logic behind it. Semantic versioning uses three levels, e.g. 1.2.3, with the numbers referring to major, minor, and patch version edits respectively. Patch is for minimal fixes, minor for things like new features, and major for edits that are needed so as not to break the code, e.g. if the name of a function changes. I wanted to make sure I communicated accurately whenever features, fixes, and updates were made to my library.

Thirdly, I needed to add a changelog – a text file that lists all versions and what was updated in each version – and to do this I needed to learn the specific format used. In a customer project, there’s no need for changelogs; if there’s a change, we go through the change in a sprint review and that’s it. Now I had to make sure that the version history is correct, the updates and fixes are clearly described, and it’s all written in the right format. Changelogs might be rarely read, but just in case mine was, I wanted it to be accurate. 

How to handle agreeing and disagreeing with reported open-source issues

The two issues reported with my plugin were the first two issues I ever received from any open-source project. For the first time ever, I was tech support for a tool I created myself. That felt exciting and got me thinking about the responsibility that comes with creating commonly used open-source libraries.

The first issue requested me to add a feature where the drop shadow color could be changed not only using the RGB color scheme but HEX too. I thought it was a great suggestion and went about coding it. However, in a customer project, I have direct contact with the customer so in any feature request I can just ask – often face-to-face if it wasn’t for COVID – “Is this what you mean?” Now, the issues were in a text format on GitHub so I needed to pay extra attention to getting it right. I wanted to make the fix they were asking for and avoid coming across like a fool by just jumping into coding without making sure I’ve understood the issue properly. Just to be sure, I asked some clarifying questions.

Suddenly, my work was visible to the entire programming community, not only to customers who hire me as an expert in my field. This felt quite exciting, adding another dimension to my coding. Anyone could see, comment, and even judge my work. I couldn’t just state how things are done but instead, I needed to discuss, justify, and be extra delicate with my replies. 

The other reported issue asked for a feature in which the elevation class drop shadow and color could be combined endlessly – defining each color to each elevation class separately. However, enabling that many combinations create an immense amount of CSS code that the user needs to download to their computer, which would break the idea of the simple and light library I created. I disagreed with the request. Now, I had to think of a polite way to express that I won’t be making such a feature and justify it clearly – again, all in public.

The facepalm moments of a first-timer

The process had its facepalm moments as all learning processes usually do. The first one for me was when I realized that in npm packages the proper way is to publish only the code the user of the library will use. I used lots of code to for example run tests when developing the tool but that’s not important to anyone actually using the library – it just increases the size of the file. The project needs to be cleaned up before publishing – obviously!

Another one was when I made a minor fix that in theory could break the code if not updated, making it a major version update. The version had been zero something and I wanted to update it to be 1.0.0. There’s a sort of an unspoken rule in semantic versioning that if the major number is zero, no rules apply; semantic versioning rules only start applying from one and users of the library should take this into account. As I wanted to provide high quality I needed the version to be 1.0.0. to indicate that all proper semantic versioning rules apply. I was happy to finally update it. As I ceremonially released the update, I soon noticed I had deleted the version’s readme file, so no information about the version was available. I humbly went back to make edits and published version 1.0.1., just two minutes after the first big release.

So, how do I feel about it?

I have realized just how much time and energy it takes to maintain an open-source library – and it’s a lot! Mine is just a small tool with some hundreds of users so I can’t even imagine the workload to maintain one of the popular libraries that are used worldwide. I totally get the point of writing a plea in readme asking for a donation towards the team of people responsible for maintaining them. Nowadays I have another level of respect for that.

Currently, my inbox has some 2,000 unread emails about pull requests from Dependabot. Reported issues also appear in my email but easily get lost in there, so I’ve made an automatic reminder to check possible issues on a weekly basis. Somehow I have half-accidentally made this project a part of my life that reminds me of its existence on a weekly basis. There’s a new layer of responsibility to my coder life – I’m stuck with this project, but in a good way. The more people that use it the better; the joys are far greater than the stress it causes. It’s almost like a pet dog – a long-term commitment that you have to clean up after and take out even though it’s pouring with rain, but the companionship and joy it brings you makes it all worthwhile!


Joonas is a senior software developer at Wunderdog. This project was done as part of the Wunderdog open-source program. Access the Tailwind CSS plugin here.


If you're looking for new challenges, we're here for you!