{"id":1923,"date":"2026-05-18T09:30:46","date_gmt":"2026-05-18T07:30:46","guid":{"rendered":"https:\/\/www.unleash-wp.com\/blog\/?p=1923"},"modified":"2026-05-18T10:15:08","modified_gmt":"2026-05-18T08:15:08","slug":"wordpress-7-0-developer-prep","status":"publish","type":"post","link":"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/","title":{"rendered":"Prepare for WordPress 7.0: the developer&#8217;s audit list"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">WordPress 7.0 launches on <strong>Wednesday, May 20<\/strong>. The headline feature was supposed to be real-time collaboration. That got pulled three weeks before launch after architectural issues with how it interacted with post caches, and it&#8217;s been deferred to 7.1. What&#8217;s left is bigger for plugin developers anyway: a provider-agnostic AI Client baked into Core, a full JavaScript counterpart to the Abilities API, and a Connectors infrastructure for managing AI provider plugins. Plugin developers now build against a stable AI abstraction instead of hard-coding vendor SDKs. This is the biggest architectural addition to WordPress since Gutenberg shipped in 2018.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ve spent the last weeks running 7.0 RC against blocks and plugins I maintain through <a href=\"https:\/\/www.kreo-pulse.com\/en\/\" type=\"link\" id=\"https:\/\/www.kreo-pulse.com\/en\/\" target=\"_blank\" rel=\"noreferrer noopener\">Kreo Pulse<\/a> and UnleashWP. The AI stack is the priority before you build against 7.0. The rest is migration work, and one piece of it has a high chance of breaking blocks you&#8217;ve already shipped if you don&#8217;t audit <code>block.json<\/code> before Wednesday.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the pre-launch read.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img  decoding=\"async\"  width=\"1024\"  height=\"496\"  src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAABAAAAAHwAQMAAAACeY9+AAAAA1BMVEUAAP+KeNJXAAAAAXRSTlMAQObYZgAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAFRJREFUeNrtwQEBAAAAgiD\/r25IQAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7wb58AABVpKpNQAAAABJRU5ErkJggg==\"  alt=\"WordPress AI conntectors\"  class=\"wp-image-1934 pk-lazyload\"  data-pk-sizes=\"auto\"  data-ls-sizes=\"(max-width: 1024px) 100vw, 1024px\"  data-pk-src=\"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector-1024x496.png\"  data-pk-srcset=\"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector-1024x496.png 1024w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector-300x145.png 300w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector-768x372.png 768w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector-1536x745.png 1536w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector-2048x993.png 2048w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector-528x256.png 528w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector-1056x512.png 1056w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector-820x398.png 820w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector-1240x601.png 1240w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector-1920x931.png 1920w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector-2112x1024.png 2112w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector-1640x795.png 1640w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector-2480x1202.png 2480w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector-600x291.png 600w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-connector.png 2560w\" ><figcaption class=\"wp-element-caption\">WordPress AI conntectors<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-the-ai-client-the-new-substrate\"><span id=\"the-ai-client-the-new-substrate\">The AI Client: the new substrate<\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The WP AI Client is the centerpiece of the 7.0 release. It sits on top of the [<code>wordpress\/php-ai-client<\/code>]. SDK that Core now bundles as a dependency.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you aren&#8217;t adding AI features in this release, you can skip ahead. If you are, or if you&#8217;re maintaining a plugin that already calls AI providers directly, read this carefully. Direct vendor integrations are what 7.0 lets you stop maintaining.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Your plugin describes what it wants. Core routes the request to whichever provider the site owner has configured under <code>Settings &gt; Connectors<\/code>. You never touch API keys. Three official provider plugins ship alongside Core, one each for Anthropic, Google, and OpenAI. Custom providers register through the <a href=\"https:\/\/make.wordpress.org\/core\/2026\/03\/18\/introducing-the-connectors-api-in-wordpress-7-0\/\" target=\"_blank\" rel=\"noreferrer noopener\">Connectors API<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Keeping the providers as separate plugins is deliberate. Provider APIs change too fast for Core&#8217;s release cadence. The abstraction lives in Core, the providers ship updates whenever they need to.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-the-basic-pattern\"><span id=\"the-basic-pattern\">The basic pattern<\/span><\/h4>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\n$text = wp_ai_client_prompt( &#039;Summarize the benefits of object caching in WordPress.&#039; )\n    -&gt;using_temperature( 0.7 )\n    -&gt;generate_text();\n\nif ( is_wp_error( $text ) ) {\n    return;\n}\n\necho wp_kses_post( $text );\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\"><code>wp_ai_client_prompt()<\/code> returns a <code>WP_AI_Client_Prompt_Builder<\/code>. Chain configuration on, then call a generation method. Errors come back as <code>WP_Error<\/code> rather than exceptions. The Core wrapper catches exceptions from the underlying SDK and converts them.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-detect-before-you-render\"><span id=\"detect-before-you-render\">Detect before you render<\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Not every site has a provider configured. If you build UI around an AI feature that can&#8217;t run, your plugin breaks on those sites:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\n$builder = wp_ai_client_prompt( &#039;test&#039; )\n    -&gt;using_temperature( 0.7 );\n\nif ( $builder-&gt;is_supported_for_text_generation() ) {\n    \/\/ Safe to render the feature UI.\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">These checks are deterministic and don&#8217;t make API calls. Available variants: <code>is_supported_for_text_generation()<\/code>, <code>is_supported_for_image_generation()<\/code>, <code>is_supported_for_text_to_speech_conversion()<\/code>, <code>is_supported_for_speech_generation()<\/code>, <code>is_supported_for_video_generation()<\/code>. Use them to hide UI, show a notice pointing to the Connectors screen, or skip enqueueing scripts when AI isn&#8217;t available.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-model-preferences\"><span id=\"model-preferences\">Model preferences<\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You don&#8217;t know which models the site has access to. Express a preference and let Core fall back:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\n$result = wp_ai_client_prompt( &#039;Summarize the history of the printing press.&#039; )\n    -&gt;using_temperature( 0.1 )\n    -&gt;using_model_preference(\n        &#039;claude-sonnet-4-6&#039;,\n        &#039;gemini-3.1-pro-preview&#039;,\n        &#039;gpt-5.4&#039;\n    )\n    -&gt;generate_text_result();\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">A preference, not a requirement. If none of your listed models are available, Core picks a compatible one. Your plugin needs to function either way.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>generate_*_result()<\/code> variants return a <code>GenerativeAiResult<\/code> with metadata: token usage, provider, model. Useful for logging and audit trails. The object is serializable and returns cleanly from a REST callback:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\nfunction unleashwp_ai_summary_callback( WP_REST_Request $request ) {\n    $result = wp_ai_client_prompt( $request-&gt;get_param( &#039;prompt&#039; ) )\n        -&gt;generate_text_result();\n\n    return rest_ensure_response( $result );\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\"><code>WP_Error<\/code> objects work the same way in <code>rest_ensure_response()<\/code>, with appropriate HTTP codes attached.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-cache-aggressively\"><span id=\"cache-aggressively\">Cache aggressively<\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The dev note doesn&#8217;t say it explicitly, so I will. Every AI call costs money and time. If you&#8217;re generating content that doesn&#8217;t need to be unique per-request, wrap the call:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\nfunction unleashwp_get_ai_summary( int $post_id ): string {\n    $modified  = get_post_modified_time( &#039;U&#039;, false, $post_id );\n    $cache_key = &#039;unleashwp_ai_summary_&#039; . $post_id . &#039;_&#039; . $modified;\n    $cached    = get_transient( $cache_key );\n\n    if ( false !== $cached ) {\n        return $cached;\n    }\n\n    $result = wp_ai_client_prompt( get_post_field( &#039;post_content&#039;, $post_id ) )\n        -&gt;using_system_instruction( &#039;Summarize the article in three sentences.&#039; )\n        -&gt;generate_text();\n\n    if ( is_wp_error( $result ) ) {\n        return &#039;&#039;;\n    }\n\n    set_transient( $cache_key, $result, WEEK_IN_SECONDS );\n    return $result;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Keying the transient on <code>get_post_modified_time()<\/code> lets the cache invalidate naturally when the post is edited. Skipping the cache layer is the fastest way to surprise a client with a four-digit API bill.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-govern-at-the-site-level\"><span id=\"govern-at-the-site-level\">Govern at the site level<\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">For administrators who want hard limits on what AI calls can happen, the <code>wp_ai_client_prevent_prompt<\/code> filter blocks prompts before they execute:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\nadd_filter(\n    &#039;wp_ai_client_prevent_prompt&#039;,\n    function ( bool $prevent, WP_AI_Client_Prompt_Builder $builder ): bool {\n        if ( ! current_user_can( &#039;edit_posts&#039; ) ) {\n            return true;\n        }\n        return $prevent;\n    },\n    10,\n    2\n);\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">When a prompt is prevented, no call is attempted, <code>is_supported_*()<\/code> returns <code>false<\/code> so plugins can hide their UI, and <code>generate_*()<\/code> returns a <code>WP_Error<\/code>. This is the hook for rate limiting, role-based blocking, time-of-day controls, or quota management. Wire it in on any agency site where you can&#8217;t predict which plugins will start making AI calls.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-don-t-expose-the-javascript-ai-client-in-distributed-plugins\"><span id=\"dont-expose-the-javascript-ai-client-in-distributed-plugins\">Don&#8217;t expose the JavaScript AI client in distributed plugins<\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">There&#8217;s a JavaScript counterpart to the AI Client, available through the [<code>wp-ai-client<\/code>] package. It looks convenient. The dev note is explicit that it isn&#8217;t the right choice for plugins shipped through the directory.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The reason: the client-side API allows arbitrary prompt execution. To prevent untrusted users from sending any prompt to a configured provider and burning through someone else&#8217;s credits, it requires a high-privilege capability check. By default that means administrators only.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Use the pattern shown above instead: a specific REST endpoint per AI feature, with granular permission checks there, and prompt configuration kept on the server. The JS API is fine for admin-only tools you build for yourself or for a specific client. For a plugin in the directory, don&#8217;t.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-migrating-from-the-standalone-packages\"><span id=\"migrating-from-the-standalone-packages\">Migrating from the standalone packages<\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;ve been bundling <code>wordpress\/php-ai-client<\/code> via Composer, the simplest migration is to bump <code>Requires at least<\/code> to 7.0, drop the Composer dependency, and replace <code>AI_Client::prompt()<\/code> calls with <code>wp_ai_client_prompt()<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you need to keep WP &lt; 7.0 support, you need a conditional autoloader so Composer doesn&#8217;t load duplicate class definitions alongside Core&#8217;s bundled copy:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\nif (\n    ! function_exists( &#039;wp_get_wp_version&#039; )\n    || version_compare( wp_get_wp_version(), &#039;7.0&#039;, &#039;&lt;&#039; )\n) {\n    require_once __DIR__ . &#039;\/vendor\/autoload.php&#039;;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The <code>function_exists()<\/code> guard handles older versions where <code>wp_get_wp_version()<\/code> doesn&#8217;t yet exist. Composer&#8217;s autoloader is all-or-nothing, so the conditional wraps the full autoload. If that&#8217;s too coarse for your dependency graph, split the AI packages into a separate Composer setup.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For <code>wordpress\/wp-ai-client<\/code>, the migration is simpler. It detects the WP version automatically and disables its own SDK on 7.0+ while keeping the REST endpoints and JavaScript API active. Load it unconditionally. The package is likely to be discontinued once those pieces land in Gutenberg or Core (tracked in <a href=\"https:\/\/core.trac.wordpress.org\/ticket\/64872\" target=\"_blank\" rel=\"noreferrer noopener\">#64872<\/a> and <a href=\"https:\/\/core.trac.wordpress.org\/ticket\/64873\" target=\"_blank\" rel=\"noreferrer noopener\">#64873<\/a>).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One housekeeping detail. If your plugin&#8217;s AI features genuinely require a specific provider plugin to be present, declare that with the <code>Requires Plugins<\/code> header in your main plugin file. The dependency surfaces to administrators on install, which avoids &#8220;AI feature broken&#8221; support tickets from missing provider plugins.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-the-abilities-api-the-underrated-piece\"><span id=\"the-abilities-api-the-underrated-piece\">The Abilities API: the underrated piece<\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The Abilities API itself isn&#8217;t new. It shipped in 6.9. What&#8217;s new in 7.0 is the full JavaScript counterpart and the tighter integration with the AI Client.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">An ability is a named callback with a schema. You give it a name, a description, an input schema, an output schema, a permission callback, and a function that runs when something calls it. The &#8220;something&#8221; can be your own code, another plugin, an AI agent through the AI Client, or, coming soon, a browser extension implementing <a href=\"https:\/\/github.com\/WordPress\/ai\/pull\/224\" target=\"_blank\" rel=\"noreferrer noopener\">WebMCP<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That last part is what makes the Abilities API more than an AI feature. It&#8217;s the workflow primitive WordPress hasn&#8217;t had: a permission-checked, schema-validated way to expose plugin actions to anything that knows the abilities store.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-the-two-packages\"><span id=\"the-two-packages\">The two packages<\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The client side ships as two packages:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>@wordpress\/abilities<\/code> is the pure store: registration, querying, execution, no server dependencies. You can use it in non-WordPress JS projects.<\/li>\n\n\n\n<li><code>@wordpress\/core-abilities<\/code> is the WordPress integration. Loading it fetches all server-registered abilities (via <code>\/wp-abilities\/v1\/<\/code>) into the client store. WordPress Core enqueues it on every admin page, so server abilities are available in the admin by default.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Most plugins want <code>@wordpress\/core-abilities<\/code>. Enqueue it as a script module:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\nadd_action( &#039;admin_enqueue_scripts&#039;, function () {\n    wp_enqueue_script_module( &#039;@wordpress\/core-abilities&#039; );\n} );\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">If you only need client-side abilities scoped to one admin page, enqueue <code>@wordpress\/abilities<\/code> instead and skip the REST round-trip.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-registering-an-ability\"><span id=\"registering-an-ability\">Registering an ability<\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Categories are required and have to exist before abilities register. Server-side categories load automatically. Client-side ones you declare yourself:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nconst { registerAbilityCategory, registerAbility } = await import( &#039;@wordpress\/abilities&#039; );\n\nregisterAbilityCategory( &#039;unleashwp-actions&#039;, {\n    label: &#039;UnleashWP Actions&#039;,\n    description: &#039;Workflow actions provided by UnleashWP plugins&#039;,\n} );\n\nregisterAbility( {\n    name: &#039;unleashwp\/create-item&#039;,\n    label: &#039;Create Item&#039;,\n    description: &#039;Creates a new item with the given title and content&#039;,\n    category: &#039;unleashwp-actions&#039;,\n    input_schema: {\n        type: &#039;object&#039;,\n        properties: {\n            title: { type: &#039;string&#039;, minLength: 1 },\n            content: { type: &#039;string&#039; },\n            status: { type: &#039;string&#039;, enum: &#x5B; &#039;draft&#039;, &#039;publish&#039; ] },\n        },\n        required: &#x5B; &#039;title&#039; ],\n    },\n    output_schema: {\n        type: &#039;object&#039;,\n        properties: {\n            id: { type: &#039;number&#039; },\n            title: { type: &#039;string&#039; },\n        },\n        required: &#x5B; &#039;id&#039; ],\n    },\n    permissionCallback: () =&gt; currentUserCan( &#039;edit_posts&#039; ),\n    callback: async ( { title, content, status = &#039;draft&#039; } ) =&gt; {\n        \/\/ Create the item.\n        return { id: 123, title };\n    },\n} );\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Input and output are validated against their JSON schemas when <code>executeAbility()<\/code> is called. Permission callbacks run first; a failure throws <code>ability_permission_denied<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One caveat to flag before you build on this: the input schema validation currently doesn&#8217;t support a <code>sanitize_callback<\/code> property, which the AI plugin already relies on. This was raised on the dev note (<a href=\"https:\/\/github.com\/WordPress\/ai\/issues\/346\" target=\"_blank\" rel=\"noreferrer noopener\">WordPress\/ai#346<\/a>), with a fix proposed in <a href=\"https:\/\/github.com\/WordPress\/gutenberg\/pull\/77029\" target=\"_blank\" rel=\"noreferrer noopener\">Gutenberg PR #77029<\/a>. Track it if you plan to register abilities that consume AI-generated input.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-executing-and-reacting\"><span id=\"executing-and-reacting\">Executing and reacting<\/span><\/h4>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nimport { executeAbility } from &#039;@wordpress\/abilities&#039;;\n\ntry {\n    const result = await executeAbility( &#039;unleashwp\/create-item&#039;, {\n        title: &#039;New Item&#039;,\n        content: &#039;Item content&#039;,\n        status: &#039;draft&#039;,\n    } );\n} catch ( error ) {\n    switch ( error.code ) {\n        case &#039;ability_permission_denied&#039;:\n        case &#039;ability_invalid_input&#039;:\n        case &#039;ability_invalid_output&#039;:\n            \/\/ Handle the specific failure mode.\n            break;\n    }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">For reactive UIs, the abilities store integrates with <code>@wordpress\/data<\/code>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nimport { useSelect } from &#039;@wordpress\/data&#039;;\nimport { store as abilitiesStore } from &#039;@wordpress\/abilities&#039;;\n\nfunction AbilitiesList() {\n    const abilities = useSelect(\n        ( select ) =&gt; select( abilitiesStore ).getAbilities(),\n        &#x5B;]\n    );\n    \/\/ ...\n}\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\" id=\"h-annotations-decide-http-semantics\"><span id=\"annotations-decide-http-semantics\">Annotations decide HTTP semantics<\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">When a server-side ability is executed through the client, the underlying REST call uses an HTTP method derived from the ability&#8217;s annotations:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>readonly: true<\/code> produces <code>GET<\/code><\/li>\n\n\n\n<li><code>destructive: true<\/code> plus <code>idempotent: true<\/code> produces <code>DELETE<\/code><\/li>\n\n\n\n<li>Everything else produces <code>POST<\/code><\/li>\n<\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nregisterAbility( {\n    name: &#039;unleashwp\/get-stats&#039;,\n    \/\/ ...\n    meta: {\n        annotations: {\n            readonly: true,\n        },\n    },\n    callback: async () =&gt; ( { views: 100 } ),\n} );\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Annotate your abilities correctly. A misannotated <code>destructive<\/code> ability gets the wrong HTTP semantics, which has implications for caching, retries, and middleware that respects HTTP method conventions.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-why-this-matters-even-without-ai\"><span id=\"why-this-matters-even-without-ai\">Why this matters even without AI<\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The Abilities API is a clean way to expose plugin functionality to other code, with typed contracts, permissions, and a single execution path. Even without an AI agent in sight, declaring your plugin&#8217;s actions as abilities means they become callable from any other plugin, from custom admin interfaces you build later, and from any future workflow runner that targets the abilities store.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For agency work, this is the part I&#8217;m most quietly excited about. The Abilities API is what custom admin scripts in WordPress should have looked like for a decade.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-the-block-json-audit-before-wednesday\"><span id=\"the-block-json-audit-before-wednesday\">The block.json audit before Wednesday<\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The migration item that breaks plugins. Unsynced patterns and template parts now default to <code>contentOnly<\/code> editing mode. The mechanism shipped in 6.7. What&#8217;s new is the default state. As of Wednesday, every pattern your block ends up in runs in <code>contentOnly<\/code> mode unless somebody flips the switch off, which most sites won&#8217;t.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Inside <code>contentOnly<\/code>, users edit text and media. The deeper block structure stays hidden, style controls don&#8217;t open. What counts as editable content lives in your <code>block.json<\/code>, on each attribute&#8217;s <code>role<\/code> property:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n{\n  &quot;attributes&quot;: {\n    &quot;url&quot;: {\n      &quot;type&quot;: &quot;string&quot;,\n      &quot;role&quot;: &quot;content&quot;\n    },\n    &quot;label&quot;: {\n      &quot;type&quot;: &quot;string&quot;,\n      &quot;role&quot;: &quot;content&quot;\n    }\n  }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Blocks without any <code>\"role\": \"content\"<\/code> attribute are hidden from List View and unselectable inside a <code>contentOnly<\/code> container. Shape of the failure: client opens a pattern on a 7.0 site, tries to edit a label, can&#8217;t find the block in List View, opens a ticket Thursday morning. You know that conversation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For blocks without an obvious content attribute, the <a href=\"https:\/\/make.wordpress.org\/core\/2026\/03\/15\/pattern-editing-in-wordpress-7-0\/\" target=\"_blank\" rel=\"noreferrer noopener\">Pattern Editing dev note<\/a> describes a <code>\"contentRole\": true<\/code> flag at the supports level. The note&#8217;s own code example shows <code>\"contentOnly\": true<\/code> instead, which looks like an editorial inconsistency rather than the intended API. Verify against the current Core source before relying on either spelling. The dev note text is clear: prefer <code>\"role\": \"content\"<\/code> on a specific attribute where possible.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you build parent-child block pairs, the rule changes slightly. When both parent and child declare a content role, <code>contentOnly<\/code> mode allows insertion of new child blocks. Core examples: List with List Item, Gallery with Image, Buttons with Button. If you ship a Testimonials block with Testimonial items or a Pricing Table with Tiers, declare content roles on both sides. Otherwise users can&#8217;t add new items inside a pattern.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For site owners who want to opt out of the new default outright, there&#8217;s an escape valve. Via PHP:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\nadd_filter( &#039;block_editor_settings_all&#039;, function( $settings ) {\n    $settings&#x5B;&#039;disableContentOnlyForUnsyncedPatterns&#039;] = true;\n    return $settings;\n} );\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Or via JavaScript on the client:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nwp.data.dispatch( &#039;core\/block-editor&#039; ).updateSettings( {\n    disableContentOnlyForUnsyncedPatterns: true,\n} );\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">A per-site valve, not a fix for plugin authors. Template parts and synced patterns stay in <code>contentOnly<\/code> mode regardless. The right move is to update your blocks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">While you&#8217;re in <code>block.json<\/code>, add <code>\"listView\": true<\/code> to supports for any block that contains inner blocks. New in 7.0, this adds a List View tab to the block inspector with a dedicated UI for rearranging and adding children. Useful inside patterns too.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">An hour per plugin if your <code>block.json<\/code> files were tidy to start with. Longer if not. Run it today.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-php-only-block-registration-the-quiet-shift\"><span id=\"php-only-block-registration-the-quiet-shift\">PHP-only block registration: the quiet shift<\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The implementation (<a href=\"https:\/\/core.trac.wordpress.org\/ticket\/64639\" target=\"_blank\" rel=\"noreferrer noopener\">Trac #64639<\/a>) lets you register a fully functional block in PHP only: no <code>edit.js<\/code>, no Webpack pipeline, no <code>block.json<\/code> file.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: php; title: ; notranslate\" title=\"\">\nfunction unleashwp_register_php_blocks() {\n    register_block_type(\n        &#039;unleashwp\/example&#039;,\n        array(\n            &#039;title&#039;           =&gt; &#039;Example Block&#039;,\n            &#039;attributes&#039;      =&gt; array(\n                &#039;title&#039;   =&gt; array(\n                    &#039;type&#039;    =&gt; &#039;string&#039;,\n                    &#039;default&#039; =&gt; &#039;Hello World&#039;,\n                ),\n                &#039;count&#039;   =&gt; array(\n                    &#039;type&#039;    =&gt; &#039;integer&#039;,\n                    &#039;default&#039; =&gt; 5,\n                ),\n                &#039;enabled&#039; =&gt; array(\n                    &#039;type&#039;    =&gt; &#039;boolean&#039;,\n                    &#039;default&#039; =&gt; true,\n                ),\n                &#039;size&#039;    =&gt; array(\n                    &#039;type&#039;    =&gt; &#039;string&#039;,\n                    &#039;enum&#039;    =&gt; array( &#039;small&#039;, &#039;medium&#039;, &#039;large&#039; ),\n                    &#039;default&#039; =&gt; &#039;medium&#039;,\n                ),\n            ),\n            &#039;render_callback&#039; =&gt; function ( $attributes, $content, $block ) {\n                return sprintf(\n                    &#039;&lt;div class=&quot;unleashwp-example unleashwp-example--%s&quot;&gt;%s: %d&lt;\/div&gt;&#039;,\n                    esc_attr( $attributes&#x5B;&#039;size&#039;] ),\n                    esc_html( $attributes&#x5B;&#039;title&#039;] ),\n                    (int) $attributes&#x5B;&#039;count&#039;]\n                );\n            },\n            &#039;supports&#039;        =&gt; array(\n                &#039;autoRegister&#039; =&gt; true,\n            ),\n        )\n    );\n}\nadd_action( &#039;init&#039;, &#039;unleashwp_register_php_blocks&#039; );\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">That&#8217;s the whole block. It appears in the inserter, gets an automatically-generated Inspector Controls sidebar from the declared attributes (text input for <code>title<\/code>, number for <code>count<\/code>, toggle for <code>enabled<\/code>, select for <code>size<\/code> with the enum values), and renders via the server-side callback. The <code>render_callback<\/code> signature is the standard three-parameter form. Even if you only use <code>$attributes<\/code>, declaring all three keeps signatures consistent across your codebase.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The sweet spot, for me, is dynamic content blocks that used to live as either shortcodes or ACF field groups: bound query results, dynamic listings, footer widgets that need to read site state, anywhere the user&#8217;s job is to pick a few values and let the server render the output. For an agency shipping client-specific blocks, this changes the calculus on what gets registered as a block in the first place.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">What it&#8217;s explicitly not for: blocks meant to be highly interactive. The auto-generated inspector controls handle scalar types like string, integer, boolean, and enum. They don&#8217;t handle image uploads, media pickers, rich text editing inside the block, or custom React controls. If your block needs any of that, JavaScript registration is still the path.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A few open questions from the early Make\/Core comments that aren&#8217;t fully resolved: inner blocks aren&#8217;t supported through PHP-only registration yet, and media picker attributes don&#8217;t get auto-generated controls. If either describes a block you want to build, stick with JS for now.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This isn&#8217;t a Wednesday-deadline item. PHP-only registration is forward-compatible with everything that already works. It&#8217;s a tool to keep in mind for your next custom block, not a migration step.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img  decoding=\"async\"  width=\"1024\"  height=\"517\"  src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAABAAAAAIFAQMAAAB2zh1JAAAAA1BMVEUAAP+KeNJXAAAAAXRSTlMAQObYZgAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAFdJREFUeNrtwTEBAAAAwqD1T20MH6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4GwElAABDTOxMwAAAABJRU5ErkJggg==\"  alt=\"WordPress Font Manager for Classic Themes\"  class=\"wp-image-1945 pk-lazyload\"  data-pk-sizes=\"auto\"  data-ls-sizes=\"(max-width: 1024px) 100vw, 1024px\"  data-pk-src=\"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-font-manager-1024x517.png\"  data-pk-srcset=\"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-font-manager-1024x517.png 1024w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-font-manager-300x151.png 300w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-font-manager-768x388.png 768w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-font-manager-1536x776.png 1536w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-font-manager-528x267.png 528w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-font-manager-1056x533.png 1056w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-font-manager-820x414.png 820w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-font-manager-1240x626.png 1240w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-font-manager-1920x969.png 1920w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-font-manager-1640x828.png 1640w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-font-manager-600x303.png 600w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-font-manager.png 2048w\" ><figcaption class=\"wp-element-caption\">WordPress Font Manager for Classic Themes<\/figcaption><\/figure>\n\n\n\n<h3 id=\"font-library-lands-in-classic-themes\" class=\"wp-block-heading\">Font Library lands in classic themes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The Font Library shipped in 6.5 for block themes. In 7.0 it works for classic and hybrid themes too. Site owners upload custom fonts and install Google Fonts from <code>Appearance &gt; Fonts<\/code>, then apply them per block from the typography sidebar. The interface mirrors the Media Library, available as both a modal during editing and a dedicated admin section.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For agency teams maintaining classic themes, this closes a real friction point. Custom font management used to mean either a plugin dependency (Custom Fonts, Easy Google Fonts) or manual <code>@font-face<\/code> declarations in <code>functions.php<\/code>. Both go away. Your users get the same font workflow that block theme users have had for a year.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The bigger shift underneath: Global Styles now work on classic themes. <a href=\"https:\/\/github.com\/WordPress\/gutenberg\/pull\/73971\" target=\"_blank\" rel=\"noreferrer noopener\">Gutenberg PR #73971<\/a> wires the Styles UI to non-block themes by parsing theme defaults from CSS. If you maintain a classic theme, audit what users can now override through Global Styles. The cascade between your theme&#8217;s stylesheets and user-applied Global Styles is non-obvious. You may need to update stylesheet specificity or ship a <code>theme.json<\/code> partial to keep the design intent intact.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If your plugin&#8217;s value proposition is font management for non-FSE sites, the ground shifted. Core handles upload, library, and per-block application. What&#8217;s left as plugin territory: subsetting, performance optimization, font pairing, advanced typography controls. Reposition before launch day.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-the-smaller-things-shipping-wednesday\"><span id=\"the-smaller-things-shipping-wednesday\">The smaller things shipping Wednesday<\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The post editor runs in an iframe whenever every block in the post uses Block API v3 or higher. If any block is on <code>apiVersion: 2<\/code>, the iframe drops back for backwards compatibility. Your v2 blocks force every post they appear in out of the iframed experience. The v3 migration mostly comes down to your <code>edit<\/code> function&#8217;s wrapper element receiving the props from <code>useBlockProps()<\/code> directly, rather than relying on the editor adding them externally. If you&#8217;re already on v3, you&#8217;re done.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Minimum PHP is 7.4 now. PHP 7.2 and 7.3 are gone. Update <code>Requires PHP<\/code> before tagging.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Interactivity API picks up a <code>watch()<\/code> function in <code>@wordpress\/interactivity<\/code> that subscribes to any signal accessed inside a callback and re-runs the callback when those signals change, with a <code>data-wp-watch<\/code> directive on the DOM side. Useful if you&#8217;ve been wiring subscriptions manually. Administrator and Editor roles are no longer in the new-user role selector under <code>Settings &gt; General<\/code>, with Site Health flagging sites where one was previously selected and the <code>default_role_dropdown_excluded_roles<\/code> filter available if you need to add either back.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-your-wednesday-morning-decoded\"><span id=\"your-wednesday-morning-decoded\">Your Wednesday morning, decoded<\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If you tag a 7.0-compatible release today or tomorrow, here&#8217;s what should be in it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Audit <code>block.json<\/code> for every block you ship. Set <code>\"role\": \"content\"<\/code> on every editable attribute, add <code>\"listView\": true<\/code> to any container block&#8217;s supports, and bump <code>apiVersion<\/code> from 2 to 3 wherever you&#8217;re behind. Update <code>Requires PHP<\/code> to 7.4 and <code>Tested up to<\/code> to 7.0.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you bundle the <code>wordpress\/php-ai-client<\/code> or <code>wordpress\/wp-ai-client<\/code> Composer packages, follow the migration path in the AI Client dev note. If you&#8217;re adding AI features in this release, register your own REST endpoints rather than relying on the JavaScript AI client, and declare <code>Requires Plugins<\/code> for any provider plugin you depend on.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If your plugin exposes actions that other code might want to call (settings updates, content creation, that kind of thing), consider registering them as abilities. Not a Wednesday item, but put it on the list for your next release.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <a href=\"https:\/\/make.wordpress.org\/core\/2026\/05\/14\/wordpress-7-0-field-guide\/\" target=\"_blank\" rel=\"noreferrer noopener\">full Field Guide<\/a> links every individual dev note. Four are essential reading before you ship a 7.0-compatible plugin: the <a href=\"https:\/\/make.wordpress.org\/core\/2026\/03\/24\/introducing-the-ai-client-in-wordpress-7-0\/\" target=\"_blank\" rel=\"noreferrer noopener\">AI Client note<\/a>, the <a href=\"https:\/\/make.wordpress.org\/core\/2026\/03\/15\/pattern-editing-in-wordpress-7-0\/\" target=\"_blank\" rel=\"noreferrer noopener\">Pattern Editing note<\/a>, the <a href=\"https:\/\/make.wordpress.org\/core\/2026\/03\/24\/client-side-abilities-api-in-wordpress-7-0\/\" target=\"_blank\" rel=\"noreferrer noopener\">Client-Side Abilities note<\/a>, and the <a href=\"https:\/\/make.wordpress.org\/core\/2026\/03\/03\/php-only-block-registration\/\" target=\"_blank\" rel=\"noreferrer noopener\">PHP-only block registration note<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>May 20 is Wednesday. Make sure your plugin is ready before then.<\/strong><\/p>\n\n\n\n<div style=\"height:42px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-columns alignfull are-vertically-aligned-center has-border-color has-primary-border-color has-background is-layout-flex wp-container-core-columns-is-layout-8440f22b wp-block-columns-is-layout-flex\" style=\"border-width:1px;background-color:#20315917;padding-top:var(--wp--preset--spacing--70);padding-right:var(--wp--preset--spacing--60);padding-bottom:var(--wp--preset--spacing--70);padding-left:var(--wp--preset--spacing--60)\">\n<div class=\"wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:33.33%\">\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/europe.wordcamp.org\/2026\/session\/panel-inside-wordpress-7-0\/\" target=\"_blank\" rel=\" noreferrer noopener\"><img  decoding=\"async\"  width=\"1024\"  height=\"1024\"  src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAP+KeNJXAAAAAXRSTlMAQObYZgAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=\"  alt=\"Inside WordPress 7.0\"  class=\"wp-image-1936 pk-lazyload\"  data-pk-sizes=\"auto\"  data-ls-sizes=\"(max-width: 1024px) 100vw, 1024px\"  data-pk-src=\"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296-1024x1024.jpg\"  data-pk-srcset=\"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296-1024x1024.jpg 1024w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296-300x300.jpg 300w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296-150x150.jpg 150w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296-768x768.jpg 768w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296-80x80.jpg 80w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296-106x106.jpg 106w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296-212x212.jpg 212w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296-528x528.jpg 528w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296-1056x1056.jpg 1056w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296-820x820.jpg 820w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296-160x160.jpg 160w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296-424x424.jpg 424w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296-600x600.jpg 600w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296-800x800.jpg 800w, https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/1778002114296.jpg 1200w\" ><\/a><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:66.66%\">\n<h3 id=\"talking-about-7-0-at-wceu\" class=\"wp-block-heading\">Talking about 7.0 at WCEU<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ll be on the &#8220;<a href=\"https:\/\/europe.wordcamp.org\/2026\/session\/panel-inside-wordpress-7-0\/\" type=\"link\" id=\"https:\/\/europe.wordcamp.org\/2026\/session\/panel-inside-wordpress-7-0\/\" target=\"_blank\" rel=\"noreferrer noopener\">Inside WordPress 7.0<\/a>&#8221; panel at WordCamp Europe 2026 in Krak\u00f3w, June 4-6. Adam Silverstein, Sarah Norris, and Juan Manuel Garrido are on the panel with me, with Milana Cap moderating. We&#8217;ll cover what shipped in 7.0, what got pulled and why, and what&#8217;s coming in 7.1. The session is recorded and goes up on WordPress.tv after the event.<\/p>\n<\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Sources:<\/strong> <a href=\"https:\/\/make.wordpress.org\/core\/2026\/05\/14\/wordpress-7-0-field-guide\/\" type=\"link\" id=\"https:\/\/make.wordpress.org\/core\/2026\/05\/14\/wordpress-7-0-field-guide\/\" target=\"_blank\" rel=\"noreferrer noopener\">WordPress Core Blog<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"AI in Core, the JavaScript Abilities API, contentOnly pattern defaults, PHP-only block registration, and the Font Library for classic themes. The plugin developer&#8217;s pre-launch audit list.","protected":false},"author":1,"featured_media":1943,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_display_header_overlay":false,"csco_singular_sidebar":"","csco_page_header_type":"","csco_page_load_nextpost":"","csco_post_video_location":[],"csco_post_video_location_hash":"","csco_post_video_url":"","csco_post_video_bg_start_time":0,"csco_post_video_bg_end_time":0,"csco_post_video_bg_volume":false,"footnotes":""},"categories":[64,66,189],"tags":[213,279,195,227,191,223],"class_list":["post-1923","post","type-post","status-publish","format-standard","has-post-thumbnail","category-ai","category-development","category-gutenberg","tag-7-0","tag-block-development-2","tag-block-editor","tag-gutenberg-font-manager","tag-wordpress-7-0","tag-wordpress-font-management","cs-entry","cs-video-wrap"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.5 (Yoast SEO v27.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Prepare for WordPress 7.0: the developer&#039;s audit list<\/title>\n<meta name=\"description\" content=\"WordPress 7.0 launches Wednesday May 20 with AI in Core. The two-day plugin prep checklist: AI Client, Abilities API, block.json audit, PHP-only blocks.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Prepare for WordPress 7.0: the developer&#039;s audit list\" \/>\n<meta property=\"og:description\" content=\"WordPress 7.0 launches Wednesday May 20 with AI in Core. The two-day plugin prep checklist: AI Client, Abilities API, block.json audit, PHP-only blocks.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/\" \/>\n<meta property=\"og:site_name\" content=\"UnleashWP Dev Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-05-18T07:30:46+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-05-18T08:15:08+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-7-0.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"538\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Benjamin Zekavica\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Prepare for WordPress 7.0: the developer&#039;s audit list\" \/>\n<meta name=\"twitter:creator\" content=\"@unleash_wp\" \/>\n<meta name=\"twitter:site\" content=\"@unleash_wp\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Benjamin Zekavica\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wordpress-7-0-developer-prep\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wordpress-7-0-developer-prep\\\/\"},\"author\":{\"name\":\"Benjamin Zekavica\",\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/#\\\/schema\\\/person\\\/c56e609b726e8914db2466c341363f17\"},\"headline\":\"Prepare for WordPress 7.0: the developer&#8217;s audit list\",\"datePublished\":\"2026-05-18T07:30:46+00:00\",\"dateModified\":\"2026-05-18T08:15:08+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wordpress-7-0-developer-prep\\\/\"},\"wordCount\":2758,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wordpress-7-0-developer-prep\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/wordpress-7-0.png\",\"keywords\":[\"7.0\",\"Block Development\",\"Block Editor\",\"Gutenberg Font Manager\",\"WordPress 7.0\",\"WordPress font management\"],\"articleSection\":[\"AI\",\"Development\",\"Gutenberg\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wordpress-7-0-developer-prep\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wordpress-7-0-developer-prep\\\/\",\"url\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wordpress-7-0-developer-prep\\\/\",\"name\":\"Prepare for WordPress 7.0: the developer's audit list\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wordpress-7-0-developer-prep\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wordpress-7-0-developer-prep\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/wordpress-7-0.png\",\"datePublished\":\"2026-05-18T07:30:46+00:00\",\"dateModified\":\"2026-05-18T08:15:08+00:00\",\"description\":\"WordPress 7.0 launches Wednesday May 20 with AI in Core. The two-day plugin prep checklist: AI Client, Abilities API, block.json audit, PHP-only blocks.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wordpress-7-0-developer-prep\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wordpress-7-0-developer-prep\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wordpress-7-0-developer-prep\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/wordpress-7-0.png\",\"contentUrl\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/wordpress-7-0.png\",\"width\":1024,\"height\":538},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wordpress-7-0-developer-prep\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Prepare for WordPress 7.0: the developer&#8217;s audit list\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/\",\"name\":\"UnleashWP Dev Blog | Professional WordPress Development\",\"description\":\"Professional WordPress development insights\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/#organization\"},\"alternateName\":\"UnleashWP\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/#organization\",\"name\":\"UnleashWP\",\"alternateName\":\"UnleashWP\",\"url\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/favicon-neu.png\",\"contentUrl\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/favicon-neu.png\",\"width\":1200,\"height\":1200,\"caption\":\"UnleashWP\"},\"image\":{\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/unleash_wp\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/unleashwp\",\"https:\\\/\\\/www.youtube.com\\\/@unleashwp\",\"https:\\\/\\\/github.com\\\/unleash-wp\"],\"description\":\"UnleashWP is a platform focused on professional WordPress engineering. It provides in depth articles, practical guidance and technical resources for developers and teams building reliable WordPress projects.\",\"email\":\"office@unleash-wp.com\",\"vatID\":\"DE 358 256 337\",\"numberOfEmployees\":{\"@type\":\"QuantitativeValue\",\"minValue\":\"1\",\"maxValue\":\"10\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/#\\\/schema\\\/person\\\/c56e609b726e8914db2466c341363f17\",\"name\":\"Benjamin Zekavica\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/cropped-benjamin-zekavica-96x96.png\",\"url\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/cropped-benjamin-zekavica-96x96.png\",\"contentUrl\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/cropped-benjamin-zekavica-96x96.png\",\"caption\":\"Benjamin Zekavica\"},\"description\":\"I\u2019m Benjamin Zekavica \u2014 founder of Kreo Pulse and UnleashWP. With a background in media design, development, and content, I build digital products and brands that are clear, efficient, and built for the long term.\",\"sameAs\":[\"https:\\\/\\\/www.unleash-wp.com\\\/blog\"],\"url\":\"https:\\\/\\\/www.unleash-wp.com\\\/blog\\\/author\\\/benjamin\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Prepare for WordPress 7.0: the developer's audit list","description":"WordPress 7.0 launches Wednesday May 20 with AI in Core. The two-day plugin prep checklist: AI Client, Abilities API, block.json audit, PHP-only blocks.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/","og_locale":"en_US","og_type":"article","og_title":"Prepare for WordPress 7.0: the developer's audit list","og_description":"WordPress 7.0 launches Wednesday May 20 with AI in Core. The two-day plugin prep checklist: AI Client, Abilities API, block.json audit, PHP-only blocks.","og_url":"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/","og_site_name":"UnleashWP Dev Blog","article_published_time":"2026-05-18T07:30:46+00:00","article_modified_time":"2026-05-18T08:15:08+00:00","og_image":[{"width":1024,"height":538,"url":"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-7-0.png","type":"image\/png"}],"author":"Benjamin Zekavica","twitter_card":"summary_large_image","twitter_title":"Prepare for WordPress 7.0: the developer's audit list","twitter_creator":"@unleash_wp","twitter_site":"@unleash_wp","twitter_misc":{"Written by":"Benjamin Zekavica","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/#article","isPartOf":{"@id":"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/"},"author":{"name":"Benjamin Zekavica","@id":"https:\/\/www.unleash-wp.com\/blog\/#\/schema\/person\/c56e609b726e8914db2466c341363f17"},"headline":"Prepare for WordPress 7.0: the developer&#8217;s audit list","datePublished":"2026-05-18T07:30:46+00:00","dateModified":"2026-05-18T08:15:08+00:00","mainEntityOfPage":{"@id":"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/"},"wordCount":2758,"commentCount":0,"publisher":{"@id":"https:\/\/www.unleash-wp.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/#primaryimage"},"thumbnailUrl":"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-7-0.png","keywords":["7.0","Block Development","Block Editor","Gutenberg Font Manager","WordPress 7.0","WordPress font management"],"articleSection":["AI","Development","Gutenberg"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/","url":"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/","name":"Prepare for WordPress 7.0: the developer's audit list","isPartOf":{"@id":"https:\/\/www.unleash-wp.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/#primaryimage"},"image":{"@id":"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/#primaryimage"},"thumbnailUrl":"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-7-0.png","datePublished":"2026-05-18T07:30:46+00:00","dateModified":"2026-05-18T08:15:08+00:00","description":"WordPress 7.0 launches Wednesday May 20 with AI in Core. The two-day plugin prep checklist: AI Client, Abilities API, block.json audit, PHP-only blocks.","breadcrumb":{"@id":"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/#primaryimage","url":"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-7-0.png","contentUrl":"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/05\/wordpress-7-0.png","width":1024,"height":538},{"@type":"BreadcrumbList","@id":"https:\/\/www.unleash-wp.com\/blog\/wordpress-7-0-developer-prep\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.unleash-wp.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Prepare for WordPress 7.0: the developer&#8217;s audit list"}]},{"@type":"WebSite","@id":"https:\/\/www.unleash-wp.com\/blog\/#website","url":"https:\/\/www.unleash-wp.com\/blog\/","name":"UnleashWP Dev Blog | Professional WordPress Development","description":"Professional WordPress development insights","publisher":{"@id":"https:\/\/www.unleash-wp.com\/blog\/#organization"},"alternateName":"UnleashWP","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.unleash-wp.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.unleash-wp.com\/blog\/#organization","name":"UnleashWP","alternateName":"UnleashWP","url":"https:\/\/www.unleash-wp.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.unleash-wp.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2025\/12\/favicon-neu.png","contentUrl":"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2025\/12\/favicon-neu.png","width":1200,"height":1200,"caption":"UnleashWP"},"image":{"@id":"https:\/\/www.unleash-wp.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/unleash_wp","https:\/\/www.linkedin.com\/company\/unleashwp","https:\/\/www.youtube.com\/@unleashwp","https:\/\/github.com\/unleash-wp"],"description":"UnleashWP is a platform focused on professional WordPress engineering. It provides in depth articles, practical guidance and technical resources for developers and teams building reliable WordPress projects.","email":"office@unleash-wp.com","vatID":"DE 358 256 337","numberOfEmployees":{"@type":"QuantitativeValue","minValue":"1","maxValue":"10"}},{"@type":"Person","@id":"https:\/\/www.unleash-wp.com\/blog\/#\/schema\/person\/c56e609b726e8914db2466c341363f17","name":"Benjamin Zekavica","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/04\/cropped-benjamin-zekavica-96x96.png","url":"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/04\/cropped-benjamin-zekavica-96x96.png","contentUrl":"https:\/\/www.unleash-wp.com\/blog\/wp-content\/uploads\/2026\/04\/cropped-benjamin-zekavica-96x96.png","caption":"Benjamin Zekavica"},"description":"I\u2019m Benjamin Zekavica \u2014 founder of Kreo Pulse and UnleashWP. With a background in media design, development, and content, I build digital products and brands that are clear, efficient, and built for the long term.","sameAs":["https:\/\/www.unleash-wp.com\/blog"],"url":"https:\/\/www.unleash-wp.com\/blog\/author\/benjamin\/"}]}},"lang":"en","translations":{"en":1923},"pll_sync_post":[],"_links":{"self":[{"href":"https:\/\/www.unleash-wp.com\/blog\/wp-json\/wp\/v2\/posts\/1923","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.unleash-wp.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.unleash-wp.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.unleash-wp.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.unleash-wp.com\/blog\/wp-json\/wp\/v2\/comments?post=1923"}],"version-history":[{"count":26,"href":"https:\/\/www.unleash-wp.com\/blog\/wp-json\/wp\/v2\/posts\/1923\/revisions"}],"predecessor-version":[{"id":1955,"href":"https:\/\/www.unleash-wp.com\/blog\/wp-json\/wp\/v2\/posts\/1923\/revisions\/1955"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.unleash-wp.com\/blog\/wp-json\/wp\/v2\/media\/1943"}],"wp:attachment":[{"href":"https:\/\/www.unleash-wp.com\/blog\/wp-json\/wp\/v2\/media?parent=1923"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.unleash-wp.com\/blog\/wp-json\/wp\/v2\/categories?post=1923"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.unleash-wp.com\/blog\/wp-json\/wp\/v2\/tags?post=1923"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}