How we built our ideal CMS
When we set out to build our own CMS, we were lucky enough to have a blank slate to start from. I've spent a lot of time working with Drupal (early days), Craft, some enterprise systems, and some proprietary CMSs. Therefore, we had some ideas of what worked and what felt overcomplicated.
Our goal was to limit any HTML stored in the database. In order to make that goal a reality, we needed to have structured content. To me, that meant pages could be rendered from a well-formed JSON structure - regardless of where and how that structure was created and stored.
Before we wrote any code for creating and editing content, I created a set of JSON files for each page in a typical site. From there, I started working in Jigsaw to create the markup we would need. Having experience with Craft and its Matrix Block, this structure was familiar and pretty easy to envision.
From my thinking, each piece of content should be a block that may or may not have children. Some blocks would be repeatable and some blocks would simply be containers with a number of child blocks. We relied on Brad Frost's ideas in Atomic Design and my experience building the front-end of Indiana University's Framework & Style Guide.
Our building blocks are: Fields -> Blocks -> Containers -> Sections.
We kicked off our project shortly after Ryan Singer released his book Shape Up. With this new project, we were intentionally working in cycles and trying to get to prototypes quickly. This meant having data (in the form of JSON files), markup (in the form of Jigsaw templates) and very minimal styling up and running within the first week. The push to completing a "slice" allowed us to validate the direction we were heading.
With structured data validated, we started to think about a UI for creating and editing the content. While I could probably write JSON files if we absolutely had to, managing the files for 500 sites wasn't an option. :)
Building a UI
I spent a week or so looking into a builder called GrapesJS. It was really promising - easy to extend, easy to create our desired layout/interface, and the output was something close to what I had created in flat JSON. However, after a week or so with GrapesJS, it became clear that we were going to need to massage the exported JSON before we could render it through Jigsaw.
Essentially, GrapesJS was creating too much data and allowed for too many settings. For example, we didn't need or want every HTML tag and attribute. We would handle all of that in Jigsaw. And - we didn't want editors mucking around with CSS attributes and custom animation settings that we would just ignore when rendering sites. We'd take care of all that behind the scenes.
A custom Vue page builder
Since we were planning to use Vue for all of the other UI, I set off building my own page builder in Vue. The idea was to build a bunch of block components that represented our JSON structure. We knew the structure already worked as JSON in Jigsaw, we just needed to be able to create and edit that structure.
The result are 15 or so block components that have this structure:
- fields (title, text, image, etc)
Using the Vue.Draggable component, we were also able to build a drag-and-drop editing experience. Whole sections can be re-ordered within a page, containers could be re-ordered within a section, and blocks can just stack up as needed.
By starting with the end (structured data represented by JSON), we were able to build our ideal UI. Obviously, it's taken some time to get there, but we're really happy with the result. The ability to add new blocks is as simple as deciding the data structure, creating a Vue component to edit that structure, and adding a Jigsaw template to render that structure. Nbd.