Learning Lab
Published in

Learning Lab

Building a SaaS with TypeScript, ExpressJS, and SOLID principles: the good the bad and the ugly

#14 — Learning how to create a clean project with TypeScript following the SOLID principles

  1. By using TypeScript

How to learn the SOLID principles and TypeScript?

Once again, I followed the Learning Lab methodology.

  1. Defining the scope of the topic
    The scope of this topic is understanding the SOLID Architecture and how to use TypeScript (and create types of course)
  2. Choosing a learning resource
    I found a lot of interesting resources from different places, you can find them here: https://learn.uno/learning/typescript-solid/
  3. Defining a project
    I took one of the projects I had in my backlog of ideas: a SaaS that aggregates sales reports from Google Play and the App Store. I called this project Revenual 💵.

Why SOLID & TypeScript are good co-workers?

What is TypeScript about?

TypeScript is an open-source language created by Microsoft, it has the same syntax as JavaScript but it adds Types. Therefore you can have more robust code, and TypeScript transpiles to JavaScript, if of course there is no type errors! This is something that you cannot have in JavaScript and what makes it so amazing.

What is SOLID Architecture?

SOLID Architecture or SOLID Principles are a set of principles to make your code more re-usable, easy to maintain, and less coupled.

Source: https://devopedia.org/solid-design-principles

How to build a SOLID SaaS from 0 to 1

Here is the process I followed to build my SaaS!

1. Find a problem to solve 🤔

I previously built some mobile apps with NativeScript VueJS and Flutter with In-App Purchases. The problem is that Google Play doesn’t give you an easy to digest report and, also, I had to go back and forth between iOS and Google Play platforms to see my sales per product. Moreover, because I have my own company I need invoices for my bookkeeping. I really wanted to automate this process.

2. Check what are the existing alternatives

Before answering your problem, check if there isn’t anyone who has answered it already, how they have answered it, and their pricing strategy, to be able to be different from them! In my case, in my initial research, I didn’t find any direct competitor. After building the core of the app a friend of mine found a competitor. But the competitor is targeting more subscriptions and not any sort of sales!

3. Check the feasibility manually

Before starting Revenual, I built a proof of concept just to check if the project is technically feasible. Basically I needed to know if there was a way to download sales data from both Google Play and the App Store. I found a library called “apple-reporter” to do it easily from the App Store, and I managed with Google Play after a bit of struggle. I built two small scripts in JS to prove it and it worked 🙌!!

4. Define the UX Flow

I based the UX Flow on my user’s need. I just took a paper and a pencil and draw it. I thought about how I would feel as a user, and update it until it would satisfy me.

5. Define the architecture of the information

Once the UX is more or less defined, I define for each of the pages the EXACT content that needs to be written (with the exact text)! This will shape the UI but also helps to define the data model of the app.

This is an example of the content I wanted to display in the sales reports page.

6. Draw the wireframes

Once you know what to put on each page you can draw the UI of each page. You can find a part of the UI/UX of Revenual. As you can see it’s both UI and UX to go faster. Also, I used the content defined at the previous step!

Here is one parts of my UI/UX. Pretty ugly right ? 😅 The most important is to be able to read it yourself!

7. Define the pricing model

At some point, you need to define a pricing model. In my case, I started with one model based on the number of Google Play/App Store accounts connected, but after getting some feedback I changed it, to something related to the number of products sold that scales with the user. Try to get feedback as soon as you can. For both the pricing, the UI, the idea, anything. Don’t be shy, share your idea, no one will steal it.

8. Define your data model

Based on all your previous info you can now build your data model, you know that you have:

  • subscription
  • accounts
  • reports

9. Chose your stack

Now we have the data model and the information of architecture, we need to choose a stack. What I usually do is to take something I am the most familiar with that fits the need of the project. The app should:

  • Download reports, unzip them and parse them
  • Parse reports
  • Save reports
  • Display reports
  • Charge the user
  • TypeScript
  • Express.JS
  • MongoDB
  • Stripe

10. Define the architecture

From the UX, and the data model defined before we can do a few things:

  1. Defines the routes of the website
  2. Split the project in services (user, accounts, reports, invoices, subscriptions)
  3. Define interfaces (here is where you can feel the power of the SOLID principles and TypeScript)
  4. Define where you need which design pattern
  • To not build an API but to render pages (to avoid having to build a frontend app and a backend), but to be able to change it easily in the future

11. Write code 👨‍💻

Now everything is defined, I just wrote the code, tested on the fly with my data, fix the bugs, handled errors... I’ve also learned a lot from the following link, explaining all the best practices.

12. Write tests

I wrote some simple tests for the most critical part of the code only, such as parsing the data from Google Play, App Store, and the report generation.

13. Design the UI and implement it

As concern the UI, I was highly influenced by this book that is pretty amazing: https://refactoringui.com/book/

14. Make users test

Last but not least, I tested with real users and fixed the bugs.

15. Release

Time to release now 🚀, on Product Hunt, Hacker News, and Reddit to start with!

The Good the Bad and the Ugly

Here is the good, the bad, and the ugly of my experience with TypeScript with the SOLID Principles. The overall experience is excellent but there are a few takeaways to avoid mistakes for the next SaaS I’ll build!

The good 👍

I really enjoyed TypeScript, here are the most remarkable reason and lessons from this experience:

  • Linters — You cannot work on a TypeScript project without linter; they make your code consistent but also detects potential security leaks. It is sometimes annoying but mostly good for your code quality and consistency.
  • TypeScript Node Starter — This boilerplate was key. Because it adds some initial structure to your project but also includes the authentication and user management. That is one thing you don’t have to take care of! If you didn’t see it before, here it is: https://github.com/Microsoft/TypeScript-Node-Starter
  • Libraries — Node JS is very good in general because you have a lot of libraries on NPM, for every problem, there is a library to solve it. It is also very easy to create your own reusable modules and make the code more clear!
  • Interfaces — I usually don’t create Interfaces, but it’s a key to the SOLID principles. It was very fascinating to be using them. I used them to implement the connection of the different accounts (Google Play, App Store) and also to manage the logic of the data aggregation.
  • Dependency Inversion — Event though I am not sure I applied the Dependency Inversion as suggested by the SOLID principles, I used dependency injection which is key for automated testing. I don’t often write tests, but when I do I am very proud of it, and thanks to that I finally understand fully the purpose of dependency injection. Without dependency injection, testing is a lot more complicated. I used the library Awilix to manage the dependency injection.
  • PM2 — It is an amazing tool that I didn’t know before to manage the deployment of the app. It made everything very easy and will restart your server in case of a crash, which is very useful.
  • Full understanding — Last but not least, writing a website is NodeJS / ExpressJS forces you to understand everything that you do, unlike frameworks like Symfony that handles a lot of crazy things out of the box.

The Bad and the Ugly 👎

Now let’s talk about the bad side of NodeJS, Express, and TypeScript:

  • File Structure — The file structure is up to you, you decide everything, it’s good sometimes for small scale projects, but as soon as it gets big it can be chaotic.
  • State — NodeJS is stateful so you have to make it stateless by persisting any data.
  • Error management — When an error is not caught your server can just crash, so you need a tool like PM2 to ensure that it reboots, but also have a very well built error management system, which requires a lot of work and experience to make it perfect.

My key learning

I really liked TypeScript and the SOLID principles are very good. But if I had to redo Revenual, I would build it with Symfony mainly and will trigger jobs in NodeJS / TypeScript to handle all the data aggregation.

Check out the result 🙌

Here it is: https://revenual.com
Revenual — Aggregated sales reports for app makers

Sales report of Revenual



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store

Hello, I’m Sandoche Adittane. I learn about one topic every month and write a post about it!