Advanced WordPress starter theme with Tailwind CSS and Laravel Blade
Hybrid WordPress theme development — Blade templates, Tailwind CSS, and Vite HMR for editor styles
Modern WordPress theme development with Laravel's Blade templating, Tailwind CSS that syncs to the block editor, and a professional development workflow.
~/wp-content/themes
$ composer create-project roots/sage my-theme
Creating a "roots/sage" project at "./my-theme"
Installing roots/sage (11.0.4)
- Downloading roots/sage (11.0.4)
- Installing roots/sage (11.0.4): Extracting archive
Created project in ./my-theme
$ cd my-theme && npm install && npm run build
added 127 packages in 8s
$ npm run build
> build
> vite build
vite v6.3.6 building for production...
✓ 4 modules transformed.
Generated an empty chunk: "app".
public/build/assets/editor.deps-DxpY22xl.json 0.02 kB │ gzip: 0.04 kB
public/build/manifest.json 0.67 kB │ gzip: 0.23 kB
public/build/assets/theme.json 34.56 kB │ gzip: 5.01 kB
public/build/assets/editor-ehnqdtwn.css 5.51 kB │ gzip: 1.83 kB
public/build/assets/app-Hfb9ghGI.css 19.27 kB │ gzip: 5.64 kB
public/build/assets/app-l0sNRNKZ.js 0.00 kB │ gzip: 0.02 kB
public/build/assets/editor-CfU4GbSP.js 0.03 kB │ gzip: 0.05 kB
✓ built in 123ms
Laravel Blade templates with WordPress
Use Laravel's powerful Blade templating engine for modern PHP templating features like template inheritance, components, and directives. Build reusable components with props and clean template organization.
Base layout template
resources/views/layouts/app.blade.php
<!doctype html>
<html @php(language_attributes())>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@php(do_action('get_header'))
@php(wp_head())
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body @php(body_class())>
@php(wp_body_open())
<div id="app">
<a class="sr-only focus:not-sr-only" href="#main">
{{ __('Skip to content', 'sage') }}
</a>
@include('sections.header')
<main id="main" class="main">
@yield('content')
</main>
@hasSection('sidebar')
<aside class="sidebar">
@yield('sidebar')
</aside>
@endif
@include('sections.footer')
</div>
@php(do_action('get_footer'))
@php(wp_footer())
</body>
</html>
Reusable alert component
resources/views/components/alert.blade.php
@props([
'type' => null,
'message' => null,
])
@php($class = match ($type) {
'success' => 'text-green-50 bg-green-400',
'caution' => 'text-yellow-50 bg-yellow-400',
'warning' => 'text-red-50 bg-red-400',
default => 'text-indigo-50 bg-indigo-400',
})
<div {{ $attributes->merge(['class' => "px-2 py-1 {$class}"]) }}>
{!! $message ?? $slot !!}
</div>
Tailwind CSS synced to WordPress block editor
Sage automatically generates theme.json
from your Tailwind configuration. Your color palette, font families, and sizes are immediately available in the WordPress block editor with zero configuration.
Tailwind CSS configuration
resources/css/app.css
@import "tailwindcss" theme(static);
@source "../views/";
@source "../../app/";
Generated theme.json
theme.json
{
"__processed__": "This file was generated using Vite",
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"layout": {
"contentSize": "48rem"
},
"background": {
"backgroundImage": true
},
"color": {
"custom": false,
"customDuotone": false,
"customGradient": false,
"defaultDuotone": false,
"defaultGradients": false,
"defaultPalette": false,
"duotone": [],
"palette": [
{
"name": "Gray (50)",
"slug": "gray-50",
"color": "oklch(98.5% .002 247.839)"
},
{
"name": "Gray (100)",
"slug": "gray-100",
"color": "oklch(96.7% .003 264.542)"
},
{
"name": "Gray (200)",
"slug": "gray-200",
"color": "oklch(92.8% .006 264.531)"
},
{
"name": "Gray (300)",
"slug": "gray-300",
"color": "oklch(87.2% .01 258.338)"
},
{
"name": "Gray (400)",
"slug": "gray-400",
"color": "oklch(70.7% .022 261.325)"
},
{
"name": "Gray (500)",
"slug": "gray-500",
"color": "oklch(55.1% .027 264.364)"
},
{
"name": "Gray (600)",
"slug": "gray-600",
"color": "oklch(44.6% .03 256.802)"
},
{
"name": "Gray (700)",
"slug": "gray-700",
"color": "oklch(37.3% .034 259.733)"
},
{
"name": "Gray (800)",
"slug": "gray-800",
"color": "oklch(27.8% .033 256.848)"
},
{
"name": "Gray (900)",
"slug": "gray-900",
"color": "oklch(21% .034 264.665)"
},
{
"name": "Gray (950)",
"slug": "gray-950",
"color": "oklch(13% .028 261.692)"
},
{
"name": "Black",
"slug": "black",
"color": "#000"
},
{
"name": "White",
"slug": "white",
"color": "#fff"
}
]
},
"custom": {
"spacing": {},
"typography": {
"font-size": {},
"line-height": {}
}
},
"spacing": {
"padding": true,
"units": [
"px",
"%",
"em",
"rem",
"vw",
"vh"
]
},
"typography": {
"defaultFontSizes": false,
"customFontSize": false,
"fontFamilies": [
{
"name": "sans",
"slug": "sans",
"fontFamily": "ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji"
},
{
"name": "serif",
"slug": "serif",
"fontFamily": "ui-serif,Georgia,Cambria,Times New Roman,Times,serif"
},
{
"name": "mono",
"slug": "mono",
"fontFamily": "ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace"
}
],
"fontSizes": [
{
"name": "xs",
"slug": "xs",
"size": ".75rem"
},
{
"name": "sm",
"slug": "sm",
"size": ".875rem"
},
{
"name": "base",
"slug": "base",
"size": "1rem"
},
{
"name": "lg",
"slug": "lg",
"size": "1.125rem"
},
{
"name": "xl",
"slug": "xl",
"size": "1.25rem"
},
{
"name": "2xl",
"slug": "2xl",
"size": "1.5rem"
},
{
"name": "3xl",
"slug": "3xl",
"size": "1.875rem"
},
{
"name": "4xl",
"slug": "4xl",
"size": "2.25rem"
},
{
"name": "5xl",
"slug": "5xl",
"size": "3rem"
},
{
"name": "6xl",
"slug": "6xl",
"size": "3.75rem"
},
{
"name": "7xl",
"slug": "7xl",
"size": "4.5rem"
},
{
"name": "8xl",
"slug": "8xl",
"size": "6rem"
},
{
"name": "9xl",
"slug": "9xl",
"size": "8rem"
}
]
}
}
}
Professional theme structure & modern workflow
Organized directory structure with PSR-4 autoloading, Vite build system with HMR, and editor styles that update live. Built on Acorn for Laravel features in WordPress.
Theme structure
my-theme
.
├── app/
│ ├── Providers/
│ ├── View/
│ │ └── Composers/
│ ├── filters.php
│ └── setup.php
├── resources/
│ ├── css/
│ │ ├── app.css
│ │ └── editor.css
│ ├── js/
│ │ ├── app.js
│ │ └── editor.js
│ └── views/
│ ├── components/
│ ├── layouts/
│ ├── partials/
│ └── sections/
├── public/
├── composer.json
├── package.json
├── theme.json
└── vite.config.js
Vite configuration with theme.json generation
vite.config.js
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite';
import laravel from 'laravel-vite-plugin'
import { wordpressPlugin, wordpressThemeJson } from '@roots/vite-plugin';
export default defineConfig({
base: '/app/themes/sage/public/build/',
plugins: [
tailwindcss(),
laravel({
input: [
'resources/css/app.css',
'resources/js/app.js',
'resources/css/editor.css',
'resources/js/editor.js',
],
refresh: true,
}),
wordpressPlugin(),
// Generate the theme.json file in the public/build/assets directory
// based on the Tailwind config and the theme.json file from base theme folder
wordpressThemeJson({
disableTailwindColors: false,
disableTailwindFonts: false,
disableTailwindFontSizes: false,
}),
],
resolve: {
alias: {
'@scripts': '/resources/js',
'@styles': '/resources/css',
'@fonts': '/resources/fonts',
'@images': '/resources/images',
},
},
})
Block editor integration with HMR
Hot Module Replacement works in the WordPress block editor. Style changes update instantly without page refreshes, making theme development faster and more enjoyable.
PSR-4 autoloading & Laravel patterns
Organized PHP with namespace autoloading, service providers for extensibility, and view composers for clean data management. All powered by Acorn.
Sponsors
Help support our open-source development efforts
Built with Sage




































Recommendations
If you have to use WordPress, use Bedrock for your web app and Sage to develop your custom theme. Any Laravel developer will feel at home in these tools.
I think 2 years ago I tweeted to y'all to say I love Sage -- now I'm getting started with Bedrock and loving it! thank you for making me feel like WordPress can be sane, secure, and modern.
In my opinion, the roots.io toolkit is the most sane way to do WordPress in 2023
Sage has brought WordPress development into the modern age. It's absolutely excellent and we'd have probably moved away from WordPress by now without it. Can't recommend it highly enough.
Subscribe for updates
Join over 8,000 subscribers on our newsletter to get the latest Roots updates and tips on building better WordPress sites
Looking for WordPress plugin recommendations, the newest modern WordPress projects, and general web development tips and articles?