title: >- Anatomía de block.json (Block API v3), Colecciones de Metadatos y Arquitectura del Bloque Moderno description: >- Análisis en profundidad de la especificación block.json en WordPress 7.0+ "Armstrong" (Block API v3): editor canvas en iframe aislado, módulos ES frontend (viewScriptModule), árbol de contexto (providesContext / usesContext), compilación de manifiestos con wp_register_block_metadata_collection() y carga condicional de assets. module: gutenberg-blocks order: 1 difficulty: intermediate estimatedTime: 35 min topics:
En las primeras versiones de Gutenberg, el registro de un bloque estaba fracturado entre dos mundos divergentes: parte de la configuración se duplicaba en JavaScript dentro de registerBlockType(), mientras que la otra parte residía en PHP. Esto provocaba desincronizaciones en el esquema de atributos durante el renderizado del lado del servidor (SSR), la imposibilidad de analizar estáticamente las dependencias sin ejecutar el paquete JS completo y descargas forzadas de cientos de kilobytes de CSS y JS en cada página del sitio.
En WordPress 7.0+ ("Armstrong"), la Única Fuente de Verdad (Single Source of Truth) para cualquier bloque es el manifiesto declarativo block.json bajo la especificación Block API v3 ("apiVersion": 3). Este archivo JSON orquesta simultáneamente cuatro subsistemas del núcleo:
apiVersion: 3): garantiza que los estilos de administración de WordPress (wp-admin) nunca contaminen la maquetación de tu bloque, asegurando un escalado impecable en las vistas previas de tabletas y teléfonos inteligentes.should_load_separate_core_block_assets): el núcleo analiza post_content antes de enviar la respuesta HTTP e inyecta en el frontend (style, viewStyle, viewScriptModule) estrictamente los módulos CSS/JS cuyos bloques están realmente presentes en la página actual.providesContext / usesContext): permite a los bloques contenedores padre propagar estado a bloques descendientes a cualquier profundidad sin recurrir a variables globales ni a prop-drilling.wp_register_block_metadata_collection): elimina la sobrecarga de I/O en disco (file_get_contents + json_decode) al registrar decenas de bloques en grandes sistemas de diseño corporativos.Imagina block.json como el manifiesto de carga de un contenedor en un puerto marítimo automatizado (Núcleo de WordPress 7.0+). La grúa pórtico no necesita abrir el contenedor e iniciar el motor en su interior (ejecutar tu bundle de React index.js) solo para inspeccionar sus dimensiones, peso bruto, régimen térmico y terminal de destino. Al leer únicamente la etiqueta declarativa block.json, el servidor comprende de inmediato:
<!-- wp:agentic/metric-card {...} -->;theme.json v3) deben autogenerarse en la barra lateral del editor mediante la sección supports;viewScriptModule) debe encolarse vía <script type="module"> en el navegador del visitante.MANIFIESTO UNIFICADO: block.json (apiVersion: 3)
│
┌────────────────────────────────┼────────────────────────────────┐
▼ ▼ ▼
┌───────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐
│ PLANO PHP (Servidor) │ │ PLANO EDITOR (Iframe)│ │ PLANO FRONTEND (Edge)│
├───────────────────────┤ ├───────────────────────┤ ├───────────────────────┤
│ • Validación Atributos│ │ • editorScript (React)│ │ • style / viewStyle │
│ • render: render.php │ │ • editorStyle │ │ • viewScriptModule │
│ • Traspaso de $context│ │ • Autogeneración de │ │ (Native ES Modules) │
│ • Enqueue Condicional │ │ Inspector Controls │ │ • Interactivity API │
└───────────────────────┘ └───────────────────────┘ └───────────────────────┘El empaquetador compila TypeScript/SCSS en build/, genera .asset.php con hashes de versión y compila un blocks-manifest.php unificado para la biblioteca.
PHP registra la colección con wp_register_block_metadata_collection() e inicia los bloques desde memoria sin consultar decenas de archivos JSON en disco.
En Gutenberg, el bloque se monta en un <iframe> aislado; el núcleo construye automáticamente paneles de color, espaciado y bordes según la declaración supports.
Al guardar el post, los atributos se validan contra el esquema y se serializan en post_content como un delimitador estructurado <!-- wp:namespace/slug -->.
Al renderizar la página, el núcleo detecta el bloque, ejecuta render.php y carga viewScriptModule mediante Import Maps del navegador SOLO en esa página.
En los proyectos empresariales de Fullstack Agentic Lab, un diseño riguroso de block.json resuelve cuatro objetivos críticos:
editorScript (pesadas dependencias de autoría en React) de un viewScriptModule ultraligero (< 3 KB), el visitante del sitio recibe 0 bytes de código de edición.supports): en lugar de escribir cientos de líneas de componentes ColorPalette, BoxControl y FontSizePicker en React, activar "spacing", "color", "typography" y "shadow" en block.json provee controles nativos de Gutenberg sincronizados con los tokens de theme.json v3 sin coste alguno."supports": { "interactivity": true } habilita la hidratación en cliente de directivas data-wp-* y navegación fluida sin recargas de página completas.wp_register_block_types_from_metadata_collection() con cero sobrecarga en el sistema de archivos.Comparación entre el registro heredado de bloques (Block API v1/v2 con encolado manual mediante wp_enqueue_script) y el estándar moderno Block API v3 en WordPress 7.0+:
A continuación se presenta el artefacto de producción de referencia para WordPress 7.0+ y PHP 8.4+, que incluye la especificación completa de block.json (apiVersion: 3) para una tarjeta interactiva de telemetría de infraestructura y un cargador de colecciones sin operaciones de I/O en disco.
<?php
/**
* Plugin Name: Fullstack Agentic Lab — Block API v3 & Metadata Collection Engine
* Description: Registro instantáneo de biblioteca de bloques mediante manifiesto precompilado.
* Version: 3.2.0
* Requires at least: 6.8
* Requires PHP: 8.4
* Author: Artur Yusupov (Fullstack Agentic Lab)
*/
declare(strict_types=1);
namespace AgenticLab\Blocks;
defined('ABSPATH') || exit;
final readonly class BlockLibraryRegistrar
{
public function __construct(
private string $buildDir,
private string $manifestFile,
) {}
public function registerHooks(): void
{
add_action('init', $this->registerAllBlocks(...), 10);
add_filter('block_categories_all', $this->registerCustomCategory(...), 10, 1);
}
/**
* Registra toda la colección de bloques en O(1) accesos a disco (WordPress 6.8 / 7.0+).
*/
public function registerAllBlocks(): void
{
// Forzar carga separada de CSS estrictamente para bloques presentes en la página
add_filter('should_load_separate_core_block_assets', '__return_true');
if (function_exists('wp_register_block_types_from_metadata_collection')) {
wp_register_block_types_from_metadata_collection($this->buildDir, $this->manifestFile);
return;
}
// Fallback para entornos heredados con registro de colección e iteración manual
if (function_exists('wp_register_block_metadata_collection') && is_readable($this->manifestFile)) {
wp_register_block_metadata_collection($this->buildDir, $this->manifestFile);
/** @var array<string, array<string, mixed>> $manifest */
$manifest = require $this->manifestFile;
foreach (array_keys($manifest) as $blockFolder) {
register_block_type($this->buildDir . '/' . $blockFolder);
}
}
}
/**
* Inyecta una categoría personalizada de componentes en el insertador de Gutenberg.
*
* @param array<int, array<string, mixed>> $categories
* @return array<int, array<string, mixed>>
*/
public function registerCustomCategory(array $categories): array
{
array_unshift($categories, [
'slug' => 'agentic-lab-architecture',
'title' => 'Fullstack Agentic Lab',
'icon' => 'performance',
]);
return $categories;
}
}
(new BlockLibraryRegistrar(
buildDir: __DIR__ . '/build/blocks',
manifestFile: __DIR__ . '/build/blocks-manifest.php',
))->registerHooks();
/*
* ============================================================================
* ARCHIVO DE REFERENCIA: build/blocks/telemetry-card/block.json (Block API v3)
* ============================================================================
* {
* "$schema": "https://schemas.wp.org/trunk/block.json",
* "apiVersion": 3,
* "name": "agentic-lab/telemetry-card",
* "version": "3.2.0",
* "title": "Architecture Telemetry Card",
* "category": "agentic-lab-architecture",
* "icon": "chart-area",
* "description": "Tarjeta interactiva de telemetría con soporte para Interactivity API y Block Context.",
* "keywords": ["telemetry", "metrics", "benchmark", "agentic"],
* "textdomain": "agentic-lab",
* "attributes": {
* "serviceName": {
* "type": "string",
* "default": "Edge Worker Gateway"
* },
* "latencyP95Ms": {
* "type": "number",
* "default": 14
* },
* "uptimePercent": {
* "type": "number",
* "default": 99.99
* },
* "statusLevel": {
* "type": "string",
* "enum": ["optimal", "degraded", "critical"],
* "default": "optimal"
* }
* },
* "providesContext": {
* "agentic-lab/statusLevel": "statusLevel"
* },
* "usesContext": [
* "postId",
* "postType",
* "agentic-lab/environmentMode"
* ],
* "supports": {
* "html": false,
* "align": ["wide", "full"],
* "interactivity": {
* "clientNavigation": true,
* "interactive": true
* },
* "color": {
* "background": true,
* "gradients": true,
* "text": true
* },
* "spacing": {
* "padding": true,
* "margin": ["top", "bottom"],
* "blockGap": true
* },
* "typography": {
* "fontSize": true,
* "lineHeight": true
* },
* " '__experimentalBorder' -> border ": {
* "radius": true,
* "width": true,
* "color": true
* },
* "shadow": true
* },
* "editorScript": "file:./index.js",
* "editorStyle": "file:./index.css",
* "style": "file:./style-index.css",
* "viewScriptModule": "file:./view.js",
* "render": "file:./render.php"
* }
*/
Define tipos estrictos (string, number, boolean, object, array), valores por defecto y listas enum sin emplear selectores frágiles de DOM source.
En lugar de codificar controles personalizados de padding, bordes y paletas, habilita color, spacing, typography, border y shadow, que se vincularán automáticamente a theme.json v3.
Mantén las dependencias de React estrictamente en editorScript y entrega la interactividad del frontend mediante un módulo ES nativo con viewScriptModule.
Ejecuta wp-scripts build --blocks-manifest para compilar un archivo único blocks-manifest.php y vincúlalo mediante wp_register_block_types_from_metadata_collection().