WordPress 6.8 ships in April 2025 and brings several developer-facing improvements: an updated Twenty Twenty-Five theme with new patterns, enhanced block-locking controls, improved wp_navigation block performance, and a new block.json field — allowedBlocks for InnerBlocks templates. Under the hood, the REST API gains batch endpoints improvements and the Script Modules API reaches stable status.
Problem: A WordPress site is running version 6.7 and the upgrade notes for 6.8 are unclear about which changes require plugin or theme code updates versus which are automatic engine improvements.
Solution: WordPress 6.8 introduces a client-side router for block-theme navigation (no full page reload between pages using the Interactivity API), updates to the HTML API with full tag processor support for custom elements, and a new wp_admin_notice() function replacing direct admin_notices output. Review your plugin's admin_notices callbacks and any navigation-related JavaScript for compatibility.
The examples below demonstrate the new allowedBlocks restriction in block.json, the improved batch REST request format, and how to register a block with the new render_callback improvements available in 6.8.
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "my-plugin/feature-card",
"title": "Feature Card",
"category": "design",
"attributes": {
"heading": { "type": "string", "default": "" },
"highlighted": { "type": "boolean", "default": false }
},
"supports": {
"html": false,
"color": { "background": true, "text": true },
"spacing": { "padding": true }
},
"usesContext": [ "postId", "postType" ],
"providesContext": { "my-plugin/isHighlighted": "highlighted" },
"editorScript": "file:./index.js",
"style": "file:./style.css"
}
<?php
// Register block with dynamic render_callback receiving full context (6.8)
add_action( 'init', function () {
register_block_type( __DIR__, [
'render_callback' => function ( array $attrs, string $content, WP_Block $block ): string {
$post_id = $block->context['postId'] ?? get_the_ID();
$highlighted = (bool) ( $attrs['highlighted'] ?? false );
$heading = esc_html( $attrs['heading'] ?? '' );
$class = 'feature-card' . ( $highlighted ? ' feature-card--highlighted' : '' );
return sprintf(
'<div class="%s"><h3>%s</h3><div class="feature-card__body">%s</div></div>',
esc_attr( $class ),
$heading,
$content
);
},
] );
} );
// Batch REST API request (6.8 improved format)
// POST /wp-json/batch/v1
$batch_requests = [
'requests' => [
[ 'method' => 'GET', 'path' => '/wp/v2/posts?per_page=5' ],
[ 'method' => 'GET', 'path' => '/wp/v2/categories' ],
[ 'method' => 'PATCH', 'path' => '/wp/v2/posts/42',
'body' => [ 'status' => 'publish' ] ],
],
'validation' => 'require-all-validate', // fail whole batch if any request fails validation
];
NOTE: The validation: require-all-validate option in batch requests is a 6.8 addition; without it the default is normal, which validates and executes each request independently — use require-all-validate when all batch items must succeed together to avoid partial-update inconsistencies.