• Imagencvp

    (@ncvp)


    I’m working on a custom menu block. The block itself is working fine, including appearing in the WordPress editor, but I’ve just noticed this message in the Dev Tools console ‘Block with API version 2 or lower is deprecated since version 6.9’

    This is block.json:

    {
    "$schema": "https://schemas.wp.org/trunk/block.json",
    "apiVersion": 3,
    "name": "ncvp/header-menu",
    "title": "NCVP 2017-style header menu",
    "category": "theme",
    "icon": "menu",
    "description": "Works in 2025 child theme",
    "supports": {
    "html": false
    },
    "editorScript": "file:./editor.js"
    }

    This is editor.js:

    (function(blocks, element) {
    var el = element.createElement;
    blocks.registerBlockType('ncvp/header-menu', { // xxxx/yyyy matches header.html
    edit: function() {
    return el('div', {
    style: {
    padding: '20px',
    background: '#f0f0f0',
    border: '5px solid #0073aa',
    textAlign: 'center',
    borderRadius: '10px'
    }
    },
    [el('span', {}, 'NCVP header menu derived from Twenty Seventeen')]
    );
    },
    save: function() {
    return null;
    }
    });
    })(window.wp.blocks, window.wp.element);

    and this is the call in functions.php:

    function t17m_enqueue_editor_script() {
    wp_enqueue_script(
    't17m-block-editor',
    get_stylesheet_directory_uri() . '/t17m/editor.js',
    array('wp-blocks', 'wp-element'),
    filemtime(get_stylesheet_directory() . '/t17m/editor.js')
    );
    }
    add_action('init', 't17m_enqueue_editor_script');

    Can anyone please advise what I should do to conform to current standards?

Viewing 9 replies - 1 through 9 (of 9 total)
  • ImagePouya

    (@pouyaebrhm)

    Hi Since you already set "apiVersion": 3 in block.json, the warning usually means WordPress is not actually loading the block from block.json.

    A few things to double-check:

    • Make sure you are registering the block with register_block_type() in PHP (not only registerBlockType() in JS).
    • If you still register it manually in JS, WordPress may fallback to API v2.
    • Clear all caches (browser + plugin + server).
    • Rebuild assets if you’re using build tools (npm run build).
    • Confirm the block is registered like this:

    register_block_type( __DIR__ . '/build' );

    If block.json isn’t detected, WordPress treats it as an older block → which triggers that deprecated warning. Most of the time it’s just a registration or cache issue 🙂

    Thread Starter Imagencvp

    (@ncvp)

    Thanks for your interest. I have made a GitHub repo of the current state of the code https://github.com/ncvp/twenty25-test6-copy in case you have time to look at it.
    WordPress must be seeing my block.json, because if I change the description key value that is reflected in the WordPress editor.
    I am calling register_block_type(), but perhaps not in the right way. You can see all my PHP code in t17m/t17m.php. There’s only 70 lines of it.

    ImagePouya

    (@pouyaebrhm)

    Hey, thanks a lot for sharing the repo — that really helps 👍

    Since WordPress is already picking up your block.json (the description change confirms that), the file is definitely being detected correctly. So the issue is probably not the JSON itself, but how the block is being registered in PHP.

    With newer WordPress versions (6.9+), it’s recommended to register the block using the folder path that contains block.json, not just the block name.

    For example:

    register_block_type( DIR . ‘/t17m’ );

    instead of:

    register_block_type( ‘t17m/header-menu’ );

    Registering by path allows WordPress to automatically load the metadata, scripts, and the correct API version. In many cases, this removes the “API version 2 or lower is deprecated” warning.

    Also double-check that:

    • the registration runs on init
    • block.json is inside that same folder
    • the block isn’t being registered twice (both JS and PHP)

    From experience, it’s usually just the registration path 🙂Let me know if it still shows the warning after trying this.

    Thread Starter Imagencvp

    (@ncvp)

    I am calling register_block_type() as you suggest, at line 43 approximately of t17m/t17m.php. I have to do that, otherwise the callback which renders the menu html is not executed.
    Interestingly (?) if I don’t enqueue editor.js (line 60 of t17m/t17.php) I don’t get the console log warning, but the editor complains ‘Your site doesn’t include support for the “ncvp/header-menu” block. You can leave it as-is or remove it.’, which is rather off-putting.
    It may be that the block is being registered twice, but I do want to see a nice friendly label on my block in the editor.

    ImagePouya

    (@pouyaebrhm)

    Ahhh — now that extra detail makes things much clearer 🙂

    If disabling editor.js removes the console warning, that’s a very strong hint that the block is being registered twice.

    Right now you’re likely doing both:

    • PHP → register_block_type() (server registration)
    • JS → registerBlockType() inside editor.js (client registration)

    With block.json + register_block_type(), WordPress already registers everything automatically (metadata, scripts, label, etc). In modern blocks you normally should NOT call registerBlockType() manually in JS anymore.

    So what’s happening is:
    JS registers the block (probably API v2)
    then PHP registers it again (API v3)
    → WordPress logs the “API version 2 or lower is deprecated” warning.

    That’s why removing editor.js removes the warning 🙂

    Recommended approach:

    • keep register_block_type( DIR . ‘/t17m’ );
    • remove registerBlockType() completely from editor.js
    • use editorScript in block.json instead to load any editor-only JS

    Example block.json:

    {
    “apiVersion”: 3,
    “name”: “ncvp/header-menu”,
    “title”: “Header Menu”,
    “editorScript”: “file:./editor.js”,
    “render”: “file:./render.php”
    }

    Then editor.js should only contain editor behavior (controls, inspector UI, etc), NOT registerBlockType().

    In short:
    block.json + PHP = registration
    JS = enhancements only

    After that the warning should disappear and the label will still show normally in the editor 👍

    Thread Starter Imagencvp

    (@ncvp)

    As I understand it I’ve got to do 3 things:
    1) Register the custom block with WordPress
    2) Render the menu HTML so it can appear on the page
    3) Provide JS to display the custom block in the editor
    At the moment my code for 2) and 3) both do 1) as well, so WordPress gets confused.
    I tried adding “render”: “file:./t17m-menu.php” to block.json, but that alone is not sufficient. editor.js, which was originally written by ChatGPT, needs to be modified, I think, but I’ve no idea how to do that.
    I’m going to work through this video https://www.youtube.com/watch?v=UidNIrkqk-E to see if it offers any solutions.

    ImagePouya

    (@pouyaebrhm)

    Yes — your understanding is actually correct. Right now you’re registering the block multiple times:

    • PHP → register_block_type()
    • JS → registerBlockType()
    • and block.json metadata

    That’s what causes the confusion. With modern blocks (block.json + apiVersion 3), you should only register the block once — from PHP (or directly from the block.json folder). JavaScript should NOT call registerBlockType() anymore.

    So the clean structure should be:

    1) PHP → register_block_type( path/to/block-folder )
    2) block.json → metadata + render callback
    3) editor.js → editor UI only (NO registerBlockType)

    In other words:

    ❌ remove registerBlockType() completely from editor.js

    Your editor.js should only contain things like:

    • edit()
    • Inspector controls
    • block behavior

    Block registration is already handled by WordPress when it reads block.json. Once you remove the JS registration, the API version warning and duplicate registration issues should disappear.

    Thread Starter Imagencvp

    (@ncvp)

    Adding apiVersion: 3 to the registerBlockType() call in editor.js made the deprecation warning go away.
    editor.js is now this:

    (function(blocks, element) {
    var el = element.createElement;
    blocks.registerBlockType('ncvp/header-menu', {
    apiVersion: 3,
    edit: function() {
    return el('div', {
    style: {
    padding: '20px',
    background: '#f0f0f0',
    border: '5px solid #0073aa',
    textAlign: 'center',
    borderRadius: '10px'
    }
    }, [
    el('strong', {
    style: {
    fontSize: '18px',
    display: 'block',
    marginBottom: '10px'
    }
    }, 'DON\'T PANIC'),
    el('span', {}, 'ncvp header menu derived from Twenty Seventeen')
    ]);
    },
    save: function() {
    return null; // Dynamic block, rendered by PHP
    }
    });
    })(window.wp.blocks, window.wp.element);

    Thanks very much for your help

    I’m unsure of the etiquette in these forums. Can I delete the copy GitHub repo I’ve linked to above, or should I leave it in case anyone else is interested?

    ImagePouya

    (@pouyaebrhm)

    Thanks for the update — glad you got it working 👍

    Regarding the GitHub repo: it’s totally fine to leave it up, especially since it helps document the solution for others who might hit the same issue. No problem either way, but keeping it is usually appreciated in these forums.

    Thanks again for following up!

Viewing 9 replies - 1 through 9 (of 9 total)

You must be logged in to reply to this topic.