The Exothermic Project: What I learned from 15 years of Content Management Systems
Published: 2021-07-11 19:42:39

Many years ago, a great happening occurred that forever changed my low-stress development job. My day-to-day activities were typically filled with acts of building mundane addons that would live out their short, six-month lives as part of low-traffic ad campaigns. That was all replaced by a massive and excruciating task of moving an entire higher education institution's content management system to a new home. I will take some of the blame. The application we were using showed its age, and I was personally eager for career advancement by working with the newest, shiny thing. So, like any good, and very bored programmer, I began researching how to make our jobs more enjoyable by completely changing everything about them. If there was anything that I learned from all the time we spent moving stacks of content, revamping countless designs, or applying the latest buzzword in any number of three-letter acronyms—every single content management system was the same.

All of them.

I will concede that there is a use case for everything. I’m not here today to throw shade at the idea of a CMS. Instead, I’m hoping to open up the conversation and shed some light on the parts that might be overlooked. Look for any missing pieces that may drive any seasoned developer into a dark room at the end of days spent working with them. To push out the "That's just how it is" culture and replace it with a more welcoming one.

{% github suhay/exothermicjs no-readme %}

## A master of none

At some point during a CMS's lifetime of feature additions and bug fixes, the core diverged to try and become a one-stop shop for everything, everyone, everywhere, every time, and ever after. Maybe it was to increase the demographic that would want to use the application, or perhaps it was because a client was putting on some added pressure. Whatever it was, at that point, the application should have split instead of continuing down a single-lane road towards a maintenance nightmare.

When the fundamental requirements changed, it should have been embraced and allowed for the two ideas to go off separately. Instead, the project will absorb these additions and mark them as breaking changes. You don’t realize that some of these new features had to be bolted on either by abstracting an already established data contract or by altering underlying core functionality. In most cases, the backend is sporting some kind of hack living freely in production code made to make something like this work. Don't try and deny it—you probably could list off several right now if you were asked to. They are found while stumbling around fixing something else and are surrounded by a big `TODO` with good intentions of being refactored. Comments that were added several years ago and haven't been touched since.

> `// TODO: this seems inefficient, will rework in next sprint ---> some_person, 2 years ago via PR #35 • final, final bug fix, for serious this time.`

So why is this the rule instead of the exception? What if we removed this burden of effort by introducing a more modular architecture for our features? If you just want a blog, then you should only need to install the blog. There is no need to have the portfolio or e-commerce stuff in the mix when you're only trying to draw buzz for your client's opening day. And, trust me, we've all worked with those people that want everything in one place. It was probably one of them that started the initial fracture in the code.

By keeping things separate, we nurture these very different parts to be developed in parallel and by the people who want to do it. This internal API will talk to the core, should never change, and be nonrestrictive and nondestructive. Free your developers instead of handing them a 200-page document listing all the things you can and cannot do.

> I got an integration manual from a fortune 500 company where all the coding examples were written in Silverlight and typed up in purple Comic Sans.

## Content, aka the TL;DR

Most mainstream content management systems love shoving all of your content into a database, keeping everything centralized. However, these large `TEXT` or `BLOB` types can cause performance hits, especially if you run a search. There are ways you can get around these bottlenecks by using caching, but then you have to start worrying about when you should and shouldn't drop that cache. And then, by doing so, letting everyone know that the cache isn't there anymore so that they stop calling you on the phone about how it looks, "[...] correct in fox-fire, but not in the blue E one."

> I should have asked them to check Netscape, just to make sure.

Up to this point in the article, I have written roughly 4500 characters. We are pushing about 7000 symbols into the database with markup and class names, meaning 33% of our storage is being used on—well—nothing. At least nothing a reader is going to see. All this extra data is taking up unnecessary space and locking large institutions into remaining with aging software because of how stuck their content is inside of these things. They have massive archives going back years and years through multiple upgrades and requiring many people to keep everything backward compatible. What if SQL or NoSQL disappears tomorrow? What if a major version release removes something that your architecture needs? At that point, do you just tell your users you can't upgrade even though there's a security issue?

Content should be stored in non-periphery forms, should only be the content that the user wants to see, and should be kept wherever the hell you want it to be. If a content solution has to retain customers through a hostage situation with your data, they probably need to change their business model. And the content that is coming into the core should be just that—content. If it's stored in flat files or cloud drives, it shouldn't matter. The core asks for page 5's content, so the only thing it should be expecting is page 5's content.

## Trust your contributors. No, really

One of the site owners I was working with was planning on getting some temporary help to speed up their site move. I said, "Sure, we can get them all set up with accounts. Just let us know their email addresses." But that was when it was made clear that the site owner wanted this temporary help but didn't want them to publish content without it going past their eyes first. And they also shouldn't be allowed to upload new images. Or link to anything just in case the links went somewhere inappropriate. And everything should be time stamped to make sure the helpers are doing their job.

> This was a genuine request.

Why would you hire someone to work on your site that you couldn't trust enough to publish a simple page? Or even let you know that a draft is ready to be viewed before going live? Adding granularity to security will reward you with a beach covered in sand. Making a change in the sand will only fill your shoes with it. Set your contributors up for success and show them the tools they will use the most, but not block their ability to do anything requiring more people to be involved. By saving time with temporary hires, you lose it all if they're still waiting on you for approval.

> I worked in a system where the roles were: reviewer, author, author2, contrib, contrib2, contrib3, admin, admin2, and superAdmin

## Plugin frameworks: wat?

So often developers are expected to learn a new framework. If it's changing jobs or starting a new side gig, there will always be a new way they have to learn to do something they've been doing for years. I can't even begin to count how many plugin frameworks I know, filed away in my mind, next to childhood addresses and that mental list of purchases I wanted to make at the next Scholastic Book Fair from the 3rd grade. A developer has to ingest unnecessarily complex function loops, hook names, and file structures to introduce one thing into one place used only one time and then never spoken about again. We attempt to qualify this effort by making the plugin open source, but who else needs this niche, one-off solution?

A plugin should have a single entry point and be defined through simple metadata. A plugin should be what its name suggests, plug and play, and not just for the consumer. The core only needs to get data into and then out of it, opening up avenues for upgrades and security patching by preventing instances where the plugin is so deeply integrated that it becomes two versions behind the current release.

## A templated, template system of templated templates

This is where the developer's true creativity can shine. Building the perfect template requires adding layers upon layers, hooking up dynamic call-outs to bring in generated lists, and fleshing out semantic markup that would make any markup validator proud. But that's not the real world. Content is messy. Authors are fickle and quickly grow bored of the cookie-cutter-shaped baked goods that your masterfully nested templates stamp out.

"But can we put the images on the left?" suddenly, you are using template names like `content-main-with-left-image`. Bugs begin to appear in odd places, and tracking them down becomes a nightmare as you wind through the patchwork of conditional branches that add hero images on some pages, but not others, and only if they are tagged by `informational` or `temp-tag-4`. Your once beautiful markup is now marred by class names that extend further than the content.

> I think `temp-tag-4` may still be in use today since I introduced it for testing something in 2010.

Templates should be organic and not set in stone. If you have to make a one-off template for more pages than that use the base template, then they aren't one-offs anymore. Content artifacts should work regardless of how their page is structured, and a template should aid in the efficiency of publishing content while staying out of the way.

> `.page .main-content .content .content-w-tabs .image-con .image-noFloat .image-noFloat_5 .float-left`

## EOF

These are the main points I plan on focusing on while I revisit the ExothermicJS project in part 2. I like to think of these bullets as ideas to keep in mind while working on the next big thing. Thoughts that will hopefully end your next marketing pitch with applause, instead of an awkward silence followed by the question, "So what did you think?"

> This is really how one of our demo calls ended with a potential vendor. I think there was dead air for a good 15 seconds after the sales person was finished before someone from my team forced out, "Seems—neat?"