This is part 3 of a series. [Part 1] made the case for splitting WordPress into Classic and Next. [Part 2] talked about the kernel underneath. Now I want to talk about what’s happening above the kernel, in the admin and the editor.
I want to say something up front because it shapes the entire post. I started an earlier draft of this part with an argument that Next should move away from the React-first admin shell toward a server-rendered Hotwire or Livewire model. I spent a few hours with that draft and then threw it out, because it was wrong, and it was wrong in a way I need to name out loud.
In 2015, Matt told the ecosystem to learn JavaScript deeply. A lot of people did. PHP developers spent the better part of a decade retraining themselves into React developers, sometimes painfully, because the project asked them to. Telling that same community in 2026 “actually, we’re going back to server-rendered HTML with a new directive layer” is the kind of whiplash that ends careers and ends loyalty. The technical argument for Hotwire-style admins is real. The community argument against asking people to pivot their stack twice in a decade is stronger. React won. I’m going to stop trying to relitigate that.
So the frame for this whole post: Next’s admin is Classic’s admin. Same React shell, same screens, same navigation. A content editor logging into Next should not be able to tell they’re on Next. The work Next does in the admin is underneath the surface, making what’s already there faster, more accessible, easier to extend, and easier to ship. That’s a less dramatic pitch than I was originally going to make, and I think it’s the right one.
What Gutenberg earned
Let me say this directly. The block model is the single most important thing this project has built since custom post types. A serializable content format with stable HTML comment delimiters that round-trips through a tree-based editor and renders deterministically on the front end is a real innovation. Block themes and theme.json finally give us a design-token system that isn’t a race between page builders. Block Bindings (6.5) fix half of ACF’s reason for existing.
Playground (PHP compiled to WebAssembly running WordPress in a browser tab) is, no exaggeration, the most important developer-experience win in the last decade of CMS work, and it unblocks an enormous amount of what I’m proposing across this series. Data Liberation is exactly the right direction for import and export. The Interactivity API is the first JavaScript architecture choice core has made that actually looks at what Astro and Qwik figured out and adopts it instead of reinventing.
Credit where credit is due. I really mean that. None of what comes next would be worth saying if the block model hadn’t proven the core idea works.
Now, the harder conversation.
Performance, accessibility, and the toolchain that didn’t keep up
The editor is slow on low-end hardware in a way that doesn’t show up in your demos or mine. A 2018 Chromebook opening a 40-block post in the block editor is not a smooth experience, and the long tail of WordPress editors is using a 2018 Chromebook. The @wordpress/* package surface is 80+ packages, of which any given plugin transitively depends on 30. First-paint to editor-interactive on a cold load on mid-tier hardware is well north of what it needs to be, and every block type added pushes it further. Gutenberg’s reconciliation model (re-render the block list on any change) hits a wall past about 200 blocks, which is not a theoretical limit for news sites.
I want to be careful about how I frame this, because the critique isn’t “React was the wrong choice.” React is the choice, it’s the one the ecosystem invested in, and the investment is not being undone. The critique is that the tooling and performance work underneath React hasn’t kept pace with what the editor is asking it to do. Those are two very different problems, and one of them is actually tractable in a reasonable amount of time.
The accessibility story is the one that still hurts me to talk about. Rian Rietveld resigned as accessibility lead in 2017 over the React-first direction, and the team’s been playing catch-up since. WPCampus’s independent audit surfaced dozens of WCAG failures. The team closed many of them, but the block UI’s core interaction model (the block toolbar, the inspector sidebar, the slash menu) remains harder to navigate by keyboard and screen reader than the classic editor ever was. For a publishing tool of this size, it’s also not acceptable, and Next should treat it as a ship-blocker rather than a backlog item.
The React-only extension surface is the deepest architectural tension, and it’s one I want to be honest about rather than pretend I can design away. register_block_type has a render_callback for PHP, but dynamic blocks are second-class. No edit experience in the editor without JavaScript. No inspector controls without JavaScript. A PHP developer who wants to ship a block has to learn React plus @wordpress/scripts plus a build toolchain. For the 70% of the plugin economy that is freelance PHP developers and agencies, that’s a real exclusion.
I don’t have a clever fix for that. I want to name it as a cost rather than pretend it’s solved. The honest answer is that block authoring on Next requires JavaScript, the same way it does on Classic, and the best thing Next can do is make the JavaScript part as painless as possible. Better tooling, better types, better docs, better AI-assisted scaffolding for people who know PHP and would rather not hand-write JSX. That’s a real commitment, but it’s not “PHP developers can author blocks without JavaScript.”
The toolchain
@wordpress/scripts is webpack 5. A cold npm run build on a modest block plugin is 8 to 15 seconds. Hot module replacement in start is 1 to 2 seconds. The React package surface pulls in enormous type footprints. Vite does the equivalent cold build in under a second. ESBuild is ten times faster than webpack on the same inputs. Turbopack is faster still. There is no technical reason block plugins ship with webpack in 2026.
Next ships a Vite-based @wordpress/scripts replacement with a TypeScript-first template, hot module replacement in the editor via a websocket bridge, and a block.json that’s unchanged. The declarative manifest is good. The toolchain that reads it is what’s tired. Keep the @wordpress/* packages. Reshape them into proper ECMAScript modules with proper types, drop the “built UMD for IE11” ballast that a significant portion of every bundle still carries.
And I know that a faster build tool doesn’t fix the fact that block authoring requires JavaScript. I already flagged that above. Vite makes the JavaScript part of block authoring measurably less miserable, which matters, but it isn’t a backdoor to letting PHP developers skip the JavaScript. Two separate problems, only one of which I’m claiming the toolchain actually solves.
Media library
The media library is the single most-untouched part of the admin. The attachment model (posts of type attachment with meta for sizes, EXIF, alt text) is a 2012 design. It doesn’t have focal points as first-class metadata, variants as a real concept (sizes are ad-hoc post meta), a responsive image pipeline beyond wp_get_attachment_image and srcset generation from preset sizes, CDN-native storage (Offload Media and friends are plugins that monkey-patch), AVIF/WebP transcoding pipelines, per-image derivatives-on-demand, asset collections or folders, usage tracking, or approval workflows.
Craft’s Assets model. Statamic’s Assets. Drupal’s Media module (with its separation between media entities and file fields). Sanity’s image pipeline with on-demand transforms via URL parameters. Any of these is a better answer than what we have.
This is one I bump into constantly working with clients across my career. Anything past a basic blog, the media library becomes a real friction point, and we end up gluing on third-party services or writing custom code to work around it.
Next ships a first-class asset service with separation of Asset (logical) from File (binary) from Variant (derivative) as proper entities, an adapter pattern for storage (local, S3, Cloudflare R2, VIP Files), on-the-fly derivatives via signed URL cached at the edge with AVIF/WebP/JPEG-XL negotiation by Accept, focal points and cropping stored as structured data, a real folder/collection primitive, and usage tracking (what posts reference this asset) as a real index rather than a LIKE '%wp-content%' query.
Now, the thing I want to acknowledge honestly before the host engineers reading this close the tab. On-the-fly AVIF or JPEG-XL encoding is expensive. It needs libvips or a modern ImageMagick build, which cheap shared hosts have historically been spotty about supporting. If Next’s media pipeline only works on hosts with the right binaries available, that’s a real economic barrier and I want to point it out rather than pretend it isn’t there.
I think the best way forward is that Next is explicitly not for the $5/month shared hosting tier. That tier is Classic, which keeps the 2012 attachment model, and that’s a deliberate choice this whole series rests on. Next assumes managed hosting, a CDN, or delegation to an image service (Cloudflare Images, Imgix, Bunny Optimizer, VIP’s image pipeline) as the baseline. The on-demand design goal stays. The way it degrades is via adapter: if libvips is present, do derivatives in-process; if not, delegate to whatever image service is configured; if neither, fall back to pre-generated derivatives at upload time (which is how Classic already works). The design goal doesn’t change. The honest answer to “who pays for the compute” is “the tier of user Next is aimed at, on the infrastructure that tier already pays for.” Which is the same answer every other modern CMS gives. We should just say it out loud.
theme.json and the cascade
The good: a single source of truth for design tokens, cascading core then theme then user, serializable, versionable, finally giving us a vocabulary for “what colors does this site use” that isn’t “grep the CSS.” This is the right direction.
The bad: JSON is a bad language for styling. The cascade rules (what wins between theme.json typography, a block’s supports, a block’s user-applied style, a global style, and the CSS from the theme’s actual stylesheets) are not obvious to anyone, including the core team. Plugin interop is brittle because plugins inject CSS without theme.json awareness.
Next doesn’t replace theme.json. It formalizes it as the design-token layer, emits CSS custom properties as its primary output, and lets themes write real CSS that consumes those properties. Tailwind-style utility classes, vanilla CSS with @property, CSS nesting, all welcome. theme.json is the data layer, not the styling layer. This matches where the CSS platform actually went.
Content modeling: fields, block bindings, and the ACF question
Here’s a question I’ve been chewing on for a while: should WordPress have a first-party content modeling API that covers what ACF, Meta Box, CMB2, and Pods have covered for over a decade? In my mind, the answer is obviously yes. Block Bindings (6.5) was the right first step. It connects block attributes to dynamic sources, which is the rendering half of the problem. The authoring half (define a repeater field, a relationship, a flexible content area, a group) is still plugin territory.
Next ships Schemas, but I want to talk about how I want this to ship because the shape of the answer matters a lot more than the feature itself.
The reason ACF dominated the content-modeling market is not the field types. It’s the GUI. A marketer, a designer, or a junior freelancer can click together a complex relational schema without writing a line of PHP. That is a genuine superpower, and it’s one of the last things protecting WordPress from losing the site-builder persona to Webflow. If Next ships a content-modeling API that only developers can use, we’ve handed Webflow a gift we didn’t have to.
So Schemas ships as two equal-peer surfaces on top of a single underlying data contract:
Schema as a GUI. An admin screen, inside Next’s content-modeling section, that lets a non-developer define a post type, add fields of various types, configure validation, set up relationships, and arrange the authoring UI. Click-and-drag. Add field. Pick type. Save. Ships as a first-class feature of the admin, same tier as Appearance or Users, not buried in Tools.
Schema as code. A declarative PHP API that produces the same underlying artifact. Configuration-as-code for teams that want content models in version control, reviewable in pull requests, and deployable through CI.
return Schema::postType('review') ->label('Reviews') ->fields([ Field::text('headline')->required(), Field::richtext('body'), Field::number('rating')->min(0)->max(5)->step(0.5), Field::relationship('product')->to('product')->cardinality(1), Field::repeater('pros')->of(Field::text('pro')), Field::image('hero')->focal()->alt(required: true), ]) ->supports([Supports::Revisions, Supports::Author, Supports::Comments]);
Both surfaces read and write the same schema objects. A schema defined in the GUI can be exported to code. A schema defined in code can be edited in the GUI (with obvious caveats about what that does to the source-of-truth question, which Payload and Sanity have both had to think through and have reasonable answers for). Block Bindings consumes whichever produced it. The authoring UI is generated from the schema regardless of how it was defined.
This is how Payload and Sanity actually ship in practice, and it’s what ACF should have been if it had core-level support the whole time.
The technical direction (fields belong in core) is still correct. The product direction (both GUI and code, as equals) is what actually protects WordPress’s place as the CMS a non-developer can use.
Composition primitives: the patterns mess
This vocabulary is a mess and users pay for it. A reusable block is a wp_block post. A synced pattern is a reusable block rebranded. A pattern is a PHP/HTML snippet registered with register_block_pattern. A template part is a wp_template_part post in a block theme. A block variation is a JS object.
Pick two: patterns (stateless composition, like CSS utilities) and template parts (concrete site regions). Fold reusable and synced blocks into patterns with an optional “sync” flag at insert time. Document block variations as a developer-only primitive.
Where this leaves us
The headline I’d put on this whole section is: Gutenberg got the model right, and the scaffolding around it is what needs the attention.
The block model is good. The toolchain underneath it needs a generation refresh. The admin shell keeps its React investment. The accessibility work has to graduate from backlog to ship-blocker. The media library needs to catch up to 2026, and we need to be honest about which tier of hosting it’s for. theme.json needs to know its job. Fields need to be in core, with both a GUI and a code API as equal peers.
None of this is a rejection of where Gutenberg has been heading. It’s a request to take what’s worked and rebuild the surrounding scaffolding so the next decade of editor work isn’t paid for by a 2018 Chromebook user trying to publish a news article.
Next post: performance and security. The two areas where every host already knows what needs to happen, and where the gap between what core ships and what production WordPress actually requires is the most embarrassing. It’s also where I get specific on the cold-boot target I flagged in part 2, and where the wp_postmeta conversation I flagged in part 2 actually happens.
More soon.
AI Disclosure: Featured image generated by Gemini, and Claude assisted with the refinement of my choices, arguments, and editing of this post and series.

Leave a comment