WordPress runs on PHP and server-rendered HTML. 41% of the web still runs on it. But eventually every theme or plugin needs a bit of real interactivity: a live product filter, a search box, a dashboard widget on the admin side. The usual advice is "use React." For WordPress specifically, there is a better answer: useWildflowerJS. WildflowerJS is what the platform actually calls for instead: no build pipeline to bolt onto a PHP project, and no fight with the jQuery that's already on every WordPress page.
WordPress doesn't have a build pipeline. React needs one.
Open a typical theme or plugin and there's no webpack.config.js, no vite.config.js, no build step in the deploy process at all. PHP renders HTML, wp_enqueue_script() loads a JS file, done. That's the mental model since WordPress existed.
React doesn't run in a browser as written. JSX has to be compiled. WordPress does have @wordpress/scripts, a wrapper around webpack, but it exists to build Gutenberg blocks for the block editor, not to add a filter widget to your theme's product page. Reaching for it there means installing Node tooling into a PHP project, adding a build step to your deploy process, and now maintaining a node_modules folder for even a dropdown filter.
If you're shipping a plugin through the WordPress.org repository, this gets worse. You can't tell your users to run npm install. You have to compile the bundle yourself and ship the compiled output, which means every change to that one filter widget is a rebuild-and-re-ship cycle for the whole plugin.
Every WordPress page already has jQuery on it. WildflowerJS is tested against it. React isn't built to coexist with it.
WordPress core still ships jQuery, and always will: admin screens depend on it, and so does a large share of the plugin ecosystem (sliders, lightboxes, date pickers, WooCommerce's own cart widgets). Any framework you add to a WordPress page is landing in a room jQuery already occupies.
React's virtual DOM assumes it owns the nodes it renders. Mix in a jQuery plugin that reaches into the same DOM tree from outside React's render cycle, and you get the class of bug every "using jQuery with React" thread on Stack Overflow is about: React re-renders, your jQuery plugin's DOM changes vanish, or React throws trying to reconcile a tree jQuery already mutated.
WildflowerJS has no virtual DOM, so there's no ownership conflict to have in the first place. v1.1 shipped 34 tests specifically covering coexistence with jQuery 4.0.0 (what WordPress core ships today) and jQuery 3.7.1 (still common on older installs), covering event-handler interaction, DOM mutation overlap, and AJAX flows. If your JavaScript is going to share a page with jQuery, and on WordPress it always is, that's a tested guarantee, not a hope.
What this actually looks like in a theme or plugin
Enqueue it the exact way you enqueue every other script in WordPress:
function theme_load_wildflower() {
wp_enqueue_script(
'wildflowerjs',
'https://cdn.jsdelivr.net/npm/wildflowerjs@1/dist/wildflower.min.js',
[],
'1.3.0',
true
);
}
add_action( 'wp_enqueue_scripts', 'theme_load_wildflower' );
Then in the template PHP already rendering your product loop or search results, add data-* attributes to the markup you're already outputting, and drop the component definition in an inline script, with PHP handing off the initial data:
<div data-component="product-filter">
<input data-model="query" placeholder="Search products…">
<div class="products" data-list="visible" data-key="id">
<template>
<div class="product-card">
<span data-bind="name"></span>
<span data-bind="price"></span>
</div>
</template>
</div>
</div>
<script>
wildflower.component('product-filter', {
state: {
query: '',
products: <?php echo wp_json_encode( $products ); ?>
},
computed: {
visible() {
return this.products.filter(p =>
p.name.toLowerCase().includes(this.query.toLowerCase())
);
}
}
});
</script>
PHP still owns the initial render, the way it always has. WildflowerJS just attaches behavior to markup PHP already output, and hands the filtering to the browser instead of a page reload. There's no separate rendering authority fighting PHP for control of the page, because there's no virtual DOM claiming it.
WordPress cares about page speed more than most platforms
WordPress sites skew SEO-driven. Blogs, marketing sites, WooCommerce storefronts, are all scored on Core Web Vitals, all competing on page speed as a ranking factor. Shipping a full SPA framework's runtime to add one interactive widget works against the platform's own incentives.
The standard WildflowerJS build, plugins and transitions included, is 74.8 KB transferred (Brotli-compressed). The nano tier, for pages that just need reactive state and binding, is 46.2 KB; the lite tier adds lists and entity pools at 71.5 KB. Even the top tier, with routing and server-side rendering both included, is 85.1 KB. That's the entire framework at every size, not just the piece that renders your widget. There is no separate state library, no router bolted on top, and nothing else eating into your Core Web Vitals budget.
WildflowerJS fits WordPress better than any framework that assumes a build pipeline and a DOM it owns exclusively. It enqueues the way WordPress scripts have always enqueued. It's tested against the exact jQuery versions WordPress ships. And it costs less, in kilobytes and in tooling, than what it replaces. That's not a close call.
PHP already renders the page. jQuery holds it together, and WildflowerJS brings reactivity. Enqueue it as shown above, ship the widget, done.
Find out more at wildflowerjs.com, or see a demo of jQuery integration with WildflowerJS.