Three input fields arranged in a column. The middle one is being dragged by a mouse cursor, leaving behind a ghostly outline

devlog

Scheming for Success

Illustrated drawing of Amadeus Maxmimilian Stadler

Amadeus

April 25, 2021

Two more weeks blew by like nothing and I’m once again spending my Sunday afternoon writing this devlog to update you on what changed in Mattrbld since the last time.

After the unscheduled detour, I did my best to get right back on track and tackle how Fields are defined in Mattrbld, as well as how to arrange those fields into Schemas that form the foundation of how content can be edited and created.

Unmet Goals

I had hoped to be able to write and publish this devlog straight from Mattrbld, but unfortunately, I wasn’t able to implement all the pieces necessary for that because the Schema-building UI proved to be more complicated to implement than anticipated. So like the past three devlogs, I’m once again writing this one in Mattrbld’s text editor, but will be copy-and-pasting this article into my code-editor for publishing.

Nonetheless, I’ve made some good progress in the past two weeks and took a moment to outline what would be necessary for me to be able to publish a devlog using just Mattrbld:

  • Import and set up the Mattrbld website into Mattrbld ✅

  • Allow intuitive schema creation and editing from within Mattrbld ✅

  • Create a schema for the “Blog Post” Content Type ✅

  • Implement collection creation and management within Mattrbld

  • Create a “Blog” collection and assign it the schema

  • Implement the Media Library

  • Implement the content editor

As you can see, judging from this list, I’m theoretically almost halfway there, but if the past two weeks have taught me anything, it’s that things are never as easy to implement as I think they will be—although some would argue that proper drag-and-drop is one of the hardest challenges to implement properly in frontend web-development. More on that in a bit.

A More Realistic Roadmap

Realistically speaking, I’m hoping that I’ll be able to publish the devlog after the next (scheduled for May 23rd) using only Mattrbld. That would fit well into my rough roadmap, since I’m planning to be done with the basic functionality by the end of the first week of June, so I can spend the rest of the month on polishing and getting ready to publish a first Alpha/Beta in the middle of July since that’s the deadline for my BA project.

Those things are for me to worry about in the future though, while this devlog is supposed to update you on what happened in the past, so before we get right into that, let me introduce a little technical background so that you’re hopefully going to have an easier time following along with the changes that I implemented.

Of Fields and Schemas

Content in Mattrbld, be it blog posts such as this one, web pages, products in an e-shop, authors, etc. is organised in Collections. Items in these collections have to adhere to a certain Schema so content editors cannot accidentally create invalid content, while giving developers certainty of the shape the data has so they can confidently use it in their applications.

Schemas consist out of one or more Fields, each of which has a distinct Type. These fields can be anything, a date, a picture, a piece of formatted text—they are the “form” that content editors will be using to create and edit content.

Each field type comes with its own options, as well as some common properties all fields have, such as options for showing and hiding them under certain circumstances, default values and, of course, validation.

A screenshot of the schema editor in Mattrbld showing two fields: Post Title and Post Content. There are two tabs visible above the fields: “Content” and “Meta-Tags and SEO”. At the right there is a list of fields that can be added via drag-and-drop

Every field in a schema has a unique key that is then mapped to the corresponding value in a given piece of content. For example, these devlogs all have a date-field in their schema that has the key createdAt. When I create a new devlog, I can set the value of such a field to the current date (or any other date I choose to for that matter). The date that I enter will show up as the value of the createdAt property in the JSON-file that represents the devlog.

Similar to the date-field, a devlog also has a title field, an author field, and many more, some of which are even nested into other fields. This schema ensures that every devlog will have the same set of properties which can then be used to display the article in the way you’re reading it now.

Two Weeks of Scheming

Creating a data-structure that can represent most forms of content isn’t an easy task, which is why I spent most of these past two weeks working on that, along with all the UI necessary to facilitate the intuitive creation and editing of Schemas. Here’s a detailed run-down of the higlights:

Prettier Filenames

Since Mattrbld is Git-based, all content lives in individual files and folders. This is a very intuitive model of storage and while it has some drawbacks compared to for example a database, it still is very much capable of meeting any requirements Mattrbld has.

One issue, however, is that filenames have to adhere to certain rules to ensure a maximum of compatibility. That’s why Mattrbld by default slugifies any filename a user enters, to ensure that it meets these requirements, along with some custom options a developer might specify for a project. This way, users don’t have to worry about special characters and rules, they just name the file the way they want to and Mattrbld ensures it’s safe and valid.

These slugified filenames aren’t exactly what we’re used to, so I created a way to make them look more like a normal name a user would have given a file. For example, a file named “Scheming for Success” would be turned into “Scheming-for-Success.json” by Mattrbld for this project. Displaying it back to the user like that wouldn’t be very nice or easy to skim, so I extended the component responsible for listing files to be able to turn it back into “Scheming for Success”, so the user sees something they’re more familiar with.

A screenshot of the rename modal showing that the typed name “Blog Post” will be renamed to “Blog-Post.json”

Reusable Components for Moving and Renaming Files

Speaking of files, there are cases when they need to be renamed or moved into a different folder. From a technical perspective, these two operations are actually the same, but there’s still the need for a distinct user interface for either of them.

That’s why I’ve built two new components—modal dialogs, actually—that allow to easily rename and move a file or folder, respectively. These were a necessary foundation for the next big area, since the user will be able to organise their Schemas into different folders for a better overview.

A screenshot of the move modal, showing two folders: content types and helpers

Schema Management

The next tab to be populated in the Project Settings is the “Schemas” tab! (How surprising, I know.) Here, users with the “Project Owner” or “Developer” access level will be able to create and manage all the Schemas for a given project.

A screenshot of the schema-settings tab in Mattrbld showing two folders and no schemas. There is also a way to filter schemas in the top left and a button to add new schemas in the top right as well as in the center of the empty schema list

This screen is also where Schemas can be opened for editing—a brand new type of view that represents all other forms of full-screen editors like the one for creating content, or the one for creating custom fields.

Schema Editor

For this screen to work properly, I first needed to come up with a specification of what a) a schema would look like and b) what the fields in that schema would look like.

Field Spec

So the first step was to create a field spec. I won’t go into too much detail here, but this is a simplified view of what I came up with. Every field has:

  • a unique key

  • a label, so content editors know what it’s meant for

  • a unique type representing what kind of field it is

  • a brief description

  • a group and a tab it belongs to

  • an icon

  • options for visibility, localisation, validation

  • a specific value and default value

  • a hint whether it’s a purely visual field or not (visualOnly)

Purely visual fields (such as separator and label fields) can be used for making the editing UI a little more descriptive and less cluttered.

On top of these standard properties, each field can also have one or more custom fieldOptions if the type requires that.

Drag-and-Drop Schema Builder

Mattrbld comes with a wide range of default fields that should be enough to cover most standard use-cases. However, users will also be able to define their own fields to create reusable and custom types for their Schemas.

All these fields, both default and custom, can be visually arranged via drag-and-drop to assemble a Schema from scratch, or building on top of one generated by a piece of content.

A screenshot of the empty schema editor in Mattrbld. The empty state has two buttons, one for adding a field, one for generating the schema from content. There are also two buttons for settings and saving the schema. The schema is titled “Blog Post” and has an orange tag showing it has local changes

In order to keep things visually separated from each other, a Schema can also be broken down into a set of different tabs, that can optionally group fields contained within them under a specific key.

A pain-point that I have personally experienced with other, similar CMSs was that it was impossible to freely nest fields without having to delete and re-create them at the appropriate level, losing all settings in the process. That’s why I spent an extra amount of time ensuring that fields can be moved in and out of groups after being created while maintaining schema validity as a whole and individual settings.

A screenshot of the schema settings in Mattrbld. There are two blocks visible in a list that is sortable by drag-and-drop (shown by six little dots at every block). The tabs are named “Content” and “Meta-Tags and SEO”

There are plenty of drag-and-drop libraries out there, but I still opted to create my own solution not only to have full control over it, but also because I have experienced some of these libraries breaking in live software (looking at you Asana!). In hindsight, building on top of an established library could have saved me some time, but I’m not sure I could’ve created the experience I have now without severely fighting against the assumptions of that library. This way, I’ve learned a lot and would definitely agree with those that say drag-and-drop is one of the hardest things to pull off well in frontend development.

Field Editing

Once added to the Schema, Fields can also be “opened” to adjust their individual settings. This way one rich text field can allow for only inline styles such as bold, italic and links, while another in the same Schema can allow for a full-blown editing experience.

A screenshot of the schema editor in Mattrbld. A field titled “Post Content” is selected and therefore has a purple background. A sidebar to the right shows a list of field configuration settings, among which there are “Output format”, “Allowed blog formats” and “Allowed inline formats”

Options differ from field type to field type, but they all can be shown or hidden under certain circumstances (and depending on who is editing a piece of content with that Schema) and allow for custom validations, so developers can control exactly what content editors can enter and save.

All in all, the Schema Editor view is one of the most complex that I have built for Mattrbld to date. It is far from being perfect and if I had more time I would like to spend that to thoroughly refactor it—but for now it’s important that it works well enough and I can move on to other points on my roadmap.

A General Sortable List Component

As hard as drag-and-drop is to implement well, it’s also a very intuitive form of UI that can be useful under many circumstances. To facilitate future interface elements that need draggable items, I have also created a more general, simplified component that can be used in those cases that don’t have as strict requirements such as nesting and transfer between different lists.

Next Steps

In the next two weeks, I plan on adding more default fields and implementing the ability to generate a Schema based on an existing piece of content, which I couldn’t quite get to anymore in this week. After that, I’ll tackle creating Collections and assigning Schemas to them and, if there’s enough time, allowing the user to configure the sidebar of their project to show these Collections.

Thank you again for reading and keeping up with Mattrbld. If you have any questions or comments, you can reach out to me on Mastodon as usual and if not, I hope you’ll stop by again in two weeks for the next update.