The last few months of my life were really crazy! I promised myself I’d complete the proof of concept of an idea which was in my head for a long time – a CMS framework. Sounds like yet another useless CMS project, doesn't it? Truth to be told, not for me. 😁 I'm aware of many popular CMS-based projects from WordPress and Ghost (which I personally use) to plenty of headless open source CMSes written in almost every possible programming language. So why create another one? 🤔Simple – it’s fun as hell!
I believe that every problem you face gives you some sort of experience e.g. you wouldn’t really know Docker until you’ve created your own Dockerfile from scratch. My personal challenge and the main reason for creating my own CMS framework was to get familiar with Moleculer – one of the trending Node.js frameworks based on microservices. What's more, I just wanted to have a good boilerplate for future commercial projects that very often start from the CMS, but also include some other custom functionalities (and I am not compromising on the highest quality!).
Requirements for my CMS framework
As every serious project, I started from gathering requirements. But to be fair, don't treat them too seriously 😛.
#1 Code Quality
As I always emphasize, the code quality is always a priority... No buts! And by code quality, I mean maintaining good architecture, using design patterns, keeping high readability and maintainability, conducting a variety of proper tests, and preparing thorough documentation.
#2 Open Source
It was very important for me to develop my CMS framework as an open source. Why? Because sharing is caring! 😃 I really enjoy the idea of open source projects and it's wonderful that nowadays people create the software and share it with the IT community completely for free! Obviously, everybody uses open source libraries every day (just take a look at your node_modules directory – guilty as charged), so I feel very proud to be able to return something to the community that has given me so much on my way to become a developer.
Even if I wanted to learn the new framework (meaning Moleculer), I always keep the abstraction layer separating my domain from the framework. In my opinion, it's a very good practice in many aspects, but also has little overhead in development. All in all, I planned to create separate git repositories for all of my domain packages, and only one "bridge" package, having Moleculer as a dependency.
This is why I call it a framework – PowerCMS is not the kind of project that you can simply unzip, install on the server and enjoy a fully functional app. It's a framework for creating CMS implementations quickly and easily by other developers.
I wanted my CMS framework to be very flexible. So there are three projects:
- Headless API
- Front-end SPA
- Admin Panel SPA
Don't even start without branding!
Have I already mentioned that things escalated quickly into something very serious? 😆 The product must have a proper “package”, so I turned my creative mode on. I called this project PowerCMS, because it's a CMS, but on steroids, so nothing fits better than this. 💪 At the same time, the idea of a logotype was born in my head. Do you know anyone that doesn't like rockets? Everybody loves rockets! With my design "talent" I'm the last person who should ever open any application, like Adobe XD, but oops, I did it again and now it's too late.
TADA! This is the marvellous result of my artistic vision. 😎 It's not so bad, is it?
First thing’s first – it’s important is to gain some experience from what you do! And it happens when you face technical choices. Difficult choices… I’d suggest that after some time you take a trip to memory lane and check whether your initial picks were correct or not. Call it a checkpoint! Here you will find a list of my dilemmas. You don’t have to agree with my choices. After all, this whole project is an experiment.
🐳 Docker vs local machine
Yeah... I know there are as many Docker fans as those who hate it.
In Node.js it's not so obvious, but I have a PHP background and in my opinion, virtualisation is a MUST.
If you want to achieve a professional level, you’ll need Docker sooner or later. While working on several projects at the same time it’s almost impossible to have different versions of PostgreSQL, for example. Using it through Docker means just a few lines of code in the docker-compose.yml file. It's even more important from the testing point of view. Modern CI platforms like Bitbucket Pipelines or TravisCI are based on Docker which makes testing much easier. So a final thought – if you are not familiar with Docker, I highly recommend giving it a try.
🛠 Monorepo vs multiple repositories
When we're talking about microservices, I have an experience with monorepos, but I As far as microservices are concerned, I have experience with monorepos, but I wanted to give the multiple repositories (written in a good way!) a try. When you have a "common" repository for all your services, a huge advantage of monorepo is that you don't need to update all of the repositories when something changes in the common one – you have just a single repository. On the other hand, it's very easy and tempting to import something from one package to another, which makes them dependent on each other. However, this is a no-no and a very bad practice.
I don't think it was a good idea to resign from monorepo. 😆 Especially in the very first phase of development, when there's a lot of R&D work and many things change. A real pain in the ass. Maybe it’s better to start with monorepo and split it, once the API is established? 🤷♂
📣 Microservices communication
There are multiple solutions for communication between microservices: directly over HTTP, with gRPC, through the queue, pub-sub mechanisms, internal websockets etc. What positively surprised me in Moleculer is the abstraction level of this communication. There is a broker interface and several transporter implementations – I picked the NATS one and I’ve never had even the slightest issue with it!
What’s really cool for me, when you have a proper abstraction then running all services in one docker container during development and running them separately in production is not a problem. This way you gain a really simple debugging method. I'm not saying that NATS is the best solution, I had no opportunity to play with it deeply because it just works, 😅 but I’d like to compare it with gRPC in terms of speed. The gRPC is for faster for sure, but I'm really curious as to how much. 🤔
You’ve probably heard about the testing pyramid. But have you ever stumbled upon testing trophy? It fits like a glove to microservices written in Typescript! Lint as static analysis can replace lots of unit tests, and you can focus mostly on kind of integration tests, as they have the greatest value.
In the case of microservices, I can't imagine to not write integration tests. I don't sleep well when they are missing.😜
Due to my project being an open-source I decided to run tests on TravisCI, which I was very satisfied with. Pipeline-like continuous integration is easy to configure – it took me a few minutes to set it up and running. I also care about tests coverage, in order to have a simple metric telling me if the tests cover the application well enough. It, of course, doesn't have to cover 100%, but it's nice to know this value and have this magic badge in NPM. To display the badge in my repository I used Coveralls, which is also free for the open source. 🎉 The report to coveralls was, of course, pushed from TravisCI.
If you want people to use your open source project, you need to have good documentation! And I don't mean the readme file in the project, but full documentation page like all serious projects have. We’re all serious here. In this case, I chose Docusaurus – markdown based static page generator, using React components. You can check out the results on https://power-cms.com, I think it looks quite professional! 🧐 I fully recommend Docusaurus – it’s DINO-MITE!
Not everyone can agree if my choices were right, but one thing is irrefutable – I gained a lot of experience working on this project and discovering the aforementioned solutions. I am not sure I would have a chance to try them out otherwise.
Right now, from a short time perspective, I would definitely change some things, introduce some things or do them in a different way. Unfortunately, I didn’t have enough time, as you can see on the road map.
I hope my PowerCMS framework will inspire you to start working on your own projects, learn a few new things and reach for the stars! 🚀 It's pure fun! 😉
Check out the official Power CMS framework website here and don't forget to click on the demo tab!