How to limit editor blocks without wrecking the Site Editor

Got a call last week from a client in a full-blown panic. Their marketing team was complaining that the block editor had been stripped bare, with only paragraphs and headings available. At the same time, their lead designer had a completely broken Site Editor: templates would not load and the layout blocks were gone. The designer blamed the marketers, the marketers blamed the designer. My hunch was that a dev fix had gone wrong.

It turned out a junior dev had been asked to limit allowed blocks for the content team so the blog post layouts stayed consistent. That is a reasonable request, and the solution looked obvious: the allowed_block_types_all filter. The problem is they applied it globally, and in modern WordPress that is a landmine.

Why a global filter breaks the Site Editor

The Site Editor is not editing a post or a page. It works with special post types, wp_template and wp_template_part, and it needs access to every layout block (groups, rows, stacks, query loops and the rest) to work at all. When you put a global filter on allowed_block_types_all, you are telling WordPress, “These are the only blocks anyone gets to use, anywhere.” So the Site Editor tries to load a template, finds the blocks it needs are banned, and breaks.

Years ago my first thought would have been the same, just use the filter. Before the Site Editor existed, that was fine. It is a good example of a fix from one era turning into a problem in the next. You cannot use a sledgehammer when the job needs a scalpel.

The right way: check the context

That filter is smarter than it looks. It passes a second argument, $context, which tells you exactly where the filter is being called, whether that is the post editor, a widget, or the Site Editor. Once you check the context, you can apply the rules only where you want them.

add_filter( 'allowed_block_types_all', 'allowed_blocks', 10, 2 );

function allowed_blocks( $allowed, $context ) {
    // Site Editor usually edits these post types.
    if ( isset( $context->post ) && $context->post ) {
        $post_type = $context->post->post_type;

        // Allow all blocks in the Site Editor.
        if ( in_array( $post_type, array( 'wp_template', 'wp_template_part' ), true ) ) {
            return true;
        }

        // Restrict blocks for regular content.
        if ( in_array( $post_type, array( 'post', 'page' ), true ) ) {
            return array(
                'core/paragraph',
                'core/heading',
                'core/image',
            );
        }
    }

    // Fallback: detect the Site Editor screen directly if available.
    if ( function_exists( 'get_current_screen' ) ) {
        $screen = get_current_screen();
        if ( $screen && 'site-editor' === $screen->id ) {
            return true;
        }
    }

    // Another fallback: some contexts expose a name like 'core/edit-site'.
    if ( isset( $context->name ) && 'core/edit-site' === $context->name ) {
        return true;
    }

    return $allowed;
}

So what’s the point?

The lesson is not really about this one filter. It is about using the context WordPress hands you. A lot of modern hooks and filters pass that extra parameter for a reason. The code here is a slightly sturdier version of a snippet from the WordPress Developer News. Checking the context first saves hours of debugging.

  • Leave the Site Editor alone: the code first checks whether we are in a wp_template or wp_template_part context. If so, it returns true, which tells WordPress to allow every block there.
  • Restrict for content editors: next it checks whether the post type is a standard post or page. If it is, then it returns the short list of approved blocks.
  • Add fallbacks: the checks for get_current_screen() and $context->name are there in case the post object is not available, so the function behaves consistently across WordPress versions.

This stuff gets complicated fast. If you are tired of debugging someone else’s mess and just want your site to work, drop my team a line. We have probably seen it before.

author avatar
Ahmad Wael
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.