Skip to main content
Version: 3.x

CBX on WordPress — Platform Guide

Version
3.x
Updated
View markdown

Audience: integrators and developers running CBX on WordPress · Scope: how the WordPress edition is wired — the adapter plugin, routing/URLs, the /cbx-api/ endpoint, identity bridging, host CSS, WP-CLI, and migrations · Last reviewed: 2026-07-25

Store admins: the task-oriented manual is the Admin Guide — its CBX on WordPress article covers logging in, the menu, and the shortcode in plain language. This document is the technical counterpart.

TL;DR — Unlike on Magento 2, CBX on WordPress is the full application: it brings its own product lists, cart, checkout, orders and customer area. WordPress contributes hosting, identity and the admin shell; a thin adapter plugin (configbox.php and friends, in the plugin root) bridges WP's hooks to the shared, platform-agnostic app in wp-content/plugins/configbox/app/ (the component submodule). Storefront URLs are backed by hidden custom post types that CBX maintains itself; XHR calls use the pretty /cbx-api/<controller>/<task> endpoint; wp configbox … mirrors the Joomla console commands.


1. The two layers​

LayerFilesLives in
WordPress adapterconfigbox.php (hooks, routing, CPTs, shortcode, admin menu), cli.php (WP-CLI wrapper), templates/general.php (loader template), uninstall.phpThe plugin root — host-repo code, packaged with every WordPress release
CBX appapp/… — the shared component (identical code on Joomla/Magento 2)The component submodule

The app's own WordPress-specific bindings sit inside the component, behind the platform abstraction: app/external/kenedo/platforms/wordpress/ (the KenedoPlatformWordpress class), app/helpers/wordpress.php (ConfigboxWordpressHelper — the WP-post sync), and app/observers/Wordpress.php. Platform-specific behavior belongs there, not inline in shared code.

2. Boot​

  • configbox_init_kenedo() (adapter) runs on WordPress's init hook and calls initKenedo('com_configbox'). Kenedo auto-detects the wordpress platform.
  • Everything is gated by shouldInitCb(), which skips CBX entirely for requests that never need it (WP cron, heartbeat, Elementor AJAX, background queues). Respect the gate when adding hooks.
  • A request "is a CBX request" when it carries option=com_configbox — the whole adapter pipeline keys off that request param, exactly like Joomla's component routing.

3. Storefront routing and URLs​

WordPress has no component/frontname router, so the adapter builds one out of stock WP parts:

  • Hidden custom post types back the SEF URLs: cb_product_list, cb_product, cb_page (configurator pages) and cb_internal (cart, account). CBX maintains these rows itself: app/observers/Wordpress.php reacts to admin saves/copies and calls ConfigboxWordpressHelper::makePageFor…() to insert/update the matching post per language. Never edit these posts by hand — they are regenerated from CBX data.
  • getRoute() (platforms/wordpress/general.php) turns internal index.php?option=com_configbox&view=… URLs into the post permalinks, and translates the Kenedo params to WP conventions for everything else: view/controller → page, controller.task → action. In the admin area it targets admin.php, or admin-ajax.php for view-only/raw output.
  • The CPT slug (/cb_product/…) is stripped from permalinks (cb_remove_slug), and cb_parse_request widens the main query's post-type search so the slugless URLs resolve.
  • On CBX requests the adapter suppresses WP's 404 handling (pre_handle_404), clears the 404 query-var that parse_request sets for unresolvable paths, and vetoes canonical redirects — the request must reach CBX untouched.
  • Rendering goes through a loader template: template_include swaps in templates/general.php, which runs configbox_execute_controller_task() — the WP equivalent of Joomla's component dispatch (controller/task resolution, output buffering, observer-filtered output).

The /cbx-api/ endpoint​

The cb-api → cbx-api rename is complete on WordPress (adapter side landed 2026-08-27). /cb-api/… is gone with no alias and no redirect — it 404s, exactly as on Joomla.

configbox_cb_api_inject_params() keeps its old name on purpose. Its existence is the feature detection: getEndpointUrl() in platforms/wordpress/general.php tests function_exists('configbox_cb_api_inject_params') before emitting a pretty URL. The rename moved the URL segment and deliberately left that literal alone, so the adapter matches it. Renaming the function without changing the function_exists() call would fail detection and silently drop every frontend XHR back to the query-string URL — which is the designed fallback, not a failure, and is why a mismatched adapter/component pair degrades instead of breaking.

Frontend XHR/API calls use /cbx-api/<controller>/<task> — the same shape as Joomla's /cbx-api frontname route (see the Joomla SEF doc). There is no rewrite rule: configbox_cb_api_inject_params() (top of configbox.php) runs before anything else, recognizes the path, and injects the classic request params (option, controller, task, page, action, output_mode=view_only) into the superglobals — from there on the request is indistinguishable from a query-string URL. The app side (getEndpointUrl()) only emits /cbx-api/ URLs when that adapter function exists (feature detection), so an older adapter falls back to query-string endpoints. Admin XHRs always keep going through admin-ajax.php for the admin context.

The four surfaces the adapter routes​

The surfaces are siblings, each versioned on its own terms — the adapter mirrors the Joomla system plugin branch for branch, and each needs its own pattern because they do not share a shape:

pathroutes towhy it needs its own branch
/cbx-api/v1[/<path…>]apiv1 / dispatch, remainder in cb_api_patha resource path of any depth that may carry dots (openapi.json, schemas/read/product.json) — its segments name an entity and a record, not a controller and a task
/cbx-api/mcpapiv1 / mcpa single segment, so the generic two-segment form below cannot match it
/cbx-api/oauth/<task>oauth / <task>already fits the generic <controller>/<task> form — no special branch
/cbx-api/<controller>/<task>that controller and taskthe original XHR endpoint

cb_api_path keeps its name for the same reason the function does: it is a request parameter, owned app-side by ConfigboxApiv1Controller::PATH_VAR, not a URL segment. Send a name the controller does not read and getPath() returns empty, so every v1 call quietly answers the store index with a 200 — a wrong answer rather than a failure.

MCP is a sibling of the entity API rather than a child of it: /cbx-api/v1/mcp answers 404 (Unknown entity "mcp"), because MCP has its own task on the shared controller. It carries no URL version because this exact URL is the OAuth protected-resource identifier every issued token records as its audience.

The OAuth discovery documents need a web-server exemption​

RFC 8414 and RFC 9728 pin the metadata to fixed paths at the site root, not under /cbx-api/:

pathroutes to
/.well-known/oauth-authorization-serveroauth / asMetadata
/.well-known/oauth-protected-resource/cbx-api/mcpoauth / prMetadata

An OAuth client fetches these before it holds any token, so they are pre-auth by design. The catch on WordPress is not the adapter but the web server: the stock nginx recipe denies everything matching /\., which 403s these paths before PHP is reached. The dev site's nginx therefore carries an explicit location ^~ /.well-known/ exemption (^~ outranks a regex location whatever the order), and any production WordPress host serving the storefront OAuth flow needs the same — otherwise discovery 403s and no agent can authorize, while everything else looks healthy.

The token commands (wp configbox token-*) and the api-export artifacts refer to endpoints that actually answer on WordPress.

4. Embedding via shortcode​

[configbox view=… id=…] renders a CBX view inside any ordinary WP page: productlist (legacy alias productlisting), product, configuratorpage, cart, checkout, user. The shortcode boots Kenedo and returns the view HTML in place.

5. Identity bridging​

  • WP is the identity provider. The wp_login hook maps the WP user to the CBX user (ConfigboxUserHelper) and moves a guest cart onto the logged-in user; wp_logout logs the CB user out and resets the cart. Don't bypass these hooks.
  • CBX user rows are created lazily (on first need), not at WP login.
  • The CB "username" is the billing e-mail, which may differ from the WP login name — KenedoPlatformWordpress::authenticate() and login() therefore resolve the WP user by e-mail first, then by login name.

6. The admin area​

The CBX backend runs inside wp-admin: add_menu_page() registers the CBX menu (capability edit_pages), and every CB admin screen is dispatched through configbox_execute_controller_task(). Admin XHRs are registered as wp_ajax_<page>.<task> actions; for output_mode=view_only responses the adapter ends the request itself so admin-ajax's trailing 0 never reaches the client.

7. Host CSS adaptation​

WordPress themes — block themes especially — bleed into ConfigBox's markup, so the app ships per-host correction stylesheets and serves them itself: KenedoPlatformWordpress::getHostStyleSheetUrls() returns hosts/wordpress-admin.css in wp-admin and hosts/wordpress-site.css on the site, and KenedoView emits them with every ConfigBox view. The adapter plugin enqueues nothing — its old assets/css/adapter.css was folded into hosts/wordpress-site.css so all host adaptation lives in one platform-driven mechanism. Put new WordPress-only CSS corrections there, not in the plugin. Full reference: technical/com_configbox_host_stylesheets.md.

8. WP-CLI​

wp configbox … mirrors the Joomla console commands one-for-one (thin wrapper cli.php → shared ConfigboxCliHelper): cache-clear, charset (--status), migrate (--status, --clear-failed-flag), migrate-unblock, run-task, config-get/set/list, sysvar-get/set/list — plus custom, the dispatcher for site-specific commands from the customization layer (wp-content/plugins/configbox-customization/cli/commands.php — the layer's WordPress location; run wp configbox custom bare to list them — see customization/com_configbox_custom_cli_commands.md). Host gotchas:

  • The acting-user selector is --cb-user (WP-CLI reserves the global --user flag).
  • The migrate* and charset commands define CB_SUPPRESS_AUTO_UPDATES at plugin load so booting Kenedo does not auto-apply the very migrations they are meant to report on/control — and so that a read-only --status call stays read-only.
  • wp cache flush also purges the CBX caches (cache-generation stamp bump), matching bin/magento cache:flush behavior on Magento 2.

Full reference: technical/com_configbox_cli_commands.md.

9. Migrations on WordPress​

Update scripts (app/helpers/updates/) auto-apply on every request that boots Kenedo — including every wp CLI invocation (except the suppressed migrate*/charset/cache flush commands above). Logs land under the uploads dir: wp-content/uploads/cb-logs/configbox/configbox_upgrade_errors.log (not docroot/logs/ as on Joomla). WP-post-backed data changes are different: renaming/creating the hidden CPT rows is done in the adapter as an init-hook function guarded by a get_option() flag (see configbox_migrate_product_list_posts() for the pattern), not as an update script. Full reference: technical/com_configbox_migrations.md.

10. Multilingual​

The post-sync helper maintains one post per language, and CBX's own content strings live in its EAV configbox_strings store — WP .po/.mo files are not involved. There is no WPML integration: CBX handles its multilingual content itself.

11. Requirements & lifecycle​

Activation checks (and deactivates on failure): PHP 7.1–8.4 (8.0 excluded), WordPress 5.0–6.99 (the ceiling is enforced, so a WordPress 7.0 host refuses activation until it is raised), the ionCube loader (15+ on PHP 8.4, 14+ on 8.3, 13+ below), and the usual PHP extensions (gd, mbstring, mysqli, xml, zip, openssl, …). Uninstall (delete via the Plugins screen) runs uninstall.php, which drops all configbox_*/cbcheckout_* tables (removing referencing foreign-key constraints first); the hidden CPT rows are not cleaned up.