Skip to main content

I've always had a thing for content management systems; I've developed a few over the years. This one is different.

MANAGED

An in-house lightweight, "un-opinionated" content management system written from the ground up.

Objective

To build an un-opinionated content management system that doesn't lock the developer into a particular technology or methodology.

The main design goals were to be:

  • "un-opinionated"
  • flexible and scalable (suit small and large applications)
  • efficient at completing tasks

It's was also important that it was source control and cloud friendly.

Implementation

Core Technologies

As it's primarily for internal projects (it manages this site) it was decided to solely support the future of ASP.NET which is the highly performant and portable, "pay to play" framework: ASP.NET Core.

For the front-end, after successfully using AngularJS a number of times, Angular 2, it's successor along with TypeScript was chosen.

Un-opinionated

The primary goal was to allow applications to be developed independently, using technologies and methodologies that are appropriate.

I don't want a CMS to dictate how I build my application

Traditionally, content management systems dictate to some degree the way in which you develop an application, with regards to technologies, data storage, routing and dependencies, for example. This can sometimes lead to inefficiencies and performance issues or get in the way of using new technologies.

The idea behind MANAGED is that it has as few opinions as possible and sits on top of your application rather than the other way around.

Traditional CMS
MANAGED CMS

This gives the developer the freedom to use the tools that best match the job. For example, a small site may not require a database at all or it may be best to use different storage providers depending on the type of content. This is achieved through the use of a configurable Repository style pattern.

One opinion that MANAGED does have is that content should be modeled using strongly typed POCO classes, which are then used to help build the runtime metadata.

The metadata, built at startup, lies at the heart of decoupling MANAGED. Various conventions can be used for ease but everything can be also configured in code using the builder.

services.AddManaged(builder =>
{
    builder.ConfigureJsonFileSystemRepository(@"C:\MY_JSON_REPO_LOCATION");

    builder.Register<Project>()
        .UseJsonFileSystemRepository()
        .Route("Project")
        .Property(p => p.Name).IsIndexed()
        .Property(p => p.Tags).IsIndexed()
        .Property(p => p.Content).IsIndexed();
});

Flexibility and Scalability

It's important that MANAGED supports both small and large applications. To achieve this it has as few moving parts as possible, which not only keeps it simple but makes it more interoperable.

The best way to develop something that's flexible and scalable is to not develop it at all

Sometimes trading a non-essential feature for simplicity can pay dividends when it comes to keeping the code flexible and scalable.

Having no central database to keep track of entities means that content and media can simply be dropped on the server and it's ready to be MANAGED.

A great example of this is images sitting on the file system. The file system alone provides listings, date created, date modified, file name and file size. It seems pointless to duplicate all or some of this information in another database (unless of course, for some reason the application demands it).

Efficient User Interface

The main design goal of the UI is to make it feel more custom and tailored towards common tasks in order to get the job done quickly. I'm still working on this and find the thought process very interesting.

"The best interface is no interface"

You may have heard the expression "The best interface is no interface", there's a lot of truth to this. Over time the interface and experience will be refined to remove unnecessary repetitive tasks.

Source Control

Simplicity and no central database play a big part in keeping MANAGED source control friendly. It's important that everything required to run the application should be in source control. This includes, Content Types, User Types, Configuration, Property Editors, basically any type of "definition". Only instances of these definitions (e.g. content) should be stored outwith source control.

The Cloud

In order to make it cloud friendly interfaces and dependency injection are used throughout the application. This makes it easy to add in a cloud based service (e.g. for handling images in an AWS S3 or querying a remote index service).

Acknowledgements:

Using ASP.NET Core is great but it raised a few challenges. Luckily some OSS guys have provided solutions.

  • Image manipulation: ASP.NET Core doesn't come with System.Drawing which was going to cause a problem generating thumbnails and responsive images. Luckily James South started the excellent ImageSharp library.

  • Indexing: Lucene.NET hasn't been ported to Core yet, so an alternative had to be found. The code for h00t which is part of RaptorDB written by Mehdi Gholam is so simple that with some tinkering it now works with .NET Core and indexes key/value pairs which allows searching against individual entity properties.

Related Projects

All skills

Contact

Get in touch to talk about your project or just ask me a question.

lee.gunn@secretorange.co.uk