13. Storefront: catalogue pages
You will: send the shop, categories, tags, products and home page through Flx, looking and behaving like native Storefront.
Result: fidelity 99.9% desktop, 99.7% phone across 11 pages, with a gate at 95% on every page.
Let WooCommerce print the middle
Twenty Twenty-Five's renderer draws everything from data. That doesn't suit a store: WooCommerce's templates run dozens of hooks, and every store plugin relies on them. Rebuilding them from data would break those plugins and never catch up.
So the plugin runs the middle of WooCommerce's own page template, everything between the theme's header and footer, and sends the result as main_html:
ob_start();
do_action( 'woocommerce_before_main_content' );
while ( have_posts() ) {
the_post();
wc_get_template_part( 'content', 'single-product' );
}
do_action( 'woocommerce_after_main_content' );
do_action( 'woocommerce_sidebar' );
$html = ob_get_clean();
The renderer draws Storefront's header and footer around it. Menus, widgets and Storefront's hook output arrive as WordPress printed them.
Copying a template needs a guard
That code is a copy of single-product.php. If a WooCommerce update or a theme override changes the file, the copy is silently wrong. So the plugin checks each template the route uses: it must be WooCommerce's own file, with no theme override, at a @version that has been reviewed. Anything else goes to native.
const SUPPORTED_TEMPLATES = array(
'single-product.php' => array( '1.6.4' ),
'content-single-product.php' => array( '3.6.0' ),
'archive-product.php' => array( '8.6.0' ),
'content-product.php' => array( '9.4.0' ),
);
A store with a customised content-product.php therefore stays native until someone reviews it. That is the most likely thing you'll meet on a real store.
A classic theme keeps its assets
The Twenty Twenty-Five renderer provides its own CSS, so the plugin filters what WordPress prints in the head. A classic theme is the opposite: the page has no CSS without it, and the markup in the footer matters too. WooCommerce's variation template and the gallery's lightbox are markup in wp_footer. So for a classic theme, head and footer output go through as printed. Above a size cap, or with a hook that throws, the page goes native rather than unstyled.
What went wrong, and how CI found it
These are worth knowing, because each looks like something else:
- First fidelity run: 96.8% / 90.9%, for the wrong reason. The secret header that asks for the native page was sent on every request, and that broke Google Fonts' CORS, so the native screenshot fell back to Arial. Send it only to your own origin.
- Menus. Storefront's CSS depends on classes from WordPress's walker. Send the menu as WordPress prints it, not as items.
- Late styles. WordPress 6.9 moves block styles printed late into the head, in a template output buffer that Flx pages never reached. Start that buffer on Flx pages too.
?m=1for measuring.?m=is WordPress's date filter. Use another query argument for the native comparison.
After a renderer failure, the page must still work
This one reached the live site. The head and footer capture prints each script's settings once, and WooCommerce records that in a private list. The queue was restored after the capture, but not that list. So after a renderer failure, the native page loaded WooCommerce's scripts without their settings: no AJAX add to cart, no variations. Nothing looked wrong until the renderer was down.
Two lessons: restore everything a capture touches, and test the fallback in a browser, not just its status code. Our CI stops the renderer and checks WooCommerce's settings are on the page.
Check it
- Fidelity on every page type, with the gate per page.
- Functional checks in a real browser: AJAX add to cart, mini-cart, variations, gallery.
- Headers:
private, no-store, and noSet-Cookie. In Playwright useallHeaders():headers()leaves out cookie headers, so a check with it can't fail. - A probe cookie, read by a hook, must not reach the page. Control: the native page does show it.
Next: 14. Shoppers with a cart.
Published from rickey29/twenty-twenty-five at commit 837705d · Flx Modernize 1.11.0 · Flx Render 1.11.0