Customization Guide

Customization Guide

Comprehensive guide to customizing BuddyX Pro theme appearance and functionality.

Getting Started

Prerequisites

  • Active BuddyX Pro installation
  • Child theme created (recommended)
  • Basic PHP, CSS, and JavaScript knowledge
  • FTP/SFTP access or File Manager
  • Code editor (VS Code, Sublime Text, etc.)

Recommended Setup

buddyx-pro-child/
├── style.css              # Custom CSS
├── functions.php          # Custom functions
├── assets/
│   ├── css/
│   │   └── custom.css    # Additional CSS
│   ├── js/
│   │   └── custom.js     # Custom JavaScript
│   └── images/           # Custom images
└── inc/
    └── customizations.php # Organized customizations

CSS Customization

Method 1: Customizer Additional CSS

Location: Appearance → Customize → Additional CSS

Quick CSS changes without creating files:

/* Change primary color */
:root {
    --color-primary: #007bff;
    --color-secondary: #6c757d;
}

/* Custom header styling */
.site-header {
    background-color: #ffffff;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

/* Modify button styles */
.button,
button[type="submit"] {
    border-radius: 5px;
    text-transform: uppercase;
    letter-spacing: 1px;
}

Method 2: Child Theme style.css

Location: buddyx-pro-child/style.css

For permanent, version-controlled changes:

/*
Theme Name: BuddyX Pro Child
Template: buddyx-pro
*/

/* ==========================================================================
   Typography
   ========================================================================== */

body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
    font-size: 16px;
    line-height: 1.6;
    color: #333333;
}

h1, h2, h3, h4, h5, h6 {
    font-weight: 700;
    line-height: 1.3;
    margin-bottom: 1rem;
}

/* ==========================================================================
   Layout
   ========================================================================== */

.container {
    max-width: 1200px;
}

.site-wrapper {
    padding-top: 2rem;
    padding-bottom: 2rem;
}

/* ==========================================================================
   Header
   ========================================================================== */

.site-header {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    padding: 1rem 0;
}

.site-header .site-logo-wrapper img {
    max-width: 180px;
}

/* ==========================================================================
   Navigation
   ========================================================================== */

.main-navigation ul {
    gap: 1.5rem;
}

.main-navigation a {
    color: #ffffff;
    font-weight: 500;
    transition: opacity 0.3s ease;
}

.main-navigation a:hover {
    opacity: 0.8;
}

/* ==========================================================================
   BuddyPress
   ========================================================================== */

#buddypress .activity-list .activity-content .activity-inner {
    background-color: #f8f9fa;
    border-radius: 8px;
    padding: 1.5rem;
}

#buddypress .activity-meta a {
    color: var(--color-primary);
}

/* ==========================================================================
   Footer
   ========================================================================== */

.site-footer {
    background-color: #1a1a1a;
    color: #ffffff;
    padding: 3rem 0 1rem;
}

.site-footer a {
    color: #ffffff;
}

Method 3: Separate CSS File

File: buddyx-pro-child/assets/css/custom.css

Enqueue in functions.php:

function buddyx_child_custom_styles() {
    wp_enqueue_style(
        'buddyx-child-custom',
        get_stylesheet_directory_uri() . '/assets/css/custom.css',
        array( 'buddyx-child-style' ),
        '1.0.0'
    );
}
add_action( 'wp_enqueue_scripts', 'buddyx_child_custom_styles', 30 );

CSS Variables Override

BuddyX Pro uses CSS custom properties:

:root {
    /* Colors */
    --color-primary: #ef5455;
    --color-secondary: #6c757d;
    --color-success: #28a745;
    --color-danger: #dc3545;
    --color-warning: #ffc107;
    --color-info: #17a2b8;

    /* Typography */
    --font-primary: 'Roboto', sans-serif;
    --font-secondary: 'Open Sans', sans-serif;

    /* Spacing */
    --spacing-small: 0.5rem;
    --spacing-medium: 1rem;
    --spacing-large: 2rem;

    /* Border Radius */
    --border-radius-small: 3px;
    --border-radius-medium: 5px;
    --border-radius-large: 10px;

    /* Shadows */
    --box-shadow-small: 0 2px 4px rgba(0, 0, 0, 0.1);
    --box-shadow-medium: 0 4px 6px rgba(0, 0, 0, 0.1);
    --box-shadow-large: 0 10px 20px rgba(0, 0, 0, 0.15);
}

JavaScript Customization

Adding Custom JavaScript

File: buddyx-pro-child/assets/js/custom.js

/**
 * BuddyX Pro Child Theme JavaScript
 *
 * @package BuddyX Pro Child
 */

(function($) {
    'use strict';

    /**
     * Document ready
     */
    $(document).ready(function() {
        console.log('BuddyX Child Theme Loaded');

        // Smooth scroll to anchor links
        $('a[href^="#"]').on('click', function(e) {
            e.preventDefault();
            var target = $(this.hash);
            if (target.length) {
                $('html, body').animate({
                    scrollTop: target.offset().top - 80
                }, 600);
            }
        });

        // Add active class to current menu item
        var currentUrl = window.location.href;
        $('.main-navigation a').each(function() {
            if (this.href === currentUrl) {
                $(this).parent().addClass('active');
            }
        });

        // Custom search toggle
        $('#custom-search-toggle').on('click', function(e) {
            e.preventDefault();
            $('.search-form-wrapper').toggleClass('active');
        });

        // Lazy load images
        if ('loading' in HTMLImageElement.prototype) {
            $('img[data-src]').each(function() {
                $(this).attr('src', $(this).attr('data-src'));
                $(this).removeAttr('data-src');
            });
        }
    });

    /**
     * Window load
     */
    $(window).on('load', function() {
        // Remove preloader
        $('.site-loader').fadeOut(300);
    });

    /**
     * Window scroll
     */
    $(window).on('scroll', function() {
        var scroll = $(window).scrollTop();

        // Sticky header
        if (scroll >= 100) {
            $('.site-header').addClass('sticky');
        } else {
            $('.site-header').removeClass('sticky');
        }

        // Back to top button
        if (scroll >= 300) {
            $('.back-to-top').fadeIn();
        } else {
            $('.back-to-top').fadeOut();
        }
    });

    /**
     * Back to top
     */
    $('.back-to-top').on('click', function(e) {
        e.preventDefault();
        $('html, body').animate({ scrollTop: 0 }, 600);
    });

})(jQuery);

Enqueue in functions.php:

function buddyx_child_custom_scripts() {
    wp_enqueue_script(
        'buddyx-child-custom',
        get_stylesheet_directory_uri() . '/assets/js/custom.js',
        array( 'jquery' ),
        '1.0.0',
        true
    );

    // Pass PHP data to JavaScript
    wp_localize_script(
        'buddyx-child-custom',
        'buddyxChildData',
        array(
            'ajaxurl'   => admin_url( 'admin-ajax.php' ),
            'nonce'     => wp_create_nonce( 'buddyx_child_nonce' ),
            'siteUrl'   => get_site_url(),
            'themeUrl'  => get_stylesheet_directory_uri(),
            'isLoggedIn' => is_user_logged_in(),
        )
    );
}
add_action( 'wp_enqueue_scripts', 'buddyx_child_custom_scripts' );

AJAX Example

JavaScript:

// custom.js
$('#custom-form').on('submit', function(e) {
    e.preventDefault();

    var formData = {
        action: 'buddyx_child_ajax_action',
        nonce: buddyxChildData.nonce,
        data: $(this).serialize()
    };

    $.ajax({
        url: buddyxChildData.ajaxurl,
        type: 'POST',
        data: formData,
        beforeSend: function() {
            $('.loading').show();
        },
        success: function(response) {
            if (response.success) {
                alert(response.data.message);
            } else {
                alert('Error: ' + response.data.message);
            }
        },
        complete: function() {
            $('.loading').hide();
        }
    });
});

PHP Handler:

// functions.php
function buddyx_child_ajax_handler() {
    check_ajax_referer( 'buddyx_child_nonce', 'nonce' );

    // Process form data
    parse_str( $_POST['data'], $form_data );

    // Your logic here
    $result = true; // Your processing result

    if ( $result ) {
        wp_send_json_success( array(
            'message' => __( 'Success!', 'buddyx-pro-child' ),
        ) );
    } else {
        wp_send_json_error( array(
            'message' => __( 'Error occurred.', 'buddyx-pro-child' ),
        ) );
    }
}
add_action( 'wp_ajax_buddyx_child_ajax_action', 'buddyx_child_ajax_handler' );
add_action( 'wp_ajax_nopriv_buddyx_child_ajax_action', 'buddyx_child_ajax_handler' );

PHP Customization

Custom Functions

File: buddyx-pro-child/inc/customizations.php

<?php
/**
 * Custom Theme Functions
 *
 * @package BuddyX Pro Child
 */

/**
 * Add custom body classes
 */
function buddyx_child_body_classes( $classes ) {
    // Add page-specific classes
    if ( is_page( 'about' ) ) {
        $classes[] = 'page-about';
    }

    // Add user role class
    if ( is_user_logged_in() ) {
        $user = wp_get_current_user();
        $classes[] = 'user-role-' . $user->roles[0];
    }

    // Add custom class based on customizer setting
    if ( get_theme_mod( 'custom_layout', false ) ) {
        $classes[] = 'custom-layout';
    }

    return $classes;
}
add_filter( 'body_class', 'buddyx_child_body_classes' );

/**
 * Custom excerpt length
 */
function buddyx_child_excerpt_length( $length ) {
    if ( is_front_page() ) {
        return 30;
    }
    return 55;
}
add_filter( 'excerpt_length', 'buddyx_child_excerpt_length', 999 );

/**
 * Custom excerpt more
 */
function buddyx_child_excerpt_more( $more ) {
    return '... <a class="read-more" href="' . get_permalink() . '">' . __( 'Read More', 'buddyx-pro-child' ) . '</a>';
}
add_filter( 'excerpt_more', 'buddyx_child_excerpt_more' );

/**
 * Add custom image sizes
 */
function buddyx_child_image_sizes() {
    add_image_size( 'custom-thumbnail', 300, 200, true );
    add_image_size( 'custom-featured', 800, 600, true );
    add_image_size( 'custom-hero', 1920, 1080, true );
}
add_action( 'after_setup_theme', 'buddyx_child_image_sizes' );

/**
 * Modify main query
 */
function buddyx_child_pre_get_posts( $query ) {
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }

    // Show 12 posts per page on archive
    if ( is_archive() ) {
        $query->set( 'posts_per_page', 12 );
    }

    // Exclude category from home
    if ( $query->is_home() ) {
        $query->set( 'cat', '-5' ); // Exclude category ID 5
    }
}
add_action( 'pre_get_posts', 'buddyx_child_pre_get_posts' );

/**
 * Custom post meta
 */
function buddyx_child_post_meta() {
    if ( ! is_single() ) {
        return;
    }

    echo '<div class="custom-post-meta">';
    echo '<span class="author">' . get_the_author() . '</span>';
    echo '<span class="date">' . get_the_date() . '</span>';
    echo '<span class="comments">' . get_comments_number() . ' Comments</span>';
    echo '</div>';
}
add_action( 'buddyx_after_content', 'buddyx_child_post_meta' );

Load in functions.php:

// Load customizations
require_once get_stylesheet_directory() . '/inc/customizations.php';

Widget Customization

Custom Widget Area

// functions.php
function buddyx_child_register_sidebars() {
    register_sidebar( array(
        'name'          => __( 'Custom Sidebar', 'buddyx-pro-child' ),
        'id'            => 'custom-sidebar',
        'description'   => __( 'Custom widget area', 'buddyx-pro-child' ),
        'before_widget' => '<div id="%1$s" class="widget %2$s">',
        'after_widget'  => '</div>',
        'before_title'  => '<h3 class="widget-title">',
        'after_title'   => '</h3>',
    ) );
}
add_action( 'widgets_init', 'buddyx_child_register_sidebars' );

Display Custom Widget Area

// In template file or via hook
<?php
if ( is_active_sidebar( 'custom-sidebar' ) ) {
    dynamic_sidebar( 'custom-sidebar' );
}
?>

Custom Widget

// inc/widgets/custom-widget.php
class BuddyX_Custom_Widget extends WP_Widget {

    public function __construct() {
        parent::__construct(
            'buddyx_custom_widget',
            __( 'Custom Widget', 'buddyx-pro-child' ),
            array(
                'description' => __( 'Display custom content', 'buddyx-pro-child' ),
                'classname'   => 'buddyx-custom-widget',
            )
        );
    }

    public function widget( $args, $instance ) {
        $title = ! empty( $instance['title'] ) ? $instance['title'] : '';
        $content = ! empty( $instance['content'] ) ? $instance['content'] : '';

        echo $args['before_widget'];

        if ( ! empty( $title ) ) {
            echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
        }

        echo '<div class="widget-content">';
        echo wp_kses_post( wpautop( $content ) );
        echo '</div>';

        echo $args['after_widget'];
    }

    public function form( $instance ) {
        $title = ! empty( $instance['title'] ) ? $instance['title'] : '';
        $content = ! empty( $instance['content'] ) ? $instance['content'] : '';
        ?>
        <p>
            <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
                <?php esc_html_e( 'Title:', 'buddyx-pro-child' ); ?>
            </label>
            <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
        </p>
        <p>
            <label for="<?php echo esc_attr( $this->get_field_id( 'content' ) ); ?>">
                <?php esc_html_e( 'Content:', 'buddyx-pro-child' ); ?>
            </label>
            <textarea class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'content' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'content' ) ); ?>" rows="5"><?php echo esc_textarea( $content ); ?></textarea>
        </p>
        <?php
    }

    public function update( $new_instance, $old_instance ) {
        $instance = array();
        $instance['title'] = sanitize_text_field( $new_instance['title'] );
        $instance['content'] = wp_kses_post( $new_instance['content'] );
        return $instance;
    }
}

function buddyx_child_register_custom_widget() {
    register_widget( 'BuddyX_Custom_Widget' );
}
add_action( 'widgets_init', 'buddyx_child_register_custom_widget' );

Customizer Integration

Add Customizer Panel

// inc/customizer.php
function buddyx_child_customize_register( $wp_customize ) {

    // Add panel
    $wp_customize->add_panel( 'buddyx_child_panel', array(
        'title'       => __( 'Child Theme Options', 'buddyx-pro-child' ),
        'description' => __( 'Customize child theme settings', 'buddyx-pro-child' ),
        'priority'    => 30,
    ) );

    // Add section
    $wp_customize->add_section( 'buddyx_child_colors', array(
        'title' => __( 'Custom Colors', 'buddyx-pro-child' ),
        'panel' => 'buddyx_child_panel',
    ) );

    // Add setting: Primary color
    $wp_customize->add_setting( 'child_primary_color', array(
        'default'           => '#007bff',
        'sanitize_callback' => 'sanitize_hex_color',
        'transport'         => 'postMessage',
    ) );

    // Add control
    $wp_customize->add_control( new WP_Customize_Color_Control(
        $wp_customize,
        'child_primary_color',
        array(
            'label'   => __( 'Primary Color', 'buddyx-pro-child' ),
            'section' => 'buddyx_child_colors',
        )
    ) );

    // Add setting: Toggle option
    $wp_customize->add_setting( 'child_enable_feature', array(
        'default'           => false,
        'sanitize_callback' => 'wp_validate_boolean',
    ) );

    $wp_customize->add_control( 'child_enable_feature', array(
        'label'   => __( 'Enable Custom Feature', 'buddyx-pro-child' ),
        'section' => 'buddyx_child_colors',
        'type'    => 'checkbox',
    ) );

    // Add setting: Text option
    $wp_customize->add_setting( 'child_custom_text', array(
        'default'           => '',
        'sanitize_callback' => 'sanitize_text_field',
    ) );

    $wp_customize->add_control( 'child_custom_text', array(
        'label'   => __( 'Custom Text', 'buddyx-pro-child' ),
        'section' => 'buddyx_child_colors',
        'type'    => 'text',
    ) );
}
add_action( 'customize_register', 'buddyx_child_customize_register' );

Use Customizer Values

// In template or functions
$primary_color = get_theme_mod( 'child_primary_color', '#007bff' );
$enable_feature = get_theme_mod( 'child_enable_feature', false );
$custom_text = get_theme_mod( 'child_custom_text', '' );

// Generate CSS from customizer
function buddyx_child_customizer_css() {
    $primary_color = get_theme_mod( 'child_primary_color', '#007bff' );

    $css = "
        :root {
            --child-primary: {$primary_color};
        }
        .button-primary {
            background-color: {$primary_color};
        }
    ";

    wp_add_inline_style( 'buddyx-child-style', $css );
}
add_action( 'wp_enqueue_scripts', 'buddyx_child_customizer_css', 50 );

Shortcode Creation

Simple Shortcode

// functions.php
function buddyx_child_button_shortcode( $atts, $content = null ) {
    $atts = shortcode_atts( array(
        'url'   => '#',
        'style' => 'primary',
        'size'  => 'medium',
        'icon'  => '',
    ), $atts );

    $class = 'btn btn-' . esc_attr( $atts['style'] ) . ' btn-' . esc_attr( $atts['size'] );

    $icon_html = '';
    if ( ! empty( $atts['icon'] ) ) {
        $icon_html = '<i class="fa fa-' . esc_attr( $atts['icon'] ) . '"></i> ';
    }

    return sprintf(
        '<a href="%s" class="%s">%s%s</a>',
        esc_url( $atts['url'] ),
        esc_attr( $class ),
        $icon_html,
        esc_html( $content )
    );
}
add_shortcode( 'button', 'buddyx_child_button_shortcode' );

// Usage: [button url="/signup/" style="primary" icon="user"]Sign Up[/button]

Advanced Shortcode with Query

function buddyx_child_recent_posts_shortcode( $atts ) {
    $atts = shortcode_atts( array(
        'posts'    => 3,
        'category' => '',
        'layout'   => 'grid',
    ), $atts );

    $args = array(
        'post_type'      => 'post',
        'posts_per_page' => intval( $atts['posts'] ),
        'post_status'    => 'publish',
    );

    if ( ! empty( $atts['category'] ) ) {
        $args['category_name'] = sanitize_text_field( $atts['category'] );
    }

    $query = new WP_Query( $args );

    if ( ! $query->have_posts() ) {
        return '';
    }

    ob_start();
    ?>
    <div class="recent-posts layout-<?php echo esc_attr( $atts['layout'] ); ?>">
        <?php
        while ( $query->have_posts() ) {
            $query->the_post();
            ?>
            <article class="recent-post-item">
                <?php if ( has_post_thumbnail() ) : ?>
                    <div class="post-thumbnail">
                        <a href="<?php the_permalink(); ?>">
                            <?php the_post_thumbnail( 'medium' ); ?>
                        </a>
                    </div>
                <?php endif; ?>
                <div class="post-content">
                    <h3 class="post-title">
                        <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
                    </h3>
                    <div class="post-excerpt">
                        <?php the_excerpt(); ?>
                    </div>
                </div>
            </article>
            <?php
        }
        ?>
    </div>
    <?php
    wp_reset_postdata();

    return ob_get_clean();
}
add_shortcode( 'recent_posts', 'buddyx_child_recent_posts_shortcode' );

// Usage: [recent_posts posts="5" category="news" layout="grid"]

Translation/Internationalization

Setup Translation

// functions.php
function buddyx_child_load_textdomain() {
    load_child_theme_textdomain(
        'buddyx-pro-child',
        get_stylesheet_directory() . '/languages'
    );
}
add_action( 'after_setup_theme', 'buddyx_child_load_textdomain' );

Translatable Strings

// Use translation functions
__( 'Text', 'buddyx-pro-child' );                    // Return translated
_e( 'Text', 'buddyx-pro-child' );                    // Echo translated
esc_html__( 'Text', 'buddyx-pro-child' );            // Return and escape
esc_html_e( 'Text', 'buddyx-pro-child' );            // Echo and escape
esc_attr__( 'Text', 'buddyx-pro-child' );            // Return for attributes

// With placeholders
sprintf(
    __( 'Hello %s!', 'buddyx-pro-child' ),
    $name
);

// Plurals
_n(
    '%s item',
    '%s items',
    $count,
    'buddyx-pro-child'
);

Generate Translation Files

# Install WP-CLI i18n command
wp package install wp-cli/i18n-command

# Generate POT file
wp i18n make-pot . languages/buddyx-pro-child.pot

# Update PO files
wp i18n update-po languages/buddyx-pro-child.pot languages/

Performance Optimization

Conditional Script Loading

function buddyx_child_conditional_scripts() {
    // Load only on specific pages
    if ( is_page( 'contact' ) ) {
        wp_enqueue_script( 'google-maps', 'https://maps.googleapis.com/maps/api/js?key=YOUR_KEY', array(), null, true );
    }

    // Load only for logged-in users
    if ( is_user_logged_in() ) {
        wp_enqueue_script( 'user-dashboard', get_stylesheet_directory_uri() . '/assets/js/dashboard.js', array( 'jquery' ), '1.0.0', true );
    }

    // Load only on BuddyPress pages
    if ( function_exists( 'is_buddypress' ) && is_buddypress() ) {
        wp_enqueue_script( 'bp-custom', get_stylesheet_directory_uri() . '/assets/js/buddypress-custom.js', array( 'jquery' ), '1.0.0', true );
    }
}
add_action( 'wp_enqueue_scripts', 'buddyx_child_conditional_scripts' );

Defer/Async Scripts

function buddyx_child_defer_scripts( $tag, $handle, $src ) {
    // Defer non-critical scripts
    $defer_scripts = array( 'buddyx-child-custom', 'analytics' );

    if ( in_array( $handle, $defer_scripts, true ) ) {
        return str_replace( ' src', ' defer src', $tag );
    }

    return $tag;
}
add_filter( 'script_loader_tag', 'buddyx_child_defer_scripts', 10, 3 );

Image Optimization

// Add WebP support
function buddyx_child_upload_mimes( $mimes ) {
    $mimes['webp'] = 'image/webp';
    return $mimes;
}
add_filter( 'upload_mimes', 'buddyx_child_upload_mimes' );

// Lazy load images
function buddyx_child_lazy_load_images( $content ) {
    if ( is_feed() || is_admin() ) {
        return $content;
    }

    $content = preg_replace( '/<img(.*?)src=/i', '<img$1loading="lazy" src=', $content );

    return $content;
}
add_filter( 'the_content', 'buddyx_child_lazy_load_images' );

Security Enhancements

Nonce Verification

// Form with nonce
function buddyx_child_custom_form() {
    ?>
    <form method="post" action="">
        <?php wp_nonce_field( 'buddyx_child_form_action', 'buddyx_child_nonce' ); ?>
        <input type="text" name="custom_field" />
        <button type="submit">Submit</button>
    </form>
    <?php
}

// Process form
function buddyx_child_process_form() {
    if ( ! isset( $_POST['buddyx_child_nonce'] ) || ! wp_verify_nonce( $_POST['buddyx_child_nonce'], 'buddyx_child_form_action' ) ) {
        wp_die( __( 'Security check failed', 'buddyx-pro-child' ) );
    }

    $custom_field = sanitize_text_field( $_POST['custom_field'] );
    // Process data
}

Sanitization and Validation

// Sanitize different input types
$text = sanitize_text_field( $_POST['text'] );
$email = sanitize_email( $_POST['email'] );
$url = esc_url_raw( $_POST['url'] );
$html = wp_kses_post( $_POST['html'] );
$int = absint( $_POST['number'] );

// Validate email
if ( ! is_email( $email ) ) {
    // Invalid email
}

// Validate URL
if ( ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
    // Invalid URL
}

Best Practices Checklist

Development

  • Use child theme for all customizations
  • Prefix all custom functions
  • Follow WordPress Coding Standards
  • Comment your code
  • Use version control (Git)
  • Test on multiple devices
  • Check browser compatibility
  • Validate HTML/CSS

Security

  • Escape all output
  • Sanitize all input
  • Verify nonces
  • Check capabilities
  • Use prepared statements for database queries
  • Don’t trust user input

Performance

  • Minimize HTTP requests
  • Optimize images
  • Use conditional loading
  • Defer non-critical scripts
  • Enable caching
  • Minimize CSS/JS

Accessibility

  • Use semantic HTML
  • Add alt text to images
  • Ensure keyboard navigation
  • Test with screen readers
  • Use ARIA labels
  • Maintain color contrast

Related Documentation

Last updated: January 31, 2026