FrontAid CMS - Agile Content Management with JSON & Git.

» FrontAid CMS / Blog

Tech Stack of a KISS SaaS

FrontAid CMS is a little Software as a Service offering which (obviously) keeps things simple. This article explains our tech stack and why we chose it.

FrontAid CMS
FrontAid is a Content Management System that is built on your own Git repository. It provides a friendly user interface to editors and stores their updates in JSON files. Content is fully versioned and it works great with your CI/CD.
SaaS
Software as a service is a delivery model for software. It applies to services that are hosted centrally and offered to customers (with a subscription).
KISS
The "Keep it simple, stupid" principle states that unnecessary complexity should be avoided and simplicity should be a key goal.

tl;dr: We are using Hugo, Vue.js, Node.js on Fly.io, MongoDB on MongoDB Atlas, and LogDNA.

Introduction

Look around on our website or the CMS. Simplicity is in our DNA. To us, it was obvious that we also need a simple but well-working tech stack for FrontAid. As you are reading this post, you likely read similar ones before. Many of them repeat the same mantra.

Well, we agree. That does not have to be true for everybody or every project. But for FrontAid, simplicity is even part of its whole branding. We wanted to use technologies that we know well so that we can iterate quickly. It must be fun to use them, and we had to be certain that they will be around for at least the next couple of years.

Regarding infrastructure, we were looking for fully-managed services. We do not want to deal with security upgrades, SSL certificate renewals, or backups ourselves. We wanted peace of mind and not the absolute cheapest solution.

Landing Page

The landing page of FrontAid is available at https://frontaid.io/. When you have a look at it, you will instantly see that it is different from most product or service websites. It is intentionally kept simple (and a little skewed). Technically, it is built on the static site generator Hugo. We chose Hugo because it is simple and fast. And it also has a large community. The website is hosted on a cheap shared hosting that we already had. Deployment is done with rsync and takes about one second.

We don’t have shitty trackers, cookie banners, noisy chat bubbles, or any other nonsense. We do have a self-hosted Matomo instance for basic user statistics (without cookies and with IP address anonymization). You can opt-out of any tracking using the Do-Not-Track setting in your browser.

Frontend

The FrontAid CMS is a relatively frontend-heavy Web application. It needs to handle nested object structures and allow easy data navigation; zooming, expanding, and collapsing of different kind of input fields and user interfaces. It also handles multiple (complex) state updates and lazy-loading. So we knew that we need a good frontend framework for that.

We wanted to use a light-weight, component-based framework with a stable API and a large enough community. In the end, Vue.js and Svelte made it on our shortlist. We knew back then that Svelte is great, but the ecosystem was just not there yet. Because of that and because we knew Vue.js much better, we decided on using it instead of Svelte.

So today, FrontAid is being built with Vue.js. We use it together with the vue-cli and Vue Router. The rest of the frontend is mostly custom-built as we want to avoid having any large packages or dependency chains in the code base. What we do use, however, are packages for the testing, drag-and-drop, applying and generating of JSON patches, and for the WYSIWYG editor.

If we had to start the frontend from scratch again today, our tech stack probably would end up exactly the same. But Svelte would definitely deserve an even closer look.

Backend and Hosting

The FrontAid backend is relatively simple. It does the user authentication/authorization, connects to the database, and reads/writes from and to Git repositories. It also provides an API for the frontend. As everything is behind an authorization step, there is no need for server-side rendering (SSR) of the frontend. The backend does a lot of JSON handling though; it parses from and stringifies to JSON, applies JSON patches, and verifies JSON schemas.

Easy JSON handling was obviously a hard requirement. And JavaScript was one of the obvious candidates. If we were to choose Node.js, we also had the advantage of being able to use the same (or similar) packages while having less context switches. And as some of our earlier projects were also based on Node.js, we knew how to work with it and also what kind of restrictions it would impose. Hence, we chose Node.js as the backend technology.

We are using Express together with a few third-party packages. The most important ones are from GitHub to access their APIs, and packages for the JSON schema validator, applying and generating of JSON patches (the same as we are using in the frontend), MongoDB connector, logging, and testing.

For the hosting, we wanted a simple, managed solution. It needs to support Node.js and make Ops as easy as possible. We tried a couple of PaaS (platform as service) providers. The one we liked most was Fly.io. It supports easy deployment, basic metrics and logging, automatic SSL cert renewal, and some other nice things.

Database

Back when we evaluated databases for FrontAid, we anticipated that we will be storing lots of JSON data. So the DB that we would choose needed good support for arbitrary JSON-like data structures. For example, it should allow reading from and writing to a subset of that data. We evaluated different SQL and NoSQL databases and eventually settled on MongoDB. Our databases are now hosted with MongoDB Atlas.

Reality turned out a little different than we assumed. We don’t actually store lots of JSON in our database. The “database” we do use for JSON content is just Git. Though, we might store or cache JSON-like data in the actual database in the future, and MongoDB will be perfectly capable of doing that. But given the improvements in SQL databases regarding unstructured data, a “good old” PostgreSQL would have been just fine. We are still happy with MongoDB, but we don’t actually use most of its advantages (yet).

Monitoring and Alerts

From the beginning, we knew that monitoring and alerts will be an important topic for FrontAid. We wanted to have access to all necessary log messages, see graphs visualizing different aspects of the applications, and we wanted to be alerted instantly in case of a problem. It was surprisingly difficult to find a service that provides all that and does not completely break the bank. We evaluated over a dozen services and were puzzled by most of them. Some were so slow or clunky, they were hardly usable. And one which looked very promising in the beginning was completely broken. But luckily the last service on our list turned out to be great: LogDNA.

LogDNA collects all our log messages. Should we have the need to debug anything, we can easily search, filter, expand, manipulate, and annotate them. We can also create graphs visualizing different aspects of the application. In addition, we can create custom alerts that will be sent out every time a certain event occurs. LogDNA is a very nice service that really helps us with the monitoring.

End Notes

Some might say we chose boring technology.

We chose a simple but mature tech stack that we are very happy with. It just works, and it is a pleasure to build with it. Ops is being done by third-party experts, and we will be notified instantly when something goes wrong. We are paying exactly 19$ per month for hosting, database, and monitoring. The infrastructure is not even close to any capacity limits. Scaling up will be possible when there is a need.

PS: Yes, “KISS Saas” does sound funny.