Claude Skill

classic-theme-assets-build

Build or audit frontend asset loading for classic PHP WordPress themes on WP 7.1. Covers `wp_enqueue_scripts`, child-theme-safe `get_theme_file_uri()` and `get_theme_file_path()`, cache-busting with `filemtime()`, classic scripts and script modules, loading strategy/fetch priorit

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download lonsdale201-wp-agent-skills-theme-development_classic-theme-assets-build-52f6020.zip · 3 KB
Part of lonsdale201/wp-agent-skills — 226 skills

Install

skills CLI npx skills add https://github.com/Lonsdale201/wp-agent-skills/tree/main/theme-development/classic-theme-assets-build
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install lonsdale201-wp-agent-skills@llmmart
Git git clone https://github.com/Lonsdale201/wp-agent-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole lonsdale201/wp-agent-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Classic Theme Assets and Build Output

Use this when adding or reviewing CSS, JavaScript, fonts, images, build artifacts, cache busting, or conditional frontend assets in a classic PHP theme.

This skill is for the frontend theme layer. Admin, editor, and block-specific asset loading are separate concerns.

When to Use This Skill

  • Adding assets/css/*.css, assets/js/*.js, build output, or a bundler manifest.
  • Replacing hardcoded <link> or <script> tags in header.php or footer.php.
  • Adding conditional CSS/JS for navigation, comments, templates, sliders, galleries, maps, or page-specific UI.
  • Reviewing cache busting, defer/async, RTL styles, inline data, or asset paths in a classic theme.

Hook and Path Rules

Frontend theme assets load on wp_enqueue_scripts.

add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_assets' );

function mytheme_enqueue_assets() {
	$theme = wp_get_theme();

	wp_enqueue_style(
		'mytheme-style',
		get_stylesheet_uri(),
		array(),
		$theme->get( 'Version' )
	);
}

Rules:

  • Use wp_enqueue_scripts for public frontend CSS/JS.
  • Use admin_enqueue_scripts only for admin screens.
  • Use customize_controls_enqueue_scripts and customize_preview_init for Customizer-specific assets.
  • Use get_theme_file_uri() and get_theme_file_path() for theme files that may be overridden by a child theme.
  • Use get_stylesheet_uri() for the active theme's root style.css.
  • Do not hardcode theme URLs or filesystem paths.
  • Do not enqueue assets inside header.php, footer.php, template parts, or loops.

Cache Busting

Use filemtime() for local built files when the file exists. Fall back to the theme version.

function mytheme_asset_version( $relative_path ) {
	$path = get_theme_file_path( $relative_path );

	if ( file_exists( $path ) ) {
		return (string) filemtime( $path );
	}

	return wp_get_theme()->get( 'Version' );
}

Example:

wp_enqueue_style(
	'mytheme-main',
	get_theme_file_uri( 'assets/css/main.css' ),
	array(),
	mytheme_asset_version( 'assets/css/main.css' )
);

Rules:

  • Call filemtime() on filesystem paths, never URLs.
  • Keep version values deterministic. Do not use time() for production cache busting.
  • If a bundler writes a manifest, parse it once and fail gracefully when an entry is missing.

JavaScript Loading

WP 7.1 retains the modern $args array for wp_enqueue_script() (introduced in 6.3). It supports strategy, in_footer, and, since 6.9, fetchpriority.

wp_enqueue_script(
	'mytheme-navigation',
	get_theme_file_uri( 'assets/js/navigation.js' ),
	array(),
	mytheme_asset_version( 'assets/js/navigation.js' ),
	array(
		'strategy'  => 'defer',
		'in_footer' => true,
	)
);

Rules:

  • Use strategy => 'defer' when the script does not need to block parsing.
  • Use strategy => 'async' only for scripts that are order-independent.
  • Keep dependencies accurate. WordPress may adjust strategies to preserve dependency order.
  • Prefer small, focused frontend scripts over one global file that runs on every page.
  • Do not pass the old boolean footer parameter in new code unless maintaining legacy style.

Script modules

Use wp_enqueue_script_module() for a real ES module/import-map graph rather than printing a hand-written <script type="module">. Dependencies are module IDs; array entries can mark import as static or dynamic. Since WordPress 6.9 the args array supports in_footer and fetchpriority, and WordPress 7.0+ supports wp_set_script_module_translations().

Do not list classic script handles as module dependencies. If a classic script must dynamically import registered modules, use the module_dependencies classic-script argument available in WordPress 7.0+, or redesign one side of the boundary. Use the wp-plugin-assets-loading skill for the complete module contract and compatibility pattern.

Inline Data

Use wp_add_inline_script() for boot data and encode PHP data with wp_json_encode().

$data = array(
	'ajaxUrl' => admin_url( 'admin-ajax.php' ),
	'nonce'   => wp_create_nonce( 'mytheme_public_action' ),
);

wp_add_inline_script(
	'mytheme-navigation',
	'window.MyTheme = ' . wp_json_encode( $data ) . ';',
	'before'
);

Rules:

  • Do not include <script> tags in wp_add_inline_script(); core strips/warns about them.
  • Do not use wp_localize_script() for arbitrary config objects. Use it for translation-style localization.
  • Do not expose privileged data or long-lived secrets to frontend JavaScript.
  • Any nonce exposed to the frontend must still be paired with capability checks server-side where permissions matter.

Conditional Enqueues

Load assets only where they are needed.

if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
	wp_enqueue_script( 'comment-reply' );
}

if ( is_page_template( 'page-templates/landing.php' ) ) {
	wp_enqueue_style(
		'mytheme-landing',
		get_theme_file_uri( 'assets/css/landing.css' ),
		array( 'mytheme-main' ),
		mytheme_asset_version( 'assets/css/landing.css' )
	);
}

Good gating signals:

  • is_singular(), is_archive(), is_search(), is_front_page(), is_home().
  • is_page_template( 'page-templates/example.php' ).
  • has_nav_menu( 'primary' ) for navigation behavior.
  • comments_open() and get_option( 'thread_comments' ) for comment-reply.

Avoid running expensive queries just to decide whether to enqueue a file.

RTL, Preload, and Resource Hints

If the theme ships an RTL replacement stylesheet, register it with style data:

wp_style_add_data( 'mytheme-main', 'rtl', 'replace' );

Use resource hints sparingly:

  • wp_resource_hints can add DNS-prefetch/preconnect URLs.
  • wp_preload_resources can add preload links for critical resources.
  • Do not preload everything. Preload only resources needed very early.

For fonts:

  • Prefer self-hosted fonts when licensing allows.
  • Declare font-display deliberately.
  • Avoid loading multiple remote font families and weights by default.

Build Output Layout

A practical classic theme layout:

mytheme/
|-- assets/
|   |-- src/
|   |   |-- js/
|   |   `-- css/
|   |-- css/
|   |   `-- main.css
|   |-- js/
|   |   `-- navigation.js
|   `-- manifest.json

Rules:

  • Public files enqueued by WordPress must exist in predictable paths.
  • Source files may live under assets/src/, but templates should reference built public files.
  • Do not require Node, Vite, webpack, or npm at runtime.
  • Keep source maps out of production packages unless the project explicitly allows them.

Review Checklist

  • Frontend assets are hooked to wp_enqueue_scripts.
  • No hardcoded asset tags in header.php/footer.php.
  • Handles are unique and prefixed with the theme slug.
  • Local asset versions use filemtime() on paths or the theme version.
  • Script dependencies and loading strategy are explicit.
  • comment-reply loads only when needed.
  • RTL style data is registered when RTL files exist.
  • Inline data uses wp_json_encode() and wp_add_inline_script().
  • Conditional enqueues do not run heavy database work.
  • Build output paths exist and are child-theme-safe when override support is intended.

Common Mistakes

  • filemtime( get_theme_file_uri( ... ) ), which passes a URL to a filesystem function.
  • Adding <script> inside wp_add_inline_script().
  • Enqueueing every page-specific asset globally.
  • Using time() as a version in production.
  • Loading comment-reply on every page.
  • Forgetting that get_template_directory_uri() always points to the parent theme.
  • Breaking child theme overrides by using parent-only path helpers for overridable files.

References

Files (wp-agent-skills)
  • SKILL.md 9 KB
    ---
    name: classic-theme-assets-build
    description: Build or audit frontend asset loading for classic PHP WordPress themes on WP 7.1. Covers `wp_enqueue_scripts`, child-theme-safe `get_theme_file_uri()` and `get_theme_file_path()`, cache-busting with `filemtime()`, classic scripts and script modules, loading strategy/fetch priority, conditional enqueues, `comment-reply`, RTL style data, inline data with `wp_json_encode()` and `wp_add_inline_script()`, build output folders, preload/resource hints, and common mistakes such as hardcoded tags, enqueues inside templates, and invalid file paths.
    metadata:
      wp-skills-author: "Soczó Kristóf"
      wp-skills-contact: "mailto:lonsdale201@hotmail.com"
      wp-skills-plugin: "wordpress"
      wp-skills-plugin-version-tested: "7.1"
      wp-skills-wp-version-tested: "7.1"
      wp-skills-php-min: "7.4"
      wp-skills-last-updated: "2026-08-20"
    ---
    
    # Classic Theme Assets and Build Output
    
    Use this when adding or reviewing CSS, JavaScript, fonts, images, build artifacts, cache busting, or conditional frontend assets in a classic PHP theme.
    
    This skill is for the frontend theme layer. Admin, editor, and block-specific asset loading are separate concerns.
    
    ## When to Use This Skill
    
    - Adding `assets/css/*.css`, `assets/js/*.js`, build output, or a bundler manifest.
    - Replacing hardcoded `<link>` or `<script>` tags in `header.php` or `footer.php`.
    - Adding conditional CSS/JS for navigation, comments, templates, sliders, galleries, maps, or page-specific UI.
    - Reviewing cache busting, defer/async, RTL styles, inline data, or asset paths in a classic theme.
    
    ## Hook and Path Rules
    
    Frontend theme assets load on `wp_enqueue_scripts`.
    
    ```php
    add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_assets' );
    
    function mytheme_enqueue_assets() {
    	$theme = wp_get_theme();
    
    	wp_enqueue_style(
    		'mytheme-style',
    		get_stylesheet_uri(),
    		array(),
    		$theme->get( 'Version' )
    	);
    }
    ```
    
    Rules:
    
    - Use `wp_enqueue_scripts` for public frontend CSS/JS.
    - Use `admin_enqueue_scripts` only for admin screens.
    - Use `customize_controls_enqueue_scripts` and `customize_preview_init` for Customizer-specific assets.
    - Use `get_theme_file_uri()` and `get_theme_file_path()` for theme files that may be overridden by a child theme.
    - Use `get_stylesheet_uri()` for the active theme's root `style.css`.
    - Do not hardcode theme URLs or filesystem paths.
    - Do not enqueue assets inside `header.php`, `footer.php`, template parts, or loops.
    
    ## Cache Busting
    
    Use `filemtime()` for local built files when the file exists. Fall back to the theme version.
    
    ```php
    function mytheme_asset_version( $relative_path ) {
    	$path = get_theme_file_path( $relative_path );
    
    	if ( file_exists( $path ) ) {
    		return (string) filemtime( $path );
    	}
    
    	return wp_get_theme()->get( 'Version' );
    }
    ```
    
    Example:
    
    ```php
    wp_enqueue_style(
    	'mytheme-main',
    	get_theme_file_uri( 'assets/css/main.css' ),
    	array(),
    	mytheme_asset_version( 'assets/css/main.css' )
    );
    ```
    
    Rules:
    
    - Call `filemtime()` on filesystem paths, never URLs.
    - Keep version values deterministic. Do not use `time()` for production cache busting.
    - If a bundler writes a manifest, parse it once and fail gracefully when an entry is missing.
    
    ## JavaScript Loading
    
    WP 7.1 retains the modern `$args` array for `wp_enqueue_script()` (introduced
    in 6.3). It supports `strategy`, `in_footer`, and, since 6.9,
    `fetchpriority`.
    
    ```php
    wp_enqueue_script(
    	'mytheme-navigation',
    	get_theme_file_uri( 'assets/js/navigation.js' ),
    	array(),
    	mytheme_asset_version( 'assets/js/navigation.js' ),
    	array(
    		'strategy'  => 'defer',
    		'in_footer' => true,
    	)
    );
    ```
    
    Rules:
    
    - Use `strategy => 'defer'` when the script does not need to block parsing.
    - Use `strategy => 'async'` only for scripts that are order-independent.
    - Keep dependencies accurate. WordPress may adjust strategies to preserve dependency order.
    - Prefer small, focused frontend scripts over one global file that runs on every page.
    - Do not pass the old boolean footer parameter in new code unless maintaining legacy style.
    
    ### Script modules
    
    Use `wp_enqueue_script_module()` for a real ES module/import-map graph rather
    than printing a hand-written `<script type="module">`. Dependencies are module
    IDs; array entries can mark `import` as `static` or `dynamic`. Since WordPress
    6.9 the args array supports `in_footer` and `fetchpriority`, and WordPress 7.0+
    supports `wp_set_script_module_translations()`.
    
    Do not list classic script handles as module dependencies. If a classic script
    must dynamically import registered modules, use the `module_dependencies`
    classic-script argument available in WordPress 7.0+, or redesign one side of
    the boundary. Use the `wp-plugin-assets-loading` skill for the complete module
    contract and compatibility pattern.
    
    ## Inline Data
    
    Use `wp_add_inline_script()` for boot data and encode PHP data with `wp_json_encode()`.
    
    ```php
    $data = array(
    	'ajaxUrl' => admin_url( 'admin-ajax.php' ),
    	'nonce'   => wp_create_nonce( 'mytheme_public_action' ),
    );
    
    wp_add_inline_script(
    	'mytheme-navigation',
    	'window.MyTheme = ' . wp_json_encode( $data ) . ';',
    	'before'
    );
    ```
    
    Rules:
    
    - Do not include `<script>` tags in `wp_add_inline_script()`; core strips/warns about them.
    - Do not use `wp_localize_script()` for arbitrary config objects. Use it for translation-style localization.
    - Do not expose privileged data or long-lived secrets to frontend JavaScript.
    - Any nonce exposed to the frontend must still be paired with capability checks server-side where permissions matter.
    
    ## Conditional Enqueues
    
    Load assets only where they are needed.
    
    ```php
    if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
    	wp_enqueue_script( 'comment-reply' );
    }
    
    if ( is_page_template( 'page-templates/landing.php' ) ) {
    	wp_enqueue_style(
    		'mytheme-landing',
    		get_theme_file_uri( 'assets/css/landing.css' ),
    		array( 'mytheme-main' ),
    		mytheme_asset_version( 'assets/css/landing.css' )
    	);
    }
    ```
    
    Good gating signals:
    
    - `is_singular()`, `is_archive()`, `is_search()`, `is_front_page()`, `is_home()`.
    - `is_page_template( 'page-templates/example.php' )`.
    - `has_nav_menu( 'primary' )` for navigation behavior.
    - `comments_open()` and `get_option( 'thread_comments' )` for `comment-reply`.
    
    Avoid running expensive queries just to decide whether to enqueue a file.
    
    ## RTL, Preload, and Resource Hints
    
    If the theme ships an RTL replacement stylesheet, register it with style data:
    
    ```php
    wp_style_add_data( 'mytheme-main', 'rtl', 'replace' );
    ```
    
    Use resource hints sparingly:
    
    - `wp_resource_hints` can add DNS-prefetch/preconnect URLs.
    - `wp_preload_resources` can add preload links for critical resources.
    - Do not preload everything. Preload only resources needed very early.
    
    For fonts:
    
    - Prefer self-hosted fonts when licensing allows.
    - Declare `font-display` deliberately.
    - Avoid loading multiple remote font families and weights by default.
    
    ## Build Output Layout
    
    A practical classic theme layout:
    
    ```text
    mytheme/
    |-- assets/
    |   |-- src/
    |   |   |-- js/
    |   |   `-- css/
    |   |-- css/
    |   |   `-- main.css
    |   |-- js/
    |   |   `-- navigation.js
    |   `-- manifest.json
    ```
    
    Rules:
    
    - Public files enqueued by WordPress must exist in predictable paths.
    - Source files may live under `assets/src/`, but templates should reference built public files.
    - Do not require Node, Vite, webpack, or npm at runtime.
    - Keep source maps out of production packages unless the project explicitly allows them.
    
    ## Review Checklist
    
    - Frontend assets are hooked to `wp_enqueue_scripts`.
    - No hardcoded asset tags in `header.php`/`footer.php`.
    - Handles are unique and prefixed with the theme slug.
    - Local asset versions use `filemtime()` on paths or the theme version.
    - Script dependencies and loading strategy are explicit.
    - `comment-reply` loads only when needed.
    - RTL style data is registered when RTL files exist.
    - Inline data uses `wp_json_encode()` and `wp_add_inline_script()`.
    - Conditional enqueues do not run heavy database work.
    - Build output paths exist and are child-theme-safe when override support is intended.
    
    ## Common Mistakes
    
    - `filemtime( get_theme_file_uri( ... ) )`, which passes a URL to a filesystem function.
    - Adding `<script>` inside `wp_add_inline_script()`.
    - Enqueueing every page-specific asset globally.
    - Using `time()` as a version in production.
    - Loading `comment-reply` on every page.
    - Forgetting that `get_template_directory_uri()` always points to the parent theme.
    - Breaking child theme overrides by using parent-only path helpers for overridable files.
    
    ## References
    
    - Official documentation: <https://developer.wordpress.org/themes/core-concepts/including-assets/>
    - Official documentation: <https://developer.wordpress.org/reference/hooks/wp_enqueue_scripts/>
    - Verified source paths:
      - `wp-includes/script-loader.php`
      - `wp-includes/functions.wp-scripts.php`
      - `wp-includes/functions.wp-styles.php`
      - `wp-includes/class-wp-scripts.php`
      - `wp-includes/class-wp-styles.php`
      - `wp-includes/link-template.php`
      - `wp-includes/general-template.php`
      - `wp-content/themes/storefront/inc/class-storefront.php`
      - `wp-content/themes/generatepress/inc/general.php`
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related