BuddyX

Assets, Enqueue, and Build

Free theme

How BuddyX registers, conditionally loads, and builds its CSS and JavaScript, and how to add your own child-theme assets after the parent.


BuddyX drives every front-end stylesheet and script through two manifest classes rather than scattered wp_enqueue_*() calls. Per the theme audit manifest, BuddyX can emit 37 CSS handles and 21 JS handles, most of them loaded conditionally. This page covers where the manifests live, how handles are named, when each loads, where source vs. built assets sit, the build commands, and the correct way to enqueue after BuddyX.

Requires PHP 8.0+.


The two manifest classes

Concern Class file Core array Filter
Stylesheets inc/Styles/Component.php $css_files (in get_css_files()) buddyx_css_files
Scripts inc/Scripts/Component.php $js_files (in get_js_files()) buddyx_js_files

Both hook wp_enqueue_scripts. Styles\Component additionally hooks wp_head (preload emission), after_setup_theme (editor styles), and style_loader_tag (critical-CSS preload). Handle names are stable across releases, so any wp_dequeue_*() you write keeps working after an update.


CSS handle structure

Core manifest handles

These nine are declared in get_css_files() and are the filterable base set. global handles enqueue on every request; the rest are registered and emitted only when their preload_callback returns true (or unconditionally when preloading is disabled).

Handle File (assets/css/) Loads when
buddyx-global global.min.css Always (global)
buddyx-tokens-applied bx-tokens-applied.css Always (global), depends on buddyx-global
buddyx-site-loader loaders.min.css Always (global)
buddyx-load-fontawesome fontawesome.min.css Always (global)
buddyx-comments comments.min.css Singular view with comments open or present
buddyx-content content.min.css Registered only (opt-in via print_styles())
buddyx-sidebar sidebar.min.css On demand
buddyx-widgets widgets.min.css On demand
buddyx-front-page front-page.min.css When the active template is front-page.php

Conditional integration handles

The remainder of the 37 are enqueued directly inside action_enqueue_styles() (and three integration methods that run at priority 99), each guarded by a class_exists() / function_exists() / defined() check. A representative set:

Handle Guard
buddyx-buddypress BuddyPress active and Youzify not active
buddyx-bbpress is_bbpress() / BuddyBoss Platform
buddyx-platform BuddyBoss Platform
buddyx-woocommerce WooCommerce
buddyx-wc-vendor WC_Vendors
multivendorx MVX
buddyx-learnpress / buddyx-lifterlms / buddyx-learndash LearnPress / LifterLMS / SFWD_LMS
buddyx-eventscalendar Tribe__Events__Main (priority 99)
buddyx-dokan WeDevs_Dokan (priority 99)
buddyx-surecart / buddyx-fluentcart SURECART_PLUGIN_FILE / FLUENTCART_PLUGIN_FILE_PATH
buddyx-better-messages / buddyx-gamipress / buddyx-rtmedia / buddyx-bp-verified-member Respective plugin class present
buddyx-slick Always (carousel library)
buddyx-dark-mode Always (dark token overrides)
buddyx-rtl is_rtl()
buddyx-amp AMP endpoint

Non-critical stylesheets (buddyx-slick, buddyx-eventscalendar, buddyx-dokan, buddyx-youzify, buddyx-wpjobmanager, multivendorx) are rewritten by add_preload_for_critical_css() on style_loader_tag to load with media="print" onload="this.media='all'" plus a <noscript> fallback, so they never block first paint.

CSS manifest entry shape

Each core entry is normalized to these keys:

'buddyx-front-page' => array(
    'file'             => 'front-page.min.css', // relative to assets/css/
    'global'           => false,                // true = enqueue on every request
    'preload_callback' => function () {         // decides per-request when global is false
        global $template;
        return $template && 'front-page.php' === basename( $template );
    },
    'media'            => 'all',
    'deps'             => array( 'buddyx-global' ),
),
Key Meaning
file Path under assets/css/. Manifest references the built .min.css
global true enqueues immediately; false registers for conditional/on-demand use
preload_callback Callable deciding emission when global is false (e.g. is_singular(), class_exists())
media Media attribute, default all
deps Other handles loaded first

Versions are computed per file via buddyx()->get_asset_version() for cache busting, so you never hand-maintain a version string. Preloading itself can be toggled with the buddyx_preloading_styles_enabled filter (it is disabled automatically under AMP).


JS handle structure

get_js_files() declares seven base handles, all global, footer-loaded, and dependent on jquery:

Handle File (assets/js/) Loading Notes
buddyx-superfish superfish.min.js defer Menu behaviour
buddyx-isotope-pkgd isotope.pkgd.min.js defer Masonry/grid layout
buddyx-fitvids fitvids.min.js defer Responsive video
buddyx-sticky-kit sticky-kit.min.js defer Sticky sidebar
buddyx-jquery-cookie jquery-cookie.min.js defer Cookie helper
buddyx-slick slick.min.js defer Carousels
buddyx-custom custom.min.js normal Main theme JS; localizes buddyx_ajax (nonce, ajaxurl)

Conditional handles are appended when their integration is active:

Handle Guard
buddyx-gamipress GamiPress
buddyx-buddypress BuddyPress
buddyx-learndash SFWD_LMS

loading maps to wp_script_add_data() (async or defer); footer controls in-footer output; localize feeds wp_localize_script(). The buddyx_js_files filter lets you disable, replace, or add entries the same way as CSS.


Source vs. built assets

Source files are authored under src/; the build tools compile them to minified siblings one level up, which is what the manifests enqueue.

Type Source Built output Compiler
CSS assets/css/src/*.css assets/css/*.min.css lightningcss
JS assets/js/src/*.{js,tsx} assets/js/*.min.js esbuild
JS vendor assets/js/src/**/*.cjs copied to assets/js/*.min.js copied as-is (UMD bundles)
Editor CSS assets/css/src/… assets/css/editor/editor-styles.min.css lightningcss (added via add_editor_style())

The CSS build resolves @import statements manually and prepends the theme's @custom-media breakpoint definitions (--narrow-menu-query, --wide-menu-query, --content-query, --sidebar-query) before minifying, so partials such as _header.css and _typography.css collapse into single output files.

Edit the src/ files, never the .min output. A rebuild overwrites anything you change in the built files.


Build commands

Defined in package.json (scripts). Node >=20.13.1, npm >=10.5.2.

Command Runs Purpose
npm run build:css node scripts/build-css.js Compile + minify all CSS (lightningcss)
npm run build:js node scripts/build-js.js Bundle + minify all JS (esbuild)
npm run dev:css build-css.js --dev Unminified CSS for debugging
npm run dev:js build-js.js --dev Unminified JS for debugging
npm run build node scripts/cli.js build Full build (CSS + JS + assets)
npm run dev node scripts/cli.js dev Watch mode with BrowserSync
npm run build:blocks node scripts/build-all-blocks.js Build bundled block assets
npm run lint:css / lint:js stylelint / eslint on src/ Lint before building

Typical loop:

npm install          # first time
npm run dev          # watch + live reload while editing src/
npm run build        # produce final .min.css / .min.js before commit

The pre-commit hook (lint-staged) auto-fixes staged assets/css/src/** with stylelint and assets/js/src/** with eslint, so keep edits in src/.


Enqueue your own child-theme assets after BuddyX

BuddyX loads templates with standard get_template_part(), and its handles are stable, so child-theme assets follow the normal WordPress pattern: hook wp_enqueue_scripts at a priority above 10 (BuddyX enqueues at the default 10) and declare a BuddyX handle as a dependency so your file loads last.

Child-theme stylesheet after the parent

add_action( 'wp_enqueue_scripts', function () {
    wp_enqueue_style(
        'buddyx-child',
        get_stylesheet_uri(),            // child theme style.css
        array( 'buddyx-global' ),        // load after BuddyX core CSS
        wp_get_theme()->get( 'Version' )
    );
}, 20 );

Child-theme script depending on theme JS

add_action( 'wp_enqueue_scripts', function () {
    wp_enqueue_script(
        'buddyx-child-scripts',
        get_stylesheet_directory_uri() . '/assets/js/child.js',
        array( 'jquery', 'buddyx-custom' ), // after BuddyX main JS
        wp_get_theme()->get( 'Version' ),
        true                                 // in footer
    );
}, 20 );

Remove a BuddyX asset you do not want

Because handles are stable, dequeue the WordPress-native way at priority 20 (after BuddyX's 10):

add_action( 'wp_enqueue_scripts', function () {
    wp_dequeue_style( 'buddyx-slick' );  // e.g. you are not using carousels
}, 20 );

Extend the manifest instead (theme-level / plugin authors)

For conditional orchestration rather than an unconditional enqueue, filter the manifest so your entry inherits BuddyX's preload and dependency handling:

add_filter( 'buddyx_css_files', function ( $css_files ) {
    $css_files['my-feature'] = array(
        'file'             => 'my-feature.min.css', // under assets/css/
        'global'           => false,
        'preload_callback' => function () { return is_page( 'pricing' ); },
        'media'            => 'all',
        'deps'             => array( 'buddyx-global' ),
    );
    return $css_files;
} );

Use the manifest filter when your asset lives inside the theme's assets/css/ (or assets/js/) tree and you want BuddyX's conditional loading. Use plain wp_enqueue_*() at priority 20 for child-theme files that live in the child theme directory. Both approaches respect the stable handle names.


Debugging what loads

To confirm which handles fire on a page:

add_action( 'wp_print_styles', function () {
    global $wp_styles;
    error_log( 'Enqueued styles: ' . implode( ', ', $wp_styles->queue ) );
} );

Or open the browser Network tab and filter by .css / .js: BuddyX handle names are encoded in the built paths (for example buddypress.min.css, custom.min.js).


Related