Prior to the block editor, I would create pre-designed page layouts for my clients using the following method:

  1. Create a page template file. For example, about-us.php, in the theme folder.
  2. Use the advanced custom fields plugin to create fields for the template file.
  3. Layout the ACF fields in the page template using CSS.
  4. To use a page template: the client selects the page template in the page editor.

I would often create multiple page templates for a client's site.

With the block editor, what is the recommended way to do this, please? I want to lock the template, if I use a block template. I understand that this can be done with custom post types, but I haven't found a solution for multiple page layouts e.g. about us page layout, contact us page layout etc.


1 Answer 1


You have a number of options. But the best method I have found is to use combination of custom blocks that allow the user to rearrange content themselves and custom post meta (depending on the situation).

For simple things, I stick to custom blocks. I create section blocks, card blocks etc, that have strict functionality and design (so the user doesn't "mess" with the design too much), but allow the user to assembling things in the order they want.

For more complex things, I use custom post meta. ACF uses the post meta functionality built into WordPress. You can replicate that functionality pretty easily in Gutenberg but there are a couple extra steps. First you'll need to register the custom post meta:

function pb_register_post_meta() {
    register_post_meta('page', '_pb_meta_name', array(
        'type' => 'string',
        'single' => true,
        'auth_callback' => function() {
            return current_user_can('edit_posts');
        'show_in_rest' => true, // This ensures the meta field is available in Gutenberg
add_action('init', 'pb_register_post_meta');

Then you can build a block, PluginDocumentSettingPanel, or a custom PluginSidebar. I personally mostly use a combination of block and PluginDocumentSettingPanel depending on the amount of custom info I need the user to input. If there is a lot, I'll make it a block so it uses the primary editor pane for editing. Either way, the process is about the same:

 * WordPress dependencies
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import { registerBlockType } from '@wordpress/blocks';
import { TextControl } from '@wordpress/components';
import { useEntityProp } from '@wordpress/core-data';
import { useSelect } from '@wordpress/data';

registerBlockType('pb/post-details', {
    apiVersion: 2,

    title: __('Post Details', 'pb'),

    icon: 'star',

    category: 'common',

    supports: {
        html: false,
        customClassName: false,
        multiple: false,
        reusable: false,

    edit: () => {
        const blockProps = useBlockProps();

        const postType = useSelect((select) => (

        // Get the post meta as an object
        const [meta, setMeta] = useEntityProp('postType', postType, 'meta');

        return (
            <div { ...blockProps }>
                    label={ __('Meta Field Label', 'pb') }
                    value={ meta._pb_meta_name }
                    onChange={ (value) => setMeta({_pb_meta_name: value}) }

    save: () => null,

(You can also register your block using block.json).

You can also use templates on post types, including the ability to lock a template.

'template_lock' (string|false) Whether the block template should be locked if $template is set.

If set to 'all', the user is unable to insert new blocks, move existing blocks and delete blocks.

If set to 'insert', the user is able to move existing blocks but is unable to insert new blocks and delete blocks. Default false.


register_post_type('post_type_name', array(
    // ...The rest of your post type settings
    'show_in_rest' => true,
    'template' => array(
    'template_lock' => 'all',

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.