Build fast, flexible calendars with Flash Calendar

UsersDevelopment13 minutes read

Marcelo T. Prado

Marcelo T. Prado

Guest Author

Flash Calendar is an incredibly fast and flexible way of building calendars in React Native.

Flash Calendar

This is a guest post from Marcelo Terreiro Prado - a Senior Software Engineer at Brex, where he works on uplevelling the front-end stack. He’s passionate about building beautiful experiences that delight users.

•••

When I joined Brex 3.5 years ago, my manager asked me to build the mobile app date picker. I was stoked, but not for long. I soon realized the chosen library had many performance and polish issues. Three years later, while working on a side project, I encountered the same problems. That’s when I decided to take matters into my own hands and build a better alternative: Flash Calendar.

What is Flash Calendar?

Flash Calendar is an incredibly fast and flexible way of building calendars in React Native. It was built from scratch to provide the most performant experience possible.

With Flash Calendar, you can easily build calendars and date pickers that look, feel, and perform beautifully. Among its many features, my favorites include the built-in dark mode, localization, infinite scroll support, Expo compatibility, date range hook, and the composable API.

I originally built Flash Calendar for Moni, my Brazilian-based personal finance app. One of my goals with this app is to create the most polished and beautiful experience I can. This often means sweating the details and going the extra mile if needed. When I first wrote the date picker component with an existing third-party library, I realized there were quality gaps I couldn’t afford to slip into my product. Without getting too deep into the details, my top three concerns were: performance, bloat, and beauty.

This is when I told myself, “Yes, you will really write a calendar from scratch. Buckle up!”. After sharing on X my initial prototype, several people showed interest and that’s when I decided to build Flash Calendar as my first serious OSS project.

I built this library for people like myself who deeply care about performance, polish, bundle size, and customization. If this resonates with you, give it a try. While still early in its lifecycle, Flash Calendar is production-ready and already used across apps of all shapes and sizes - from my side project to multi-billion-dollar companies like Brex. The latest v1 release marks the stability of the package.

How does Flash Calendar work?

Flash Calendar was built with four principles in mind. In this article, I’d like to expand on two of them: Fast and Customizable.

Fast

Two key pieces provide Flash Calendar superior performance: scrolling speed and rendering optimizations.

Scrolling Speed

Flash Calendar uses Shopify's FlashList internally as a drop-in replacement for FlatList. Using FlashList as its scroll primitive is one of the main reasons the library performs so well while scrolling. Also, by building on top of the well-respected library, Flash Calendar also inherits Shopify’s performance-tuning guides. You'll feel right at home if you already use FlashList in your apps.

Rendering optimizations

Another trick heavily used by Flash Calendar is avoiding unnecessary re-renders. While the render phase for React is usually fast enough, this becomes an issue when working with large lists. For instance, imagine selecting a date range and re-rendering five years’ worth of calendars. That’s roughly 1800 React components (5y * 12m * 30d) updating – frame drops are likely to happen.

Flash Calendar avoids re-renders through known React memoization techniques; in some cases, it even bypasses React for better performance. Check out the video below and notice how only the affected dates re-render. This means your component stays responsive no matter how lengthy the calendar list is.

Flash Calendar performance demo

Customizable

The library's default styling is beautiful – it supports dark mode out-of-the-box and has a minimalist but pleasant aesthetic. However, Flash Calendar also had to offer a powerful and flexible styling API. That way, it could be used by companies that follow a particular style guide.

This requirement was also the key reason I chose a composable API design. I knew companies would want to build their calendars, so I made that experience as seamless as possible.

As I considered the best way to demonstrate how customizable Flash Calendar is, I had an idea: what if I showed how you could build both a future-looking and a nostalgic calendar? This is when the “From Linear all the way back to Windows XP” tagline was born. Without a doubt, this was one of the most exciting parts of the journey!

After publishing Flash Calendar’s first release, it was incredible to see the community share their creations, such as this beautiful minimalistic calendar by Gary Chiu (@garyxchiu):

Gary is building Hyperlog, a new mobile workout tracker. When asked about his experience with the library, he said, "It's a calendar component done right — composable, flexible to style however I want, and fast! The composable pattern is so nice!"

Calendar building challenges

Most date picking and calendar libraries I analyzed offered too many features. It’s nice at first glance, and works great for prototypes and side projects. But over time, I realized I just needed a subset of the features, and could use a leaner approach. I observed the existing libraries bloated my app’s bundle-size with dependencies that I didn’t need. For instance, I use date-fns in Moni, but these libraries would install moment-js as a side effect. That’s just wasteful!

I knew I had to be very minimalistic with my tools and avoid external dependencies at all costs. Flash Calendar ships with just one 200-byte event-emitter dependency that helps improve rendering performance.

The most time-consuming part was writing my own date functions - yes, I did that. As any seasoned engineer knows, dealing with dates and time zones is frequently one of the most challenging parts of the job. To make this safer, I took inspiration from date-fns and crafted a lot of unit tests. Between manually written and generated tests, there are close to 9.000 expect calls (it’s over 9.000!). This gives me confidence the functions work and produce the same output as date-fns.

Finally, as we all know, building an NPM library is only possible by fighting the build tools. As such, this was definitely a painful step. Flash Calendar uses a monorepo architecture and even though it leverages well-known tools, scaffolding the project took a lot of time (and that’s my third time doing it). Making your linter, type checking, and bundler work together across several packages is a lot of work.

In retrospect, I could have chosen simpler alternatives like react-native-builder-bob. On the other hand, the Turborepo team is actively working on better documentation, so there’s a good chance this will get better over time.

Tools for great developer experience

“We shape our tools and thereafter our tools shape us” - Father John Culkin, SJ

I really wanted a great local development experience for Flash Calendar. I knew that others and I would work on this repo for a long time to come and therefore, the DX needed to be great. Some of the tools that make this possible are:

Bun

I fell in love with Bun’s performance last year and having Bun as Flash Calendar package manager and test runner felt like the perfect match. The fact it runs the entire test suite (with ~9000 expect calls) in ~125ms is insane - I profiled it against Jest and noticed it was 96% faster.

Turborepo

Turborepo works as a monorepo orchestration tool. While a simple NPM library doesn’t need something as fancy as a monorepo, once you add a kitchen-sink app, a storybook app and a documentation website, the architecture makes more sense. It might take some time getting used to it but once you grasp the key ideas, the DX is great.

Storybook

Flash Calendar is a heavy user of storybook. Every feature, code example and bug fix is extensively tested with stories, ensuring the library works exactly as advertised. One of my favorite features is the ability to load stories from multiple paths. This allows story files to live in different folders, but appear grouped together.

Expo

Before starting Flash Calendar, I knew first-class support for Expo was a must. Expo is used by Moni and Brex and inside Flash Calendar’s repo across two projects: the example app and the kitchen sink app.

The example app works as the Storybook host, which I use in the regular development flow. The kitchen sink app is a blank Expo app, with just Flash Calendar and its requirements installed. This enables testing the library in the “real world”, ensuring consumers won’t run into errors while installing and using the library.

Another thing I love about Expo is their over-the-air (OTA) updates. Since Flash Calendar is a JS-only library, you can ship it through an OTA update and skip the need for a binary release, making integrating with the library even easier.

Advice for leading an OSS project

Leading an open-source project is a new experience for me and one I'm learning from daily. The “building” phase was fast (it took 14 days between the first commit and the announcement tweet), but there’s a lot more involved in maintaining a healthy package. Here are three tips that help me manage the repo:

1. Documentation

First, I focused a lot on documentation. At Brex, I worked on design systems for a while and learned the value of great docs. For Flash Calendar, using Docusaurus allowed me to fully focus on the writing aspect of the documentation. I wanted the docs to be visually pleasant and easy to copy and paste. This is why every example often comes with code examples + screenshots/video.

I also used tricks to improve IDE discoverability. For instance, all props are prefixed with “calendar”, allowing consumers to differentiate which props come from Flash Calendar and which from Shopify’s FlashList (since it extends FlashList).

2. Being your own consumer

The fact that I had an app of my own to test Flash Calendar was key. Being both the author and the consumer is a powerful position since you know in advance how people will integrate and use your library. Besides, it’s safer to release changes. I can test an alpha build of a PR in my app first before releasing it to the world.

3. Project management

I have a lot going on: my full-time job, side project, and now the open-source package. Therefore, I must manage my time well. One thing that has helped me is leveraging Linear to track Flash Calendar’s development. I already use Linear for Moni, and it was a great idea to treat the library as if it were a standard project.

I'm really enjoying this workflow since it keeps me honest about my progress. The fact that Linear syncs with the Github repo and automatically creates issues for you is just icing on the cake.

What's next for Flash Calendar?

Now that Flash Calendar is officially on 1.0.0, I can consider new functionalities. In addition to addressing issues like font-scaling support and adding docs for horizontal swiping, people asked for a Week component. These are likely the library’s next steps.

One surprising but delightful aspect of building an open-source project is how people contribute back to the project. It makes me smile when I wake up and see a PR from a new contributor. Thanks to @danibonilha, @bpingris, @dannyhw and @alirezahadjar for being the library’s first external contributors 🙏🏻

If you think Flash Calendar is missing something, don't hesitate to contribute. I would love to have more help building the next generation of React Native calendars!

react native
calendar
open source
developer experience

Create amazing apps, in record time with EAS

Learn more