I’ve been tracking the growth of the new coronavirus ever since it first appeared in China in the last week of January, and even more since it spread to Europe around mid February. Initially I’ve been looking mostly at the popular ArcGIS dashboard made by Johns Hopkins University that everyone is probably familiar with.
However, I really wanted to see some charts showing how the numbers grow in each country separately, since just seeing “8000 in Italy” doesn’t tell me much if I don’t remember how much it was yesterday. At that point it wasn’t possible to see that kind of information on the dashboard, and I couldn’t find any other source that showed that in an accessible way.
But then I saw a mention in the footer on the dashboard that the authors have shared all their data (including past numbers) in a GitHub repository in the form of CSV files. So of course I decided to do what always comes to my mind when I have a problem to solve… build a new project :)
And that’s how the Coronavirus charts site was born.
I managed to build and deploy an initial working version in one afternoon and evening – it’s amazing how fast you can build things with the right tools. I used Ruby for the server part – I wrote an import script that downloads the CSV files from GitHub every few hours (though in practice they only change daily) and processes them into a JSON file. There’s a whole bunch of things that need to be done on the data: extract the columns that list the numbers, calculate totals (global count, whole Europe, adding up Australian or Canadian provinces which are listed separately), some naming tweaks, etc. And Ruby is absolutely *perfect* for tasks like that – get this file, parse it, slice it into arrays, filter them this way, map them through that block, gsub some strings with a regexp, and so on – nothing else I know comes close. It feels almost like being Dr. Strange.
The UI part is a small amount of plain static HTML, some vanilla CSS and JS, and the Chart.js library for rendering the charts. I’ve worked with Chart.js before and it’s super easy to get started and get a nice chart once you have the arrays of numbers loaded from the JSON.
Everything else is completely plain JS, no jQuery, no NPM, no React, no nothing. I like to avoid dependencies, and it’s so nice how much more you can achieve with standard JS now than what I remember from my professional web development days, when IE 8 was still a thing. Things like arrow functions,
classList, ES5 Array extensions and so on make coding in plain JS much easier than it used to be when jQuery or at least Underscore.js was a requirement.
Since the first version the code grew quite a lot – I’m adding some improvements almost every other day. You can now switch between linear and logarithmic scales, “daily increase” and “% increase” views, and there’s a pretty complex “Compare Countries” screen that lets you compare up to 20 countries or regions, with a few more options like adjusting the numbers by population size. I also regularly have issues with the source data, so I need to add some workarounds to the import code, including some code that detects places where the number of cases is lower or the same as the day before, in which case I fix the numbers manually.
To my surprise, even though this is just one of dozens if not hundreds of similar dashboards, this seems to be my most popular project ever. I got over 200K visits in March, around 6-9K daily (over 30K on the first day when I posted it to Reddit, while normally my blog gets around 100 visits a day (!). I’m also getting quite a lot of messages from various people all over the world with feature requests.
I’m kind of having fun building this, and seeing that it’s helpful to so many people – even though these are extremely serious matters… but in a way getting busy writing code lets me take my mind off the constant worrying, and is a good way to spend these weeks stuck at home. I just hope, for all our sakes, that I won’t need to maintain this site for much longer… Stay safe out there.
(The project isn’t open source since I built it as a module of this blog to save time, but the JS should be fairly readable if you’re curious.)