Readable Report

Readable Report is a (now dead) SAAS app from a startup I co-founded with Stephen Erke. It delivered vital social media metrics to your inbox daily or weekly.

Steve's done an excellent write-up on the design process and everything that went into making such a beautiful web app. If you are interested in the technical stack, keep reading.

Frontnd Stack

  • Vue.js
  • Nuxt.js
  • Tailwind CSS

API Stack

  • Node.js
  • Express
  • MongoDB
  • Stripe

Cloud - AWS

  • Lambda
  • Step Functions
  • DynamoDB
  • SES
  • S3
  • So many more ...


Making a modern SAAS app, we knew the site had to be responsive, so we settled on Flexbox to make our lives easier. Tailwind CSS's utility first design makes setting up mobile-friendly layouts with Flexbox very easy.

We separated the site into two main Nuxt layouts; the marketing site and the user admin. Although the two sites were completely different from a design standpoint, keeping them together under one project allowed us to have a seamless user experience when transitioning between the two. It also allowed us to easily share elements of our style guide between both layouts and not duplicate our colors, fonts, or other branding attributes.

Tailwind has some excellent features, like the PostCSS plugin PurgeCSS. It's great for getting rid of unused styles and reducing the file size of our stylesheets. The new Just-in-Time mode (JIT) speeds up how long it takes Nuxt to build and hot reload the codebase.


Vue.js has an excellent Style Guide that clearly defines how components should be named and organized. This guide allowed us to avoid a tangled mess of nested and oddly named components.

The project relies heavily on the principles of a component-based design. Coupling that with its ability to extract Tailwinds CSS classes using @apply allowed us to make reusable and testable components.

We used Storybook to visualize our component library. It's a great tool that allows you to easily view a component in different states and what props it takes. It also helps automate testing, so we instantly become aware of any breaking changes.


Our API uses Node.js, Express, and MongoDB. Although there are probably better alternatives to Express now, there wasn't a clear winner when we started the development of the project. I'm excited to use Nuxt 3, which is currently in beta at the time of writing. It uses Nitro which is built upon the h3 HTTP framework. Express middleware still makes for a pleasant development experience, and it's been easy to add RESTful endpoints to our API.

We chose MongoDB for our storage layer. Mongo is remarkable for its easy-to-use and powerful querying ability. Mongoose also made it enjoyable to define models. The big BUT with Mongo, though, is that it's not a great experience in a serverless environment. There are workarounds for many of its issues, but if I had to choose a DB layer again, I would pick something that works out of the box with serverless microservices.

For authentication, we use JWTs. Nuxt, Vuex, and Node have all made the process fairly straightforward. Every app that Readable Report connects to has to first authenticate via OAuth2 (or OAuth1 — looking at you old Twitter API). Instead of using a third-party library like Passport, we decided to roll our own to have total flexibility. Doing this certainly made me an expert on multiple different authentication flows.


The actual core of our app runs on AWS. This code is proprietary, and I'm not going to go into a lot of detail about how it works. From a high level, though, we use the Serverless framework to deploy to multiple accounts and regions based on the AWS Governance best practices. Jest is used for testing, and our Ci/CD pipeline prevents code from deploying if tests fail. After the initial AWS learning curve, the service was a pleasure to use.