Creating A Content Management System From Scratch
A full story about why I chose to create a CMS, the structure, SEO, the admin panel, themes, and more21.01.2021 - 22:40
Over the years, my website has been getting more and more outdated and was missing many important features including the most basic SEO functions. While I have been writing a lot more recently, I posted less content on my website overall, because it didn't match my requirements anymore.
Therefore, I decided to give my website its well-deserved modernization. Rather than adding new features into the old code, I started mostly from scratch. For a while, I had been playing with the idea of creating my own content management system and now seemed like a good opportunity to take on the challenge.
In this story, I want to go over the reasons why I choose to create my own CMS and talk about some of the design decisions and implementation details.
When I created the previous version of my website, I mostly wanted to fill the main domain with something, so I built a simple blogging site. It had a static design, but it was already possible to create and edit the blog posts in the admin panel. I didn't know a lot about SEO at the time, but it didn't really matter because I wasn't using my website for anything important.
A few months later, when I started to become more serious about indie game development, I thought it would be a good idea to write regular blog posts about my progress. I was writing one post per week and nobody was reading them. However, when I started to branch out into other topics and became more active on social media, it became obvious that my website would need some SEO capabilities.
The main reason why I decided to start from scratch and develop a content management system was the URLs. The old version was using GET variables for navigation. They work great and are easy and efficient to implement. However, they aren't optimized for search engines.
Search engines prefer short and human-readable URLs with keywords in them. So I switched from the old style https://pingpoli.de?s=blogpost&bpid=60 to the much more professional looking and search engine friendly variant https://pingpoli.de/gamedev-52-viking-map.
Another feature that the old version was completely lacking was SEO meta tags. The website had a single title that stayed the same for every page and no description tag at all.
Because changing the URLs and adding support for SEO titles and descriptions would have required bigger structural changes in the code, it seemed easier to develop everything from the ground up and introduce a better structure from the start.
At the fundamental level, every website is a collection of pages. Therefore, I started with a general page concept as well that splits up into more specialized subpages. A page controls a few settings that are the same for every type of page. This includes the title, the SEO description, and whether the page is currently public or not. Every page also has a URL, which serves as an index in the database, so the index file can fetch the correct page depending on the URL.
While some settings are important for every page, it wouldn't be feasible to only have a singular type of page that can handle everything. Therefore, I added three types of subpages: static pages, posts, and modules.
Static pages are the most basic. They only contain static content. For the most part texts and images. They are created once and don't change very often.
Posts are as you can imagine for blog posts. They also mostly contain static content and don't really change after their initial creation. However, they have a few additional parameters as well: A title, a description/subtitle, an author, a publishing date, a small and a big thumbnail image, and tags. It's also possible to enable user comments below posts.
The third and most complicated type of page is a module. They are used for all the things that are not just static content in a similar way to WordPress plugins. For example, the contact form on my website and the list of posts with multiple pages are modules.
Unlike static pages and posts, modules require some PHP code to function properly, so they have to be written externally and can then be installed on the website. To allow for on-the-fly customizations, modules also have two text fields that can be edited in the admin panel and the texts are included above and below the module itself. For example on the contact page, only the form elements are the module, while the text above and the ads below are included via the custom text, so they can be changed easily.
When I was looking into a way to dynamically load different modules, I discovered a very nice PHP feature that I didn't know before. It's possible to instantiate a class from a variable name like this:
$className = "Test";
$obj = new $className;
This means that it's possible to load the module name from the database and call its code dynamically. This also means that I can develop another module, upload it, and it's going to work without any other source code changes.
After implementing the initial structure of the content management system, I was focusing a lot on the admin panel. In fact, I probably spend more time designing and implementing the admin panel than all other tasks combined. I wanted to be able to control everything on the website from within the admin panel without having to use another tool like PHPMyAdmin to tweak database variables.
The ability to add pages dynamically meant that I also needed to be able to customize the links in the navigation area of the website. The navigation link area in the admin panel turned out really nice. I added quick link buttons for all three types of pages, which makes it very fast and easy to add a new navigation link. It's also possible to link to external pages, dynamically show or hide the links, change their order, and delete them.
The editor is one of the areas that I am not completely happy with. It has BB-codes for the most important style elements and it's possible to embed images, lists, or YouTube videos. I have been using BB-codes for many years and I can use them efficiently. However, compared to a modern and dynamic editor like the Medium editor, it feels a bit outdated. I am probably going to look into implementing a better editor for my website in the near future.
In addition to the page options, there are also a bunch of settings for the whole website. For one, I have added a button to toggle the visibility of the website as a whole. When you want to perform maintenance or integrate updates, you can use the button to set the website to private for a while. There is also an option for admins to override all hidden pages, so you can preview a page before making it public.
Because every theme for the website is going to have a bottom text and an area to display social media links, I also added editable text fields for them. Finally, there are options to enable Magpie, my custom web analytics tool, and Google AdSense to include ads on the website.
When you look at big writers, content creators, and websites, many of them have a mailing list. Even my old website had an email notification system when I published a new blog post.
So it seemed sensible to include a mailing list on my new website as well. I was able to take most of the basic functionality from my old code and I added a few new admin features. The old version didn't have a way to write real newsletters, it was only autogenerating an email when a new blog post was published. For the new version, I wanted to be able to write a more personal newsletter instead of a generic "Hey! A new post has been published" message.
I know that other people are using companies like ConvertKit for their mailing lists and it's even free for small accounts. But as always, I prefer to create a custom solution that's better integrated into my website.
Get NotifiedGet an email notification whenever a new blog post is published!
One of my favorite features of the new content management system is special commands. They are a way to dynamically insert content into texts. Let's say, you write a new blog post and you want to reference another post. You could use a normal link, but that's not very eye-catching. With my special commands, it's possible to insert a small or big preview of the post that includes an image, the title, and the subtitle of that post. Especially images are more likely to be clicked on, so not only does it look better, but it also increases the chance of somebody clicking on the referenced post.
I wrote a simple parser to handle the special commands. The pattern is always ###command### and there are a handful of accepted commands. As mentioned, you can add previews to other posts, but there are also commands for inserting a subscription form to my mailing list, a Google AdSense ad, or a PayPal donation button.
So far the special command handling happens in the core CMS class and adding a new command would require changing that class. However, I have an idea of how to add dynamic extensions to the special commands as well. Similar to the modules, you would be able to add a file with a new special command that could then be used everywhere. Once I come across a new special command I want to add, I am going to implement that new system to make it even more useful.
Initially, I only wanted to add the content management functions and integrate them into the existing design of the website with some minor design changes. However, I realized that adding WordPress-like themes wouldn't require a lot of extra work, so I went ahead and did it.
The design of the website is completely controlled in the theme files. They consist mostly of HTML and CSS and require only minimal PHP code to insert the content at the correct positions. This means that designers could create a design without having to worry about code. The functionality and the design are mostly decoupled, which has a lot of benefits for upgradability and maintenance.
Besides converting the old website design into a theme and creating another theme for the new version, I haven't tested any other designs yet. I'm sure there are some crazy designs that wouldn't be possible with the current system, but I can always add more features when I find something that doesn't work.
Social Media Meta Tags
Tweets and other social media posts that include an image are more likely to be liked and clicked on. A few years ago, the big social media platforms came up with special HTML meta tags that tell their parsers how to interpret content on a linked page. When you or somebody else post a link to your website on social media and it has the social media tags, the post will automatically be well formated and include an image, a title, and a description. It looks better, more professional, and also increases the likelihood of clicks, while being easy and fast to add to a website, so there's no reason not to include these meta tags.
Unfortunately, my content management system will have very limited use cases. Right now, I am using it only for my personal website and I don't see many opportunities to use it for other projects in the near future.
One of my goals for 2021 is to get into freelancing. Let's say I find a client who wants a website developed. Unfortunately, It wouldn't make sense to use my CMS in a client's project. If another developer works on that website in the future, they won't know how to use my CMS, there wouldn't be any tutorials on the internet, and they wouldn't know how to develop modules or themes.
While I am very happy with how my CMS turned out, I am aware that it isn't perfect. There are certainly some bugs left and it probably could use a few additional features. As long as I am the only one using it, I can fix bugs and add features whenever I need to. However, when it is running on other servers keeping it maintained everywhere would be a lot of extra work.
This means that it will probably only be used for my website(s) and maybe for friends and family members if they wanted to use it. For freelancing work, it probably makes more sense to stick to WordPress and other popular CMSs, which is a lot less fun, but well known and widely used.
Is it worth implementing your own CMS? As with almost everything else, the answer is "it depends". Purely from an economical point of view, it's not worth it. Using WordPress or another existing CMS is faster, has better support and more tutorials, is well known, and is widely used in the industry.
However, I still believe creating a content management system can be great. For one, it's always nicer to use your own system. You will be more motivated to use it and implement additional features. You also know exactly how it works, so you can troubleshoot problems quickly and fix them yourself.
Finally, it's a nice challenge and you can learn a lot from doing it. It covers pretty much every aspect of web development from a database heavy backend over functional and dynamic admin panels to a well-designed frontend.
I am glad that I implemented my own CMS and I am happy with how it turned out. Not only is it better and has more features than my old website, but it also makes future updates easier through the use of modules, and when I am bored with the current design I can easily create a new theme and change it with a single click of a button.
by Christian - 21.01.2021 - 22:40