Sage Roots, commonly known as Sage, is a WordPress starter theme and development workflow built on modern front-end tooling. It provides a foundation for creating custom WordPress themes using best practices and modern technologies, such as SCSS, JavaScript ES6+, and the Blade templating engine.
Sage streamlines the theme development process by incorporating tools like Webpack for asset compilation, Browsersync for live reloading, and Laravel's Blade for efficient template building. This approach enables developers to write cleaner, more maintainable code while leveraging the latest front-end development techniques.
Before diving into Sage, ensure you have the following prerequisites installed:
Node.js and NPM: Sage relies on Node.js and the Node Package Manager (NPM) for managing front-end dependencies and running build scripts. Visit https://nodejs.org to download and install the latest LTS version.
Composer: Composer is a dependency manager for PHP, which Sage uses to install and manage WordPress-specific dependencies. Install Composer by following the instructions at https://getcomposer.org.
Local WordPress Setup: You'll need a local WordPress installation to develop and test your Sage theme. Popular options include Local by Flywheel, DesktopServer, or a local development environment like MAMP or XAMPP.
Code Editor: Choose your preferred code editor, such as Visual Studio Code, Sublime Text, or PhpStorm. Consider installing plugins or extensions for SCSS, JavaScript, and Laravel Blade syntax highlighting and autocompletion.
To install the Sage starter theme, follow these steps:
Open your terminal or command prompt and navigate to your WordPress installation's wp-content/themes
directory.
Run the following Composer command to create a new Sage project:
composer create-project roots/sage my-sage-theme
Replace my-sage-theme
with your desired theme name.
Once the installation is complete, navigate to the newly created theme directory:
cd my-sage-theme
Install the required front-end dependencies by running:
npm install
Alternatively, you can use Yarn by running:
yarn install
Build the theme assets by running the following command: Or, if you're using Yarn:
yarn run build
Your Sage theme is now set up and ready for development!
Sage's directory structure differs from traditional WordPress themes. Here's an overview of the essential directories and files:
app/ : Contains PHP files for theme setup, filters, and custom functionality.
resources/ : Stores all front-end assets, including SCSS, JavaScript, and views (templates).
assets/ : Houses compiled CSS and JavaScript files.
views/ : Contains Blade template files organized into subdirectories for better organization.
dist/ : The compiled theme files, including minified CSS and JavaScript, are output here.
composer.json: Manages PHP dependencies and scripts.
package.json: Manages front-end dependencies and scripts.
webpack.mix.js: Configuration file for Webpack asset compilation.
Sage leverages Webpack for asset compilation, allowing you to write modular SCSS and JavaScript code using modern syntax and features.
Create new SCSS files in the resources/styles
directory, following the provided structure (e.g., resources/styles/components/_buttons.scss
).
Import your new SCSS files into resources/styles/main.scss
, which serves as the entry point for SCSS compilation.
Use @import
statements to include partials and organize your styles.
Webpack will automatically compile your SCSS files into a single main.css
file in the dist/styles
directory.
Here's an example of how you can structure your SCSS files:
resources/
└─ styles/
├─ components/
│ ├─ _buttons.scss
│ ├─ _cards.scss
│ └─ _forms.scss
├─ layouts/
│ ├─ _header.scss
│ ├─ _footer.scss
│ └─ _sidebar.scss
├─ utilities/
│ ├─ _functions.scss
│ ├─ _mixins.scss
│ └─ _variables.scss
├─ vendor/
│ └─ _bootstrap.scss
└─ main.scss
In main.scss
, you can import all the necessary files:
// utilities
@import 'utilities/functions';
@import 'utilities/mixins';
@import 'utilities/variables';
// vendor
@import 'vendor/bootstrap';
// components
@import 'components/buttons';
@import 'components/cards';
@import 'components/forms';
// layouts
@import 'layouts/header';
@import 'layouts/footer';
@import 'layouts/sidebar';
Create new JavaScript files in the resources/scripts
directory, adhering to the provided structure (e.g., resources/scripts/components/carousel.js
).
Import your JavaScript modules into resources/scripts/main.js
, the entry point for JavaScript compilation.
Take advantage of ES6+ features like classes, modules, and arrow functions.
Webpack will bundle and transpile your JavaScript files into a single main.js
file in the dist/script
directory.
Sage leverages Webpack and Babel to support modern JavaScript syntax and features. You can organize your JavaScript files into modules and leverage ES6+ features like classes, arrow functions, and import/export statements.
// resources/scripts/components/carousel.js
export default class Carousel {
constructor(element) {
this.carousel = element;
this.slides = this.carousel.querySelectorAll('.slide');
this.currentSlide = 0;
this.initCarousel();
}
initCarousel() {
this.showSlide(this.currentSlide);
this.carousel.addEventListener('click', this.nextSlide.bind(this));
}
showSlide(n) {
// ...
}
nextSlide() {
// ...
}
}
In resources/scripts/main.js
, you can import and instantiate your components:
import Carousel from './components/carousel';
const carousel = document.querySelector('.carousel');
if (carousel) {
new Carousel(carousel);
}
Sage incorporates Laravel's Blade templating engine, which offers a clean and expressive syntax for building WordPress templates. Here's an overview of using Blade in Sage:
Create new template files (e.g., page.blade.php
) in the resources/views
directory or its subdirectories.
Use @extends
to define a parent layout and @section
to define content areas within that layout.
Create reusable components using @component
and @slot
directives.
Pass data from PHP to your Blade templates using the @php
directive or by creating a custom $data
array in your theme's app/setup.php
file.
Leverage Blade's built-in control structures ( @if
, @foreach
, etc.) and template inheritance for efficient code organization.
Here's an example of creating a reusable card component:
{{-- resources/views/components/card.blade.php --}}
@props([
'title' => '',
'content' => '',
'link' => '',
])
<div class="card">
<div class="card-body">
<h5 class="card-title">{{ $title }}</h5>
<p class="card-text">{{ $content }}</p>
@if ($link)
<a href="{{ $link }}" class="btn btn-primary">Read More</a>
@endif
</div>
</div>
You can then use this component in your templates:
{{-- resources/views/page.blade.php --}}
@extends('layouts.app')
@section('content')
<div class="row">
@foreach ($posts as $post)
<div class="col-md-4">
@component('components.card')
@slot('title')
{{ $post->post_title }}
@endslot
@slot('content')
{{ $post->post_excerpt }}
@endslot
@slot('link')
{{ get_permalink($post->ID) }}
@endslot
@endcomponent
</div>
@endforeach
</div>
@endsection
Sage provides a solid foundation for building advanced WordPress themes. Here are some examples of how you can extend your theme with additional features:
Utilize modern JavaScript techniques, such as the Fetch API or Axios, to make AJAX requests and integrate with third-party APIs or your custom WordPress API endpoints.
// resources/scripts/components/api-integration.js
import axios from 'axios';
export default function fetchData() {
axios.get('/wp-json/my-custom-api/v1/data')
.then(response => {
// Handle API response
console.log(response.data);
})
.catch(error => {
// Handle error
console.error(error);
});
}
Leverage the power of custom post types and Advanced Custom Fields (ACF) to create rich content types and enhance your theme's functionality.
// app/setup.php
add_action('init', function() {
register_post_type('books', [
'public' => true,
'labels' => [
'name' => 'Books',
// ...
],
// ...
]);
});
{{-- resources/views/single-book.blade.php --}}
@extends('layouts.app')
@section('content')
<h1>{{ get_the_title() }}</h1>
<p>{{ the_field('book_description') }}</p>
@endsection
Sage makes it easy to register custom taxonomies and meta fields for your post types. In app/setup.php
, you can define your custom taxonomies and meta fields:
// app/setup.php
use Roots\Sage\Setup;
// Custom Taxonomy
Setup::roadTermMenu('Book Categories', 'book_category', 'book', [
'hierarchical' => true,
'public' => true,
]);
// Custom Meta Field
Setup::postMeta('Book Author', 'book_author', 'book', [
'type' => 'string',
'single' => true,
'show_in_rest' => true,
]);
You can then use these custom taxonomies and meta fields in your templates:
{{-- resources/views/single-book.blade.php --}}
@extends('layouts.app')
@section('content')
<h1>{{ get_the_title() }}</h1>
<p>Author: {{ get_post_meta(get_the_ID(), 'book_author', true) }}</p>
<p>Categories:</p>
<ul>
@foreach (get_the_terms(get_the_ID(), 'book_category') as $category)
<li>{{ $category->name }}</li>
@endforeach
</ul>
@endsection
Sage allows you to create custom Gutenberg blocks to enhance your content editing experience. You can define your block in resources/scripts/editor.js
:
// resources/scripts/editor.js
import { registerBlockType } from '@wordpress/blocks';
registerBlockType('my-theme/testimonial', {
title: 'Testimonial',
icon: 'format-quote',
category: 'common',
attributes: {
testimonial: {
type: 'string',
source: 'text',
selector: 'blockquote',
},
author: {
type: 'string',
source: 'attribute',
attribute: 'data-author',
selector: 'cite',
},
},
edit: ({ attributes, setAttributes }) => {
// ...
},
save: ({ attributes }) => {
// ...
},
});
Then, in your template files, you can render the block:
{{-- resources/views/single.blade.php --}}
@extends('layouts.app')
@section('content')
@while(have_posts()) @php(the_post())
{!! apply_filters('the_content', get_the_content()) !!}
@endwhile
@endsection
Sage provides a built-in helper function for optimizing images, ensuring better performance and faster load times. In your templates, you can use the @asset
directive:
<img src="@asset('images/hero.jpg')?resize(800,600)&quality=80" alt="Hero Image">
This will optimize the hero.jpg
image, resizing it to 800x600 pixels and compressing it with a quality of 80%.
To improve initial render times, you can generate critical CSS for your theme's templates. Sage includes a critical
mix task that generates critical CSS files for each template:
// webpack.mix.js
mix.critical({
enabled: mix.inProduction(),
urls: [
{ src: 'http://localhost/about', dest: 'about' },
{ src: 'http://localhost/blog', dest: 'blog' },
// ...
],
options: {
// Critical options
},
});
The generated critical CSS files will be included in your template's <head>
section, ensuring faster initial render times.
Build Process: Before deploying, run npm run build
or yarn run build
to generate the latest compiled assets in the dist
directory.
Upload to Server: Upload the entire theme directory, including the dist
folder, to your live server or hosting environment.
Theme Activation: Log in to your WordPress admin dashboard and activate the Sage theme.
Clear Caches: After activating the theme, clear any caches (server-side, browser, or CDN) to ensure the latest changes are reflected.
Sage Roots provides a powerful and efficient workflow for building custom WordPress themes while leveraging modern front-end development practices. By combining SCSS, JavaScript ES6+, and the Blade templating engine, Sage empowers developers to create maintainable, scalable, and high-performance themes.
Explore the Sage community and resources, such as the official documentation (https://roots.io/sage/) and the Roots Discord
Front-end Developer based in Miami.