Woo Template Integration Contract
Woo components are not enough by themselves. A starter also has to own the Woo routes that WordPress and WooCommerce resolve: product archive, single product, cart, checkout, order confirmation, and any product taxonomy archives the starter exposes.
This page is the public contract for that ownership. It translates the repo-backed demo flow into starter-safe rules.
Required Route Ownership
| Route surface | Starter-owned content | Required slug or option | Notes |
|---|---|---|---|
| Product archive | Active-theme block template | archive-product | Use Template::new() and render a product loop. The default Woo shop route is usually /shop/. |
| Single product | Active-theme block template | single-product | Use Template::new() and current-product dynamic data such as {this.id} and {this.omewoo.*}. |
| Cart | Page content plus optional page template | woocommerce_cart_page_id, optionally page-cart | Assign a real cart page. A page-cart template should pass through page content or render the Woo cart block. |
| Checkout | Page content plus optional page template | woocommerce_checkout_page_id, optionally page-checkout | Assign a real checkout page. A page-checkout template should pass through page content or render the Woo checkout block. |
| Order confirmation | Active-theme block template or Woo-owned page content | order-confirmation and order-received flow | Keep Woo's order received lifecycle intact. Render Woo core order confirmation output for completed orders. |
| Product taxonomies | Active-theme taxonomy templates when customized | taxonomy-product_cat, taxonomy-product_tag | Use product-loop-aware markup. Do not let taxonomy archives fall back to a non-product post layout if the starter presents them as store routes. |
Source-Backed Builder Shape
The local demo store builder proves the minimum code-owned content shape:
Template::new()
->slug( 'archive-product' )
->title( 'Product Archive' )
->overwrite()
->blocks_markup( product_archive_blocks() )
->register();
Template::new()
->slug( 'single-product' )
->title( 'Single Product' )
->overwrite()
->blocks_markup( single_product_blocks() )
->register();
$cart_page_id = Page::new()
->slug( 'cart' )
->title( 'Cart' )
->overwrite()
->blocks_markup( cart_page_blocks() )
->register();
$checkout_page_id = Page::new()
->slug( 'checkout' )
->title( 'Checkout' )
->overwrite()
->blocks_markup( checkout_page_blocks() )
->register();
if ( is_int( $cart_page_id ) ) {
update_option( 'woocommerce_cart_page_id', $cart_page_id, false );
}
if ( is_int( $checkout_page_id ) ) {
update_option( 'woocommerce_checkout_page_id', $checkout_page_id, false );
}
The demo uses Page::new() for cart and checkout because those are Woo page
settings. A starter can additionally own page-cart and page-checkout
templates, but those templates must not hide the assigned page content.
Product Archive And Single Product
Use Template::new() for archive-product and single-product so the active
theme owns those Woo block templates.
Archive templates should render a product loop. Inside each loop item, use
{item.*} and {item.omewoo.*} values. Single product templates should use
{this.*} and {this.omewoo.*} values from the current product.
Read Product Archive Flow and Single Product Flow for component composition.
Cart And Checkout Page Assignment
Woo still needs assigned pages. The starter must create or update page content and write the Woo options:
| Option | Meaning |
|---|---|
woocommerce_cart_page_id | Page Woo uses for /cart/, cart links, and cart redirects. |
woocommerce_checkout_page_id | Page Woo uses for /checkout/, checkout redirects, and payment return fallbacks. |
The page slug can be cart and checkout for public starter sites. The demo
uses ome-demo-cart and ome-demo-checkout to keep fixture pages isolated.
If the starter also registers block templates for page-cart or
page-checkout, those templates should preserve page content:
Template::new()
->slug( 'page-cart' )
->title( 'Cart Page Template' )
->overwrite()
->blocks_markup( '<!-- wp:post-content /-->' )
->register();
Template::new()
->slug( 'page-checkout' )
->title( 'Checkout Page Template' )
->overwrite()
->blocks_markup( '<!-- wp:post-content /-->' )
->register();
If your starter has a helper such as CoreBlock::post_content(), use that for
the same pass-through behavior. If it does not, the raw core block markup is:
<!-- wp:post-content /-->.
Woo Core Block Fallbacks
When a starter is not composing the cart or checkout with OhMyEtch Woo components, use Woo core blocks inside the assigned page content:
$cart_blocks = '<!-- wp:woocommerce/cart /-->';
$checkout_blocks = '<!-- wp:woocommerce/checkout /-->';
$order_confirmation_blocks = '<!-- wp:woocommerce/order-confirmation /-->';
Do not mix a full OhMyEtch checkout form and the Woo checkout block in the same visible checkout surface. Pick one owner for the checkout UI.
Order Confirmation
The checkout Store API success path redirects into Woo's order received flow.
The route can include order-received, and payment gateways may also use
Woo-owned return URLs.
If the starter owns order-confirmation, render the Woo core order confirmation
block or pass through Woo-managed page content:
Template::new()
->slug( 'order-confirmation' )
->title( 'Order Confirmation' )
->overwrite()
->blocks_markup( '<!-- wp:woocommerce/order-confirmation /-->' )
->register();
Do not replace this route with a generic static thank-you page. The customer must land on a Woo-aware surface that can read the completed order context.
Taxonomy Archive Considerations
Product taxonomy routes are store routes too. If the starter links to product
categories or tags, add product-aware taxonomy templates for product_cat and
product_tag.
The normal WordPress block template slugs are:
| Taxonomy | Template slug |
|---|---|
| Product categories | taxonomy-product_cat |
| Product tags | taxonomy-product_tag |
The template content should reuse the product archive loop shape rather than a
generic post archive card. It should render product purchase components only
inside a product loop context where {item.omewoo.*} is available.
Starter Skill Smoke Recipe
A starter-building skill or generated recipe should explicitly mention every required ownership slug before it claims Woo route integration is complete:
Required starter route slugs:
- archive-product
- single-product
- page-cart
- page-checkout
- order-confirmation
Required assigned Woo page options:
- woocommerce_cart_page_id
- woocommerce_checkout_page_id
The smoke should fail if any slug is missing from the generated starter plan or if cart and checkout pages are not assigned to Woo options.
Route Smoke Checklist
After building a starter, run browser smoke checks against all customer-facing routes:
| Route | What to verify |
|---|---|
/shop/ | Product archive renders product cards and add-to-cart controls. |
/product/.../ | Single product renders current product data, variation selectors when needed, and purchase controls. |
/cart/ | Cart page is the page stored in woocommerce_cart_page_id; cart rows and empty state render. |
/checkout/ | Checkout page is the page stored in woocommerce_checkout_page_id; checkout fields, payment selector, notices, order summary, and place-order flow render. |
order-received | A completed checkout reaches a Woo order received or order confirmation surface with order-aware content. |
For the repo demo flow, WooDemoStoreBuilder returns preview URLs for archive,
single, cart, and checkout. A production starter should expose equivalent route
checks through its own smoke workflow.