Chord Pro - beautiful interactive chord diagrams

How and why I created my first data visualisation SaaS with D3.js, FastAPI, and WooCommerce.

Chord Pro - beautiful interactive chord diagrams

When nothing comes to mind, just make up your own quote.

This brief article tells the journey of my first software release with a price tag. Read on to find out how I launched my first SaaS with D3.js, FastAPI, and WooCommerce.

It all started when I wanted to write a section on Chord diagrams for my book, Data is Beautiful (if you've seen the book, you'll know that my relationship with chord diagrams got a little out of hand). The plan was to compile the book with Python notebooks and follow the literate programming paradigm. This meant I needed a Python package for Chord diagram generation.

Data is Beautiful - Data Crayon
A practical book on data visualisation that shows you how to create static and interactive visualisations that are engaging and beautiful.

I surveyed many Python packages for Chord diagram generation, these included Plotly, Bokeh, and a few lesser-known packages. I wanted something as beautiful as it was interactive, but I couldn't find one with the right balance. I had wanted to take a closer look at D3.js anyway, so I treated this as an opportunity to create my own Python package for Chord diagram visualisation!

Beautiful By Default

Chord Pro started with two core ideas. It was to be:

  • Beautiful and interactive by default,
  • and straight-forward to invoke, with many optional customisations.

With that in mind, I converged toward a single HTML file that rendered an interactive chord diagram. On this side of things, I stuck with HTML, CSS, JavaScript, and D3.js.

I was happy to promote this as "beautiful by default".

For tooltips, I was lucky enough to find and settle on Tippy.js. I was satisfied with its appearance with only minor configuration.


I parameterised several customisations based on my personal requirements and feedback given by others along the way. These included the following four examples.

Multiple Colour Schemes

Bipartite Support

Rich Popups

Reversed Gradients

Creating and Exposing the API

For the server-side I wanted something lean and not too opinionated, i.e. I didn't want to be forced into a particular pattern. I was doing a lot of Python work back then and some options I found were Flask, Django, and FastAPI.

  • Flask: I had some experience here exposing machine learning algorithms over the web. It looked like a good option.
  • Django8: I had only read about Django before, and after some more reading I decided I didn't want to learn the "Django way" of doing things, and the "batteries included" were not of much use for this project. Spoiler for future articles: I end up using Django to create
  • FastAPI: This was completely new to me and the articles/discussions I found were advocating FastAPI over Flask.

FastAPI was very convincing, and I ended up choosing it to build the Chord Pro service. To summarise, the API end-point would receive the data and parameters, process them, load them into the templated HTML file from earlier, and return the HTML as a string.

For the interested reader, this was hosted on AWS using docker containers and docker-compose.

Handling Payment and Licenses

Chord Pro was to use a single-payment model, so that made things a little easier. I didn't want to build and maintain a system for accepting payments and managing accounts/licenses, so I went with something I already understood and had available. I was already selling books in the DataCrayon Shop with WordPress + WooCommerce, so I added Chord Pro as a product and used the WordPress API to authenticate license holders.

I've read a lot of arguments for/against WordPress... Was it perfect? No! But in this instance it allowed me to get payments and accounts out the way fairly quickly. It also allowed me to accept many payment methods with its payment plugins.

Creating a Python Package

Whilst Chord Pro did technically support any environment that allowed for HTTP requests, I wanted to create a Python package to make things easier for notebooks. It was my first time doing this too, but it was easy enough to get something on PyPi that could be installed with pip install chord.

Getting things to behave in notebooks was a challenge. There were so many notebook environments that did things slightly or very differently. The crucial one was the difference between Jupyter Notebook (classic) and Jupyter Lab. I pushed onwards with support for only Jupyter Lab, as Jupyter were referring to it as the "next generation" notebook interface. Another spoiler for the future where I launch I end up supporting Jupyter Notebook, Jupyter Lab, Google Colab, and much more.

Creating a Rust Crate

I'll keep this part brief - but I also wrote a Rust Crate for Chord Pro users!

My Version of Success

I was very happy and flattered with what I consider to be the success of Chord Pro:

  • It actually worked! I used it for my book and in notebooks for my own analyses.
  • I had customers! The feedback was generally great, and people started using Chord Pro and sharing their visualisations with me and others. It was a one-time purchase and not very pricey (originally £5, slowly moving up to £9 as the features increased). The amount of money it generated was enough to support a coffee habit of 4 drinks a month. If I was to take my own time into account, the project lost money!
  • I started posting visualisations on Reddit and three of them made it to the front page! This didn't result in a significant increase in purchases, but it did increase my AWS bills because of poor caching, and plenty of downtime because of a weak server!

Unexpected Challenges

I learned a lot from this project. Here are some things I wasn't prepared for that ultimately led to Chord Pro shutting down.