Over my many years building web applications, I have consistently needed content management systems to host web sites/pages with frequently changing content where business owners are able to make real-time changes themselves.

Historically, systems like WordPress or Drupal have been the choice because they work well and it is not terribly painful to get them running. However, I have never been a fan of these large content management systems because of everything that comes along with them (like bloated code, software updates, unused functionality, exploits) AND because of the need to configure and pay for a server or some form of hosting.

Recently I needed to implement a CMS and figured that there must be an open source Serverless Content Management System out there that I could quickly spin up. I looked and found a few options. Webiny looks great but I have taken to Vue.js and Webiny uses React. There are a few other options out there as well, but I really just wanted something that is lean that can quickly build, publish, and manage websites using AWS.

I have built bits and pieces of a serverless content management system across several projects but decided I would put them together into a working serverless content management system.

Once finished, I packaged everything together in case others may find it useful. It works as a CMS to actually host websites and could be a great learning tool as it uses multiple AWS serverless services and Vue.js.

This article describes what I put together and links to github for all of the code and more detailed instructions.

Here is the architecture diagram:

Architecture Diagram

The key enabler to all of this is AWS Amplify because the most challenging part of building applications can be authentication and authorization. With tools like AWS Amplify, this barrier goes away and opens doors to build things in new, serverless, ways.

… and Amplify configures Amazon Cognito to handle the authentication for the admin module. Entering “add api” from the CLI adds the API Gateway resources and most importantly, ties the endpoints to the authentication already created. With authentication and authorization handled, we can build the rest.

A content management system for websites can be straightforward. Common ideas like “layouts” and “snippets” can be set up so pages reuse code and common elements. When it comes time to build an actual page, there are really just a bunch of strings and search and replace. As the image below shows, to build a page we take a layout, plug in the reusable pieces (snippets), and then plug in the page-specific data and output an HTML file.

To accomplish the general tasks above with serverless technologies, we need a place to store our data and we need computational tools to process and orchestrate everything. DynamoDB and S3 handle the former and Lambda and Step Functions handle the latter.

Before I describe those components, we also need a way to quickly and consistently build out the resources and infrastructure. AWS Serverless Application Model (SAM) is the choice. All of the resources needed to build the backend for the CMS are in a template. Having your infrastructure as code not only saves a ton of time, but it greatly reduces the chance of errors.

$ sam build

$ sam deploy

Those two commands to the SAM CLI are all it takes to build out the backend resources.

DynamoDB is a great choice for persistence in serverless applications. DynamoDB stores data as JSON objects which, in turn, enables easy read/update from the Vue.js admin module via our REST interface as you can just pass JSON objects back and forth. Being a NoSQL database, DynamoDB has flexibility on how and what you store. In DynamoDB, you can store items with both a partition key and a sort key and since items can contain different attributes (layouts, snippets, pages all have different attributes) everything can be stored in a single table. DynamoDB has continuous backups so the system has built-in redundancy and disaster recovery.

S3 is great for saving objects (JSON, HTML, CSS, images, whatever) and it has the ability to serve as a static website that is useful to a CMS for websites. S3 has a ton of other abilities as well. You can add triggers to S3 to take action whenever certain events take place. For example, whenever an HTML file is updated, a trigger is fired to a Lambda function to call a cache invalidation on CloudFront to be sure that your end users are getting the latest version.

Lambdas do most of the computational work for this system. Putting your code into smaller Lambdas makes things easier to manage and loosely coupled. Being serverless, Lambdas scale to meet any demand and you only pay for what you use. I used Node.js as the Lambda runtime.

Step Functions orchestrate the key “publish” functionality. Step Functions are a powerful way to string Lambda functions together in workflows. The system has the following Step Function:

This is a simple flow, but it shows how you can benefit from a loosely coupled design. Input can be easily routed by type — for example, a “Product” gets handled differently from a “Page” but they can all share the CompressAndCopy step. Extending this workflow is easy. You can add additional lanes for new types or add or modify additional steps without affecting the others. The Step Functions use Lambdas so there is no need to worry about scaling servers. You can publish a couple of hundred pages in a few minutes without anything crashing or slowing down. If your site doesn’t change for a couple of months, you aren’t accruing any usage (cost).

Lastly, for the end users actually consuming the web pages, the actual downloading is as good as can be. CloudFront, Amazon’s content delivery network, serves the content to the end users. CloudFront has edge locations all over the world so the actual time to download HTML and assets will be as good or better than anything else.

Conclusion

I was able to build a serverless content management system that delivers web pages to end users with industry-leading speed while allowing business owners to make real-time edits to the content. All of the resources are built using command line interfaces.

The system does not have to worry about servers, software upgrades, or exploits common to systems like WordPress. While you’ll need to understand the concepts and know your way around AWS to get it installed, the overall system is extremely lean and can be customized and extended to meet your needs. As for cost, under $10 or much less per month should be easily achievable in most cases.

Popular Content Management Systems have long required large software packages and server hosting. It is great to see a new breed of Serverless Content Management Systems coming online. Here is a lean system that uses Vue.js, is installed from templates, and is deployed to AWS: