Let me set the scene: It's a Saturday. Nothing particularly dramatic is happening. I'm just sitting there, scrolling through my old GitHub repos kinda digital archaeologist, and I find it
— react-calendar-datetime.
My old and abandoned calendar package.
Version 1.3.1 Last update: five years ago. ~100 downloads a month. A couple of themes. A moment.js dependency that probably weighs more than the entire package should.
I don't know what came over me. Maybe it was lazy weekend. Maybe it was nostalgia. Maybe I just wanted to feel something. Either way, I opened it up and thought: let's see how bad this is.
State of Things
Honestly? It wasn't that bad. The core worked. The calendar rendered dates correctly and didn't catch fire when you clicked on it. By the standards of "abandoned weekend projects", this was actually in pretty good shape.
But I cannot look at working code and leave it alone. I wanted to try to optimize it, pour in everything I'd learned over the past 5 years — and if that didn't work out, at least break something :D
So what started as "let me just poke around" turned into a two-week sprint that took the package from v1.3.1 all the way to v3. I have no one to blame but myself.
The First Boss: TypeScript
The first real challenge was migrating to TypeScript. I'd been putting this off for years — not because I don't like TypeScript (I really do), but because migrating an existing JS project to TS is exactly as fun as it sounds. You think you're just adding types. You are not just adding types. You start finding every lazy shortcut you ever took with your data, all at once, while the compiler just stares at you and judges.
It took a while. But once it was done, everything felt more solid. Like the project had grown a spine.
The Dependency Problem (Or: My Obsession With Bundle Size)
Here's something I didn't expect to become a personality trait: I got absolutely fixated on bundle size.
It started innocently. The original package had moment.js. Classic. I migrated to dayjs, felt very smart about it, moved on. Then I started actually measuring the bundle.
Then I couldn't stop.
Then I started resenting every single byte that wasn't mine.
So I removed dayjs too :D
Wrote my own date utilities. They're not fancy — no one's going to write a blog post about my addMonths function — but they work, they're pretty small, and they belong to me.
Final score: zero external dependencies. Bundle stayed around: ~5-7kb gzipped. I check this number more often than I'd like to admit.
The CSS Saga
I moved all styles from SCSS to goober, a CSS-in-JS library. Felt modern. Felt good. 1kb of injected code. Shipped it.
But I couldn't stop thinking about zero dependency library.
And what we have now: CSS Modules. No more goober. I slept better after this decision and I'm not joking. At least for next few weeks :D
The Localization Rabbit Hole
This is my favorite part of the whole story, because it went from "annoying problem" to "surprisingly elegant solution" in a way that felt like cheating.
Originally, locales were only supported for presets — "Today", "Yesterday", etc. and just for few languages.
Then I added dayjs locale support for month names, weeks...
This was... fine, but the list of supported locales was limited, and every new locale added weight to the bundle. (Remember my obsession?)
The more languages I wanted to support, the fatter the package got.
It was a trap.
Then I discovered Intl — the native browser internationalization API. And I just... used that instead.
400+ locales. Month names, weekday names, relative time formatting for presets — all of it, natively, with zero extra bytes. No dictionaries. No JSON files. No dependencies.
I just sat back and stared at the ceiling for a moment. Sometimes the platform just gives you what you need and you've been ignoring it.
The Theme System (My Proudest Weird Thing)
At some point I started making themes. Then I made more themes. Then I couldn't stop making themes. The package now has 18 of them — dark, light, brutalist, pastel, neon — and I love each one like a slightly chaotic parent.
But more importantly: trying to manage all these themes efficiently (bundle size!) pushed me to design a proper theming system based on CSS variables.
Seven variables per theme, one lookup table, predictable output. That system ended up being clean enough that I extracted it into a separate npm package
We all need more NPM packages :D
That's just what happens when you get bored on a weekend.
The Easy Win I Didn't Expect
Migrating from rollup to tsup, and later to tsdown — I expected this to be a nightmare. Build tooling migrations have a reputation, and it's not a good one.
It was fine. It was suspiciously fine. The authors of these tools did a great job and I got to just... configure a few things and move on. After weeks of one thing leading to another, this was a nice surprise.
Where Things Stand
Two weeks of obsessive weekend coding later:
v3.1.2 is out
- Fully modular: toggle time picker, month grid, year selector, presets independently
- 18 themes with a CSS variable system, gradients, shades.
- 400+ locales via Intl
- Week numbers, weekend highlighting, swipe gestures, jelly mode (don't ask, just try it)
- ~5.9kb gzipped
- Accessibility work in progress (there's always more to do here, I know)
Downloads went from 100/month to... more than 100/month. I'm not going to oversell it. But people are using it, filing issues, and occasionally saying nice things, which is more than I had before.
The Honest Conclusion
Open source has always made me nervous — I've tried before and it never really clicked. This time feels different, maybe because I'm not trying to make something important. I'm just trying to make something good.
If you have an old project collecting dust somewhere: maybe don't let it sit for five years. Or do.
Get bored on a Saturday.
See what happens.
The package is react-calendar-datetime if you want to take a look. PRs welcome. Issues welcome. Gentle feedback about my themes collection absolutely welcome.
Top comments (0)