Skip to main content

Styles and Scripts

Deodar provides a powerful asset management system that handles SCSS compilation, JavaScript bundling, and proper enqueuing for both frontend and backend. This guide will show you how to add and manage styles and scripts in your Deodar project.

Overview​

Deodar's asset management system offers:

  • SCSS Compilation: Automatic compilation with source maps
  • JavaScript Bundling: Modern ES6+ support with bundling
  • Conditional Loading: Load assets on frontend, backend, or both
  • Dependency Management: Handle script dependencies properly
  • Development & Production: Different builds for different environments
  • Watch Mode: Real-time compilation during development

Configuration​

Styles and scripts are configured in your main project file using the deodar filter:

add_filter('deodar', function($data) {
return [
'path' => get_template_directory(), // or plugin_dir_path(__FILE__)
'url' => get_template_directory_uri(), // or plugin_dir_url(__FILE__)
'production' => false,
'styles' => [
// Your styles configuration
],
'scripts' => [
// Your scripts configuration
]
];
});

Styles Configuration​

Basic Style Configuration​

'styles' => [
[
'handle' => 'main-style',
'file' => '/build/index.build.scss',
'frontend' => true,
'backend' => false
]
]

Style Configuration Options​

OptionTypeRequiredDescription
handlestring✅Unique identifier for the style
filestring⚠️Path to the SCSS file (relative to project root)
urlstring⚠️External URL for the style
frontendbool❌Load on frontend (default: true)
backendbool❌Load on backend/admin (default: false)
templatestring/array❌Specific template(s) to load this style on
dependenciesarray❌Array of style handles this depends on
versionstring❌Version string for cache busting
mediastring❌CSS media type (default: 'all')

⚠️ Either file or url is required (not both)

Advanced Style Configuration​

'styles' => [
[
'handle' => 'google-fonts',
'url' => 'https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap',
'frontend' => true,
'backend' => false
],
[
'handle' => 'main-style',
'file' => '/build/index.css',
'dependencies' => ['google-fonts'],
'version' => '1.0.0',
'media' => 'all',
'frontend' => true,
'backend' => false
],
[
'handle' => 'admin-style',
'file' => '/build/admin.build.css',
'frontend' => false,
'backend' => true
]
]

Scripts Configuration​

Basic Script Configuration​

'scripts' => [
[
'handle' => 'main-script',
'file' => '/build/index.build.js',
'frontend' => true,
'backend' => false
]
]

Script Configuration Options​

OptionTypeRequiredDescription
handlestring✅Unique identifier for the script
filestring⚠️Path to the JavaScript file (relative to project root)
urlstring⚠️External URL for the script
frontendbool❌Load on frontend (default: true)
backendbool❌Load on backend/admin (default: false)
templatestring/array❌Specific template(s) to load this script on
dependenciesarray❌Array of script handles this depends on
versionstring❌Version string for cache busting
argsbool❌Load in footer (default: false)

⚠️ Either file or url is required (not both)

Advanced Script Configuration​

'scripts' => [
[
'handle' => 'jquery',
'url' => 'https://code.jquery.com/jquery-3.6.0.min.js',
'frontend' => true,
'backend' => true
],
[
'handle' => 'main-script',
'file' => '/build/index.build.js',
'dependencies' => ['jquery'],
'version' => '1.0.0',
'args' => true, // Load in footer
'frontend' => true,
'backend' => false
],
[
'handle' => 'admin-script',
'file' => '/build/admin.build.js',
'dependencies' => ['jquery'],
'frontend' => false,
'backend' => true
]
]

File Structure​

your-project/
├── source/ # Source files
│ ├── index.scss # Global styles
│ ├── index.js # Global scripts
│ ├── admin.scss # Admin-only styles
│ └── admin.js # Admin-only scripts
├── build/ # Compiled assets (auto-generated)
│ ├── index.build.css
│ ├── index.build.css.map
│ ├── index.build.js
│ └── index.build.js.map
└── ... # Other files

Template-Specific Loading​

Template Key Usage​

The template key allows you to load assets only on specific templates, improving performance by loading only what's needed:

'styles' => [
[
'handle' => 'homepage-style',
'file' => '/build/homepage.build.css',
'template' => 'front-page.php',
'frontend' => true,
'backend' => false
],
[
'handle' => 'blog-style',
'file' => '/build/blog.build.css',
'template' => ['index.php', 'single.php', 'archive.php'],
'frontend' => true,
'backend' => false
]
]

Common Template Patterns​

A common pattern is to have global assets that are always loaded, plus template-specific assets. The global index.scss and index.js files import header styles and scripts:

'styles' => [
// Always loaded global styles (includes header via @use)
[
'handle' => 'main-style',
'file' => '/build/index.build.css',
'frontend' => true,
'backend' => false
],
// Template-specific styles
[
'handle' => 'homepage-style',
'file' => '/build/homepage.build.css',
'template' => 'front-page.php',
'frontend' => true,
'backend' => false
],
[
'handle' => 'contact-style',
'file' => '/build/contact.build.css',
'template' => 'page-contact.php',
'frontend' => true,
'backend' => false
]
],
'scripts' => [
// Always loaded global scripts (includes header via import)
[
'handle' => 'main-script',
'file' => '/build/index.build.js',
'frontend' => true,
'backend' => false
],
// Template-specific scripts
[
'handle' => 'homepage-script',
'file' => '/build/homepage.build.js',
'template' => 'front-page.php',
'frontend' => true,
'backend' => false
]
]

File Organization for Template-Specific Assets​

your-project/
├── source/
│ ├── index.scss # Global styles (imports header.scss)
│ ├── index.js # Global scripts (imports header.js)
│ ├── homepage.scss # Homepage-specific styles
│ ├── homepage.js # Homepage-specific scripts
│ ├── contact.scss # Contact page styles
│ └── contact.js # Contact page scripts
├── template-parts/
│ ├── header/
│ │ ├── header.scss # Header styles (imported by index.scss)
│ │ └── header.js # Header scripts (imported by index.js)
│ └── footer/
│ ├── footer.scss # Footer styles (imported by index.scss)
│ └── footer.js # Footer scripts (imported by index.js)
└── build/ # Compiled assets
├── index.build.css
├── homepage.build.css
└── contact.build.css

Import Patterns​

In source/index.scss:


// Template part styles
@use '../template-parts/header/header.scss';
@use '../template-parts/footer/footer.scss';

// Global styles
body {
font-family: 'Roboto', sans-serif;
}

In source/index.js:

// Import template part scripts
import Header from '../template-parts/header/header.js';
import Footer from '../template-parts/footer/footer.js';

// Global JavaScript
$(document).ready(function() {
console.log('Global script loaded');
});

External Dependencies​

CDN Resources​

You can include external resources from CDNs:

'styles' => [
[
'handle' => 'bootstrap',
'url' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css',
'frontend' => true,
'backend' => false
]
],
'scripts' => [
[
'handle' => 'bootstrap',
'url' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js',
'dependencies' => ['jquery'],
'frontend' => true,
'backend' => false
]
]

WordPress Dependencies​

Use WordPress core dependencies:

'scripts' => [
[
'handle' => 'custom-script',
'file' => '/build/index.build.js',
'dependencies' => ['jquery', 'wp-api'],
'frontend' => true,
'backend' => false
]
]

Build Configuration​

deodar.json Configuration​

Create a deodar.json file in your project root to customize the build process:

{
"externals": {
"jquery": "jQuery",
"lodash": "_",
"gsap": "gsap"
},
"skip": [
"node_modules/**",
"dist/**",
".git/**"
]
}

Configuration Options​

OptionTypeDescription
externalsobjectExternal dependencies to exclude from bundling
skiparrayFile patterns to skip during compilation

Development Workflow​

1. Create Source Files​

Create your SCSS and JavaScript files in the source/ directory:

// source/index.scss
$primary-color: #007cba;
$secondary-color: #f0f0f0;

body {
font-family: 'Roboto', sans-serif;
color: $primary-color;
}

.button {
background-color: $primary-color;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;

&:hover {
background-color: darken($primary-color, 10%);
}
}
// source/index.js
import $ from 'jquery';

$(document).ready(function() {
console.log('Deodar project loaded!');

// Your JavaScript code here
$('.button').on('click', function() {
console.log('Button clicked!');
});
});

2. Configure in Main File​

Add the styles and scripts to your Deodar configuration:

add_filter('deodar', function($data) {
return [
'path' => get_template_directory(),
'url' => get_template_directory_uri(),
'production' => false,
'styles' => [
[
'handle' => 'main-style',
'file' => '/build/index.build.scss',
'frontend' => true,
'backend' => false
]
],
'scripts' => [
[
'handle' => 'main-script',
'file' => '/build/index.build.js',
'dependencies' => ['jquery'],
'frontend' => true,
'backend' => false
]
]
];
});

3. Build Assets​

Use the Deodar CLI to build your assets:

# Development build
deodar development

# Production build
deodar production

# Watch mode for development
deodar watch

Best Practices​

Performance Optimization​

  1. Minimize Dependencies: Only include what you need
  2. Use CDNs Wisely: Balance performance vs. reliability
  3. Conditional Loading: Load assets only where needed
  4. Version Control: Use version strings for cache busting

Code Organization​

  1. Modular SCSS: Break styles into logical components
  2. ES6 Modules: Use modern JavaScript features
  3. Consistent Naming: Use consistent naming conventions
  4. Documentation: Document complex configurations

Development Workflow​

  1. Use Watch Mode: For real-time development
  2. Test Both Environments: Test frontend and backend loading
  3. Version Control: Track source files, not build files
  4. Error Handling: Handle missing files gracefully

Troubleshooting​

Common Issues​

Styles Not Loading

  • Check file paths in configuration
  • Verify SCSS compilation
  • Check browser console for errors

Scripts Not Working

  • Verify JavaScript file paths
  • Check for JavaScript errors in console
  • Ensure dependencies are loaded

Build Errors

  • Check SCSS syntax
  • Verify JavaScript syntax
  • Check deodar.json configuration

Debug Mode​

Enable debug mode to see detailed information:

'production' => false, // Set to false for development

Examples​

Complete Configuration Example​

add_filter('deodar', function($data) {
return [
'path' => get_template_directory(),
'url' => get_template_directory_uri(),
'production' => false,
'styles' => [
// External dependencies
[
'handle' => 'google-fonts',
'url' => 'https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap',
'frontend' => true,
'backend' => false
],
// Global styles (includes header via @use in source/index.scss)
[
'handle' => 'main-style',
'file' => '/build/index.build.css',
'version' => '1.0.0',
'frontend' => true,
'backend' => false
],
// Template-specific styles
[
'handle' => 'homepage-style',
'file' => '/build/homepage.build.css',
'template' => 'front-page.php',
'frontend' => true,
'backend' => false
],
[
'handle' => 'blog-style',
'file' => '/build/blog.build.css',
'template' => ['index.php', 'single.php', 'archive.php'],
'frontend' => true,
'backend' => false
],
// Admin styles
[
'handle' => 'admin-style',
'file' => '/build/admin.build.css',
'frontend' => false,
'backend' => true
]
],
'scripts' => [
// Global scripts (includes header via import in source/index.js)
[
'handle' => 'main-script',
'file' => '/build/index.build.js',
'dependencies' => ['jquery'],
'version' => '1.0.0',
'args' => true,
'frontend' => true,
'backend' => false
],
// Template-specific scripts
[
'handle' => 'homepage-script',
'file' => '/build/homepage.build.js',
'template' => 'front-page.php',
'dependencies' => ['jquery'],
'frontend' => true,
'backend' => false
],
// Admin scripts
[
'handle' => 'admin-script',
'file' => '/build/admin.build.js',
'dependencies' => ['jquery'],
'frontend' => false,
'backend' => true
]
]
];
});

Next Steps​

Now that you understand how to manage styles and scripts:


Ready to build something amazing? Let's create your first custom block!