A developer's approach to controlled content layout features

(Nate Wright) #1

For a while now I’ve been working on a small library that can be used for bespoke, carefully ring-fenced content layout. Today I released a user-facing demo video that shows it in action on my next theme.

But I wanted to give a bit of a preview of what’s going on under the hood, in lieu of the developer documentation (which is still missing).

The content-layout-control is a small library which provides a Customizer control to which a developer can add components. The user can then use this control to add/edit/remove/re-order the components. And the components are then rendered out and saved into post_content.

The easiest way to think of it is like “widgets” for posts, except without all the data storage problems that widgets come with, and with more careful developer control over which components are supported.

The main goals of the project were:

  1. Provide an alternative approach to content layout from traditional page builders by making most of the design decisions for the user.
  2. Solve some issues around data storage and persisting content long-term.

I feel pretty happy about how this library addresses the first goal. I think the library can be a really useful tool for client work and other situations where developers need to be able to support rich content editing but don’t want to hand over design control to users. Right now it’s a lib to be included manually, but I’m definitely thinking about putting the lightweight core into a plugin for easier dependency management.

The second goal is a bit of a mixed bag. By rendering the components into post content, the data is indexable and scalable, which solves a large part of the issue. But in my experience there’s still a heavy reliance on shortcodes for dynamic data – not layout data, but just for populating a page with data which might change (like a post). For example, there’s currently no way to register dependencies and re-render post_content when a post title that’s displayed in a component on another page changes. That means you end up needing to rely on shortcodes more than I’d like.

A quick developer-y run-down of what’s going on:

  • Backbone Models/Views and WP’s Underscore-like templates for rendering controls
  • Uses the REST API for retrieving component previews and other bits
  • Object-oriented approach to components so it’s easy to scaffold new layout components
  • Event-based architecture for communicating between control/preview panes (pretty much what the customizer already does, but adds easy retrieval of templates from server for PHP-side template rendering)
  • Event-based control of a slide-out panel for component controls (similar to widgets and menus in core)
  • Date rendered to post_content and “source” data serialized in post meta
  • Support for custom callback to restrict what posts can be edited this way (default is page, but in my theme I limit it to just the homepage)

I’ll be pretty tied up for a bit releasing this theme, but I want to get a stripped-down demonstration theme put together soon so that others can start playing around with it.

In the meantime, you can look at the github project and let me know what you think.

What is the best way to build home pages with a lot of sections for distributable themes
(Leland Fiegel) #2

Been meaning to give this a look. Wish I didn’t wait so long. :smiley:

I’m hesitant to invest too deeply in widget-based layout features, due to the data storage issues. So this solves that problem.

IMO, a theme should not give the user the option of making their site look terrible. So I like this a lot.

This is why I prefer to include prepackaged color schemes like Twenty Fifteen does, rather than a color picker in Customizer controls.

Yeah, this could be a problem. I’d imagine if not accounted for, could lead to “I changed the title but it doesn’t update on the homepage” type support requests.

But overall I’m digging this.

(Nate Wright) #3

Thanks @leland. Just got to get going on the documentation/examples. :slight_smile:

(Nate Wright) #4

Ok, I’ve built a very simple demo theme that illustrates how you can integrate the content-layout-control with a theme.

It’s pretty bare-bones right now. It only adds the two default components. It should at least give a clue to those who want to look at how it’s going to work.

Next step is to demonstrate a custom component. That will be the primary use-case and will dive into the JavaScript a bit more.

(Matt Medeiros) #5

(I know you and I have debated this functionality for a bit – and keep in mind, I’m not a developer, nor do I pretend to be one.)

What happens when someone switches themes, are those visual components lost, while data stays in post_content? Because you’re storing in post_content, can a user bring that component you created on the homepage, to another page? Watched your workflow video and it’s exactly how we build our Baton theme with our Note widget, except, widgets. :slight_smile:

Jousting with Note widgets

(Nate Wright) #6

What happens when someone switches themes, are those visual components lost, while data stays in post_content?

The HTML is rendered out to post_content, so that stays in place regardless of the theme. The components wouldn’t be styled, though, unless the theme styled that specific HTML.

To be honest, for the moment I’d probably recommend the framework primarily for client work, where you want to provide a particular building environment but closely control the output. Or for theme products where there isn’t going to be heavy use of the layout control. For instance, in my latest theme I restrict it to just the homepage.

But even if/when I decide to open it up, to say a specific Page template, my customers usually don’t have more than a half dozen pages anyway. So in that case keeping the content around and editable is useful but won’t necessarily impose a huge burden on an end user.

But switching away does still impose costs, and isn’t as portable as, say, a builder plugin. In my experience there’s a real tension in builders between generalizability and design quality. My approach leans towards the latter, and in that sense is more tailored to end-users without design skills or web building knowledge.

ps - I really like your inline text formatting tools. Might have to steal that some day. :slight_smile:

(Eric Daams) #7

@NateWr This sounds great. I’m going to explore using this for a theme we’re working to get out on WordPress.org.

Quick question: How hard would it be to adapt this to use it to define a default template for a custom post type? i.e. Instead of customizing a single post/page, define the layout to use for all items of a particular post type.

(Nate Wright) #8

That’s a pretty neat idea @ericnicolaas. I don’t think it would be that difficult, but it would require some knowledge of the Customizer’s internals.

Here’s a quick run-down on how I’d go about it:

  1. Extend the CLC_WP_Customize_Content_Layout_Control class.
  2. Define a custom type for your new control, like cpt_layout.
  3. The type is then used in a dynamic hook during the save process. (So the hook could be customize_update_cpt_layout).
  4. The content layout control saves to post content but you could save the HTML blob as a template file in your wp-content folder, I suppose?

That last bit will be the tricky part: deciding what kind of output you want to render and where/how to save it safely. Obviously you won’t want a PHP file in wp-content that can be run in a direct request, so you’ll want something like this at the top:

if ( !defined( 'ABSPATH' ) ) exit;

(Zackary Allnutt) #9

@NateWr I’ve been playing with your library. It’s absolutely brillient and exactly what I need. A way to create pages with modules rather then giving the full control of a page builder.

Tool a bit to get my head around it because I’ve not used underscores.

I wanted to make it a bit easier to add modules so I’ve modified it to be able to add field types. I’ll commit as a fork.

Thanks for sharing :slight_smile:

(Nate Wright) #10

Thanks @ZorbixThemes! Glad to hear someone’s gotten over some of the initial hurdles to get familiar with the layout control. It’s definitely not as simple to deploy as other WP content libs.

Can you explain more about what you mean about making it easier to add modules? I’d be curious to see what the pain point was and how you overcame it.

In preparation for a couple themes I’m working on, I built a small plugin that adds some common components for my themes:

That might make a good example of building out some custom components. They’re then activated in a theme with a simple add_theme_support call. Here’s an example in the base theme I’ve put together for my own needs:

(Zackary Allnutt) #11

Thanks, will look through that. My issues was figuring out where I needed to add things to create a new module. As someone who’s neither familiar with the customizer in depth and backbone. But after spending sometime looking through your examples I got to grips with it.

I felt like creating a new component was overly verbose. I wanted to make it a bit simpler and quicker to add and create a new component.

That’s probably my own laziness talking. So I started to creating fields so i could set what the field type of a field was so that it would auto generate the forms. So more like using something like Kirki. So an array of fields with name, setting, field type and it create the form from that.

Will try to commit my fork soon. Taken a break from working on it right now as I’m trying to get a theme done but plan to go back to it in the future.

Really excellent work and I think you’ve totally go the right approach. Give some flexibility without going down the page builder route.

(Zackary Allnutt) #12

Pain points were trying to figure what I needed to do to created a new module.

(Nate Wright) #13

Yeah, creating a new component is really verbose, especially on the JS end of things. I’d like to make it easier to re-use the JS models/views/controls/templates where possible.

I’m hesitant to build in a form generator though, as I want to keep this pretty slim. Also, since the templates are JS underscore templates, I’m really hesitant to use PHP to generate JS to generate HTML, in part just because of the sheer awfulness of the whole undertaking. :slight_smile: But it’s definitely an area that could use some improvement.

(Zackary Allnutt) #14

Completely understand and the way you’ve done it keeps it flexible. You don’t have to create a new field type for something you might use once. Also I think you concentrate in one theme so it makes less sense to put efforts into speeding up the field creation. I’m remaking four themes so its more important for me to be able to quickly generate the controls.

For now I’ve used Kirki to do something kinda similar. It allows me to create controls quickly and gives ability to re-arrange layouts. Just not as elegant and user friendly as your solution. Although the beta version includes selective refresh which should mean getting those edit buttons that jump to the customizer field.

And doesn’t add the html to the page, which I think is good for switching themes. I’ve used a page template instead.