• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » How to build custom Understrap styling structures extensions utilizing modern Heartbeat API schemas

How to build custom Understrap styling structures extensions utilizing modern Heartbeat API schemas

Leveraging Understrap’s Sass Architecture with the Heartbeat API

Understrap, a robust WordPress starter theme built on Bootstrap, offers a highly extensible Sass architecture. This post details how to integrate custom styling structures and dynamic updates using the WordPress Heartbeat API, specifically targeting advanced plugin development scenarios where real-time visual feedback or configuration changes are paramount. We’ll move beyond basic theme modifications to architecting a system that allows plugins to influence Understrap’s styling dynamically.

Understanding Understrap’s Sass Structure

Understrap’s strength lies in its modular Sass. Key directories include:

  • sass/: The root directory for all Sass files.
  • sass/theme/: Contains core Understrap styles, including Bootstrap overrides and custom Understrap components.
  • sass/custom/: The designated area for your custom Sass. This is where we’ll focus our integration efforts.
  • sass/custom/variables/: For overriding Bootstrap and Understrap variables.
  • sass/custom/mixins/: For custom Sass mixins.
  • sass/custom/components/: For custom component styles.

The build process (typically via npm scripts like npm run build or npm run watch) compiles these Sass files into style.css. To inject dynamic styles, we need a mechanism to trigger recompilation or inject CSS directly.

Introducing the Heartbeat API for Dynamic Styling

The WordPress Heartbeat API provides a way for the browser to communicate with the server at regular intervals. While often used for autosave and other dashboard functionalities, it’s a powerful tool for triggering server-side actions from the client. We can leverage this to signal that dynamic styles need to be generated or updated.

Plugin Architecture for Styling Extensions

We’ll create a simple WordPress plugin that:

  • Registers a Heartbeat API callback.
  • The callback will check for specific conditions or data.
  • If conditions are met, it will signal the need for style updates.
  • A separate mechanism will handle the actual style generation/injection.

Plugin Setup and Heartbeat Registration

First, let’s set up our plugin. Create a directory wp-content/plugins/understrap-styling-extensions and add a main plugin file, e.g., understrap-styling-extensions.php.

<?php
/**
 * Plugin Name: Understrap Styling Extensions
 * Description: Extends Understrap styling via Heartbeat API.
 * Version: 1.0.0
 * Author: Your Name
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly.
}

/**
 * Register Heartbeat API callback.
 */
function use_heartbeat_for_styling_extensions( $settings ) {
    // Add our custom heartbeat callback.
    $settings['callbacks'] = $settings['callbacks'] || array();
    $settings['callbacks']['heartbeat_received'] = 'my_custom_heartbeat_callback';
    return $settings;
}
add_filter( 'heartbeat_settings', 'use_heartbeat_for_styling_extensions' );

/**
 * Custom Heartbeat API callback function.
 *
 * This function is called when the Heartbeat API receives data.
 * It checks for a specific action and potentially triggers style updates.
 *
 * @param array $response The response data.
 * @param array $data     The data sent from the client.
 * @return array Modified response data.
 */
function my_custom_heartbeat_callback( $response, $data ) {
    // Check for a custom action sent from the client.
    if ( isset( $data['action'] ) && 'trigger_style_update' === $data['action'] ) {
        // In a real-world scenario, you might:
        // 1. Check user capabilities.
        // 2. Fetch options from the database.
        // 3. Generate dynamic CSS based on these.
        // For demonstration, we'll just add a flag to the response.
        $response['trigger_style_update'] = true;
        $response['style_update_timestamp'] = time(); // For cache busting or logging.
    }

    // You can also check for other conditions here.
    // For example, if a specific plugin option has changed.
    // if ( get_option( 'my_plugin_color_scheme' ) !== false ) {
    //     $response['color_scheme_changed'] = true;
    // }

    return $response;
}
add_action( 'heartbeat_received', 'my_custom_heartbeat_callback', 10, 2 );

// Include other necessary files for style generation.
// require_once plugin_dir_path( __FILE__ ) . 'includes/style-generator.php';
// require_once plugin_dir_path( __FILE__ ) . 'includes/heartbeat-handler.php';
?>

Client-Side Triggering of Heartbeat

The Heartbeat API needs to be triggered from the client-side (JavaScript) to send data to the server. We’ll enqueue a script that listens for specific events or conditions and then sends a Heartbeat request.

<?php
/**
 * Enqueue JavaScript for Heartbeat interaction.
 */
function enqueue_styling_extensions_scripts() {
    // Only enqueue on the front-end for simplicity.
    // You might want to enqueue this on specific admin pages too.
    if ( ! is_admin() ) {
        wp_enqueue_script(
            'understrap-styling-extensions-heartbeat',
            plugin_dir_url( __FILE__ ) . 'js/heartbeat-trigger.js',
            array( 'jquery', 'heartbeat' ), // Depends on jQuery and WordPress Heartbeat script.
            '1.0.0',
            true // Load in footer.
        );

        // Pass data to the script if needed.
        wp_localize_script( 'understrap-styling-extensions-heartbeat', 'heartbeat_params', array(
            'ajax_url' => admin_url( 'admin-ajax.php' ),
            'nonce'    => wp_create_nonce( 'heartbeat_nonce' ),
            // Add any other parameters your JS might need.
        ) );
    }
}
add_action( 'wp_enqueue_scripts', 'enqueue_styling_extensions_scripts' );
?>
// js/heartbeat-trigger.js
jQuery(document).ready(function($) {

    // Trigger Heartbeat with custom data when a specific event occurs.
    // For demonstration, we'll trigger it on a custom event.
    // In a real scenario, this could be tied to user actions,
    // changes in theme customizer, or AJAX responses.

    // Example: Trigger on a custom event named 'triggerStyleUpdateEvent'
    $(document).on('triggerStyleUpdateEvent', function() {
        console.log('Custom event detected: triggerStyleUpdateEvent. Sending Heartbeat...');
        wp.heartbeat.connect({
            action: 'trigger_style_update', // This matches our PHP callback's check.
            // You can send other data here as well.
            // plugin_data: { some_setting: 'value' }
        });
    });

    // You can also manually trigger a heartbeat connection.
    // For example, after a successful AJAX save of plugin settings.
    // $('#save-my-plugin-settings').on('click', function() {
    //     // ... perform save ...
    //     wp.heartbeat.connect({
    //         action: 'trigger_style_update',
    //         source: 'settings_save'
    //     });
    // });

    // Listen for responses from the Heartbeat API.
    $(document).on('heartbeat-tick', function(e, data) {
        // console.log('Heartbeat tick received:', data);

        if (data.trigger_style_update) {
            console.log('Server signaled style update needed at', data.style_update_timestamp);
            // Now, trigger the actual style generation or update mechanism.
            // This could involve:
            // 1. Making another AJAX call to a custom endpoint.
            // 2. Dynamically injecting CSS into the .
            // 3. Triggering a full Sass recompile (less ideal for front-end).
            trigger_dynamic_style_update();
        }

        // Example: Reacting to a color scheme change.
        // if (data.color_scheme_changed) {
        //     console.log('Color scheme has changed. Updating styles.');
        //     trigger_dynamic_style_update();
        // }
    });

    // Function to handle the actual style update.
    function trigger_dynamic_style_update() {
        // This is where the magic happens.
        // Option A: AJAX call to generate and return CSS.
        // $.ajax({
        //     url: heartbeat_params.ajax_url,
        //     type: 'POST',
        //     data: {
        //         action: 'generate_dynamic_css', // Custom AJAX action.
        //         _ajax_nonce: heartbeat_params.nonce
        //     },
        //     success: function(response) {
        //         if (response.success && response.data.css) {
        //             // Inject CSS into the head.
        //             $('#dynamic-plugin-styles').remove(); // Remove old styles.
        //             $('<style id="dynamic-plugin-styles">' + response.data.css + '</style>').appendTo('head');
        //             console.log('Dynamic styles injected.');
        //         }
        //     }
        // });

        // Option B: If your styles are simple variables, you might update them directly.
        // This is more complex and usually requires a JS-based CSS parser or
        // a pre-defined structure that JS can manipulate.
        // For example, if you have a CSS variable:
        // document.documentElement.style.setProperty('--primary-color', 'red');

        // For this example, let's simulate injecting CSS.
        // In a real plugin, this would be generated server-side.
        const dummyCss = `
            body {
                background-color: rgba(255, 0, 0, 0.1) !important; /* Example dynamic style */
            }
        `;
        $('#dynamic-plugin-styles').remove(); // Remove old styles.
        $('').appendTo('head');
        console.log('Simulated dynamic styles injected.');
    }

    // Example of how to trigger the custom event manually for testing.
    // setTimeout(function() {
    //     $(document).trigger('triggerStyleUpdateEvent');
    // }, 5000); // Trigger after 5 seconds.

});

Server-Side Style Generation and Injection

The Heartbeat API callback in PHP (`my_custom_heartbeat_callback`) can signal that styles need updating. The JavaScript then needs to act on this signal. The most robust approach is to have a server-side function that generates the CSS based on plugin settings or other dynamic data, and then have the JavaScript inject this CSS.

<?php
// Add this to your plugin file or a separate 'includes/style-generator.php' file.

/**
 * AJAX handler to generate dynamic CSS.
 */
function ajax_generate_dynamic_css() {
    check_ajax_referer( 'heartbeat_nonce', '_ajax_nonce' ); // Verify nonce.

    // --- Dynamic CSS Generation Logic ---
    // This is where you'd fetch plugin options, user meta, or other data.
    // Example: Fetching a custom color scheme from options.
    $primary_color = get_option( 'my_plugin_primary_color', '#007bff' ); // Default Bootstrap primary.
    $secondary_color = get_option( 'my_plugin_secondary_color', '#6c757d' ); // Default Bootstrap secondary.

    // You can also use Understrap's Sass variables as a base and override them.
    // For example, if you want to dynamically set the body background.
    $body_bg_color = get_option( 'my_plugin_body_bg', '#ffffff' );

    // Construct the CSS string.
    // It's best to target specific elements or use CSS variables.
    // Targeting Understrap/Bootstrap classes directly can be brittle if the theme updates.
    // Using CSS variables is generally more future-proof.
    $dynamic_css = '';

    // Example 1: Injecting CSS variables for theme customization.
    // This assumes your theme (or a child theme) uses these variables.
    // Understrap's default Bootstrap setup might not expose these directly in the head.
    // You might need to enqueue a stylesheet that *uses* these variables.
    $dynamic_css .= ":root {
        --plugin-primary-color: {$primary_color};
        --plugin-secondary-color: {$secondary_color};
        --plugin-body-bg: {$body_bg_color};
    }";

    // Example 2: Direct CSS overrides (use with caution).
    // This might be useful for specific components managed by your plugin.
    $dynamic_css .= "
        body {
            background-color: var(--plugin-body-bg);
        }
        .site-header {
            border-bottom-color: var(--plugin-primary-color);
        }
        .btn-primary {
            background-color: var(--plugin-primary-color);
            border-color: var(--plugin-primary-color);
        }
        .btn-secondary {
            background-color: var(--plugin-secondary-color);
            border-color: var(--plugin-secondary-color);
        }
    ";

    // --- End Dynamic CSS Generation Logic ---

    if ( ! empty( $dynamic_css ) ) {
        wp_send_json_success( array( 'css' => $dynamic_css ) );
    } else {
        wp_send_json_error( array( 'message' => 'No dynamic CSS generated.' ) );
    }
}
add_action( 'wp_ajax_generate_dynamic_css', 'ajax_generate_dynamic_css' );
// add_action( 'wp_ajax_nopriv_generate_dynamic_css', 'ajax_generate_dynamic_css' ); // If needed for non-logged-in users.
?>

In the JavaScript (js/heartbeat-trigger.js), the trigger_dynamic_style_update() function would now make an AJAX call to this generate_dynamic_css action. The response containing the CSS would then be injected into the document’s <head>.

Integrating with Understrap’s Sass Build Process (Advanced)

For scenarios requiring more complex styling or when you want your styles to be part of the compiled Sass, you can integrate with Understrap’s build process. This is more involved and typically requires modifying the theme’s build scripts or creating a separate build process for your plugin’s Sass.

Method 1: Injecting Sass Variables

You can generate a Sass partial file (e.g., wp-content/uploads/my-plugin-vars.scss) containing Sass variables derived from plugin settings. Then, modify Understrap’s config.rb (if using Compass) or package.json build scripts to include this partial in the Sass import path or directly in the main Sass file.

<?php
// Example: Function to generate a Sass variables file.
function generate_plugin_sass_vars() {
    $upload_dir = wp_upload_dir();
    $vars_file_path = $upload_dir['basedir'] . '/my-plugin-vars.scss';

    $primary_color = get_option( 'my_plugin_primary_color', '#007bff' );
    $secondary_color = get_option( 'my_plugin_secondary_color', '#6c757d' );

    $scss_content = <<<SCSS
// Generated by Understrap Styling Extensions plugin.
// Do NOT edit this file directly.
\$plugin-primary-color: {$primary_color};
\$plugin-secondary-color: {$secondary_color};
SCSS;

    // Ensure the uploads directory is writable.
    if ( wp_is_writable( $upload_dir['basedir'] ) ) {
        file_put_contents( $vars_file_path, $scss_content );
        // Potentially trigger a build process here if possible, or inform the user.
        // This is the tricky part: how to reliably trigger a Sass compile.
    } else {
        // Handle error: uploads directory not writable.
    }
}
// Hook this to an action that saves plugin settings.
// add_action( 'update_option_my_plugin_primary_color', 'generate_plugin_sass_vars' );
// add_action( 'update_option_my_plugin_secondary_color', 'generate_plugin_sass_vars' );
?>

You would then need to configure Understrap’s build process (e.g., Webpack, Gulp, or Grunt configured in package.json) to:

  • Add {$upload_dir['basedir']} to the Sass include paths.
  • Ensure my-plugin-vars.scss is imported into the main Sass entry point (e.g., sass/style.scss) or that the build process picks it up automatically.

Method 2: Custom Sass Component

Create a new Sass file within your plugin’s directory (e.g., understrap-styling-extensions/sass/plugin-styles.scss). This file would contain your custom component styles, potentially using the generated Sass variables from Method 1.

// understrap-styling-extensions/sass/plugin-styles.scss
@import "variables"; // Assuming my-plugin-vars.scss is included in the path and named _variables.scss

.plugin-custom-widget {
    border: 1px solid $plugin-primary-color;
    padding: 1rem;
    background-color: lighten($plugin-primary-color, 40%);

    h3 {
        color: $plugin-primary-color;
    }
}

You would then need to modify Understrap’s build process to include this Sass file in the compilation. This might involve:

  • Adding understrap-styling-extensions/sass/ to the Sass include paths.
  • Modifying the main Sass file (e.g., sass/style.scss) to include @import "plugin-styles";.
  • This approach requires the user to have the Understrap build tools set up and potentially re-run the build process whenever plugin settings change, which is less dynamic than the Heartbeat API method for front-end updates.

Considerations and Best Practices

  • Performance: Frequent Heartbeat pings can impact server load. Adjust the Heartbeat interval (via heartbeat_settings filter) or trigger Heartbeat only on specific user interactions.
  • Security: Always use nonces for AJAX requests and check user capabilities before performing sensitive operations or generating styles based on user-specific data.
  • Cache Busting: When injecting CSS dynamically, consider cache-busting techniques. Appending a timestamp or version number to the injected style tag’s ID or URL can help ensure users get the latest styles.
  • Specificity: Be mindful of CSS specificity. Your plugin’s styles should ideally override theme defaults gracefully without causing conflicts. Using CSS variables or targeting specific plugin-managed elements is recommended.
  • User Experience: Provide clear visual feedback to the user when styles are being updated or when a rebuild is necessary.
  • Understrap Updates: If integrating directly with the Sass build process, be aware that Understrap theme updates might overwrite your modifications to its build scripts. Prefer methods that don’t require altering core theme build files.

By combining the power of the WordPress Heartbeat API with Understrap’s flexible Sass architecture, developers can create sophisticated styling extensions that respond dynamically to user actions and plugin configurations, offering a truly integrated and customizable theming experience.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Designing audit logs for enterprise WordPress setups tracking internal user modifications to shipping tracking histories
  • Debugging and Resolving deep-seated hook priority conflicts in third-party Zapier dynamic webhooks connectors
  • Step-by-Step Guide: Offloading high-frequency shipping tracking histories metadata writes to a Redis KV store
  • How to implement custom REST API Controllers endpoints with token authentication in Gutenberg blocks
  • Step-by-Step Guide to building a custom real-time activity logs block for Gutenberg using PHP block-render callbacks

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (658)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (872)
  • PHP (5)
  • PHP Development (41)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (20)
  • Ruby on Rails (1)
  • Security & Compliance (639)
  • SEO & Growth (492)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (43)
  • WordPress Plugin Development (44)
  • WordPress Plugin Development (330)
  • WordPress Theme Development (357)

Recent Posts

  • Designing audit logs for enterprise WordPress setups tracking internal user modifications to shipping tracking histories
  • Debugging and Resolving deep-seated hook priority conflicts in third-party Zapier dynamic webhooks connectors
  • Step-by-Step Guide: Offloading high-frequency shipping tracking histories metadata writes to a Redis KV store

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (872)
  • Debugging & Troubleshooting (658)
  • Security & Compliance (639)
  • SEO & Growth (492)
  • Business & Monetization (390)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala