2 years of building my own CMS...
published at 30.06.2017 20:16 by Jens Weller
Today is the day, the first website build with my CMS is live. Its meetingembedded.com, a website where I try to recreate Meeting C++ for the embedded/IoT sector. But that is a different story. Looking back, its now almost 2 years since I started the project, I am finally able to build websites. To be fair, I worked on lots of different projects in between, as every now and then the project became blocked by either internal or external forces.
First a picture, this is how the UI for my CMS looks:
Actually, its almost that, the TinyMCE in Qt thing didn't work out.
Let me quickly give you a short overview on the structure of the project. There is a Qt UI which serves as "input layer", and the CMS it self, which is written in standard C++ + boost + rapidjson. In the long term, I'd like to separate them into a Qt application and a CMS library, but that hasn't happend yet. Reason for the separation is also, that Qt is under LGPL, while a the other parts are under more liberal licenses. But, actually, there is a 3rd layer, which isn't really separated, its part of the CMS layer: the layer which creates the HTML it self, the "output layer". Most code is in one of these layers. The project is at ~10.7k loc currently, will grow some more in the coming weeks when I start adding missing features for the Meeting C++ website.
Features, Bugs and Errors
The last two days I've spend a lot of time in these 3 layers to hunt down subtle bugs. Also I haven't worked on this project for like, 3 month. Most bugs are now related to the website, but some also related to the UI. Why is the date in the RSS feed wrong? Well, the difference between y and Y can be 100 or 2000 years, depending on your date format or parser. Other things that show up are simple oversights, where the pubDate is just not available to the text templates variable store. Of course I also had a one off error, which also wasn't that easy to catch.
The hardest to find was the one tiny UI bug, which made /News show its list content, and /Blogroll not. When you have a combobox for selecting things in Qt, and you fill it with values, it shows the first value as selected. But that doesn't reflect the null state in the model, so it only looks like that Blogroll is selected as the list to show. In reality its null. Sometimes this is prevented by the model with a non null default value, not in this case, as maybe, just maybe, there is no list to select. So now the first value added to the combobox is "none", with an assigned null value.
The two roots of the CMS
What got me started in 2015, was I already had spent a year thinking about possible website solutions. At the end, a static website made the most sense, so I looked at available options. One other important issue for me is, that I want to be able to easily convert a website to the next major version of what ever is used. And in reality, thats often not possible. Sorry THAT plugin is not supported anymore, this is now done different, etc... Also, I'd like to be able to integrate this into the already existing tools which manage this and that for Meeting C++. So why not write a CMS on my own? Insane idea.
But then I sit in the talk about boostache at C++Now in spring 2015, which is one of the missing pieces, how to have a good text templating system? Well, with boostache that problem is solved. In June that year I have an even crazier Idea: how do I edit html fragments for the website in Qt? Integrate TinyMCE into your Qt Application! Some research shows at least that some people have tried this, and it seems possible. Writing the CMS becomes my summer project, I will give a few lightning talks about this at CppCon, C++Now and QtDevDays, write a few blog articles and also make some youtube videos. Its a good start.
External road blockades
Both boostache and TinyMCE have every now and then stopped this project. I needed to fork boostache, as its been on C++14 for generic lambdas, and my MinGW did not support this. You get to like generic lambdas very much, when you ever need to replace them... TinyMCE was the bigger road blockade, its still a hack, and to be honest, never was anything else. The first version used QWebKit, but had a few JS issues with this, but one could hack around these. But then Qt is like, you know whats cool? Deprecating and removing QWebKit. But we give you this new shiny thing called QWebEngine, based on Chromium! Cool, except, that Chromium does not build with MinGW under Windows, so its major blocking issue.
This spring I finally have time to deal with QWebEngine, I rebuild the application with the VS Compiler, aka Visual Studio Build Tools. Works like a charme, I'm able to refactor my HTMLEditor easily. But once I start testing the application, it keeps crashing. The debugger doesn't help, something seems corrupted, wrong or cursed. The crashes are also random, so after a few days of debugging to find only randomness, I get an idea. QWebChannel is the way you communicate with QWebEngine, which is also a huge part of the program when used. It launches a few background processes, Chromium is really a little beast it self:
So, just in theory, when QWebChannel connects to the Chromium process via Websockets, couldn't that do it also to a normal browser? So I switch back for the solution which I use today: a special crafted editor.html file with the needed JS to handle the websocket and Qt things for QWebChannel and displaying a TinyMCE Editor, while on the Application site, its now a simple link to click when you'd like to edit some HTML. It took some time to get used to this workflow, but it actually works. I'm thinking about moving the application to linux, where I again could switch back to the chromium solution though.
Still a lot to do, I'd like to add an asio (or maybe beast?) based server to the CMS, so that I can start to integrate it better with my other applications. Then a client could issue commands to add a post to a list, or add data to a collection. The collections/data sets are a feature which is still in progress, but needed for the speaker/talk/sponsor data. Also, for the website it self I have done lots of research in CSS/HTML5, the first website is kind of the test ground to get most bugs and trivial oversights out of the way to start working on the Website of Meeting C++ later this summer.
This project is a poster child of a rabbit hole. The complexity also is reflected in being a CMS, there are lots of features which are very detailed, and hence also need to be detailed in the UI. First, there is a list of available lists, then a list is a set of posts, while a feed is a set of lists, which are contained in that feed. But the generate step of the feed only should take the last n posts from all its containing lists. So most features are split into the 3 layers, separating the UI is a good step, and the output layer, is, well also some kind of UI. I haven't mentioned JSON, well I should. Adding to the complexity is also, that I should be able to import the data from my old website (blog+news, maybe also talks and speakers).
And then also, there would be this and/or that, but for now, thats enough...