If you’re upgrading your Sage theme to the newest version (v. 11), it’s important to remember several important things that I’ve learned along the way. You can’t just simply plop your old files into the new version, you’ll have to work through the process with a plan. Let’s discuss it.

Frontend Changes

Roots, the makers of Sage, have been doing great work for us with their upgrades to the Sage theme. It still uses the beloved Blade Templating system, but it does make some important changes. For instance, it comes preconfigured for Tailwind CSS (see the vite.config.js file below). It has also updated it’s build system and modernized other frontend tooling. The reason you should upgrade to the latest version is to truly enjoy the awesomeness of Laravel and

The Build System

Earlier versions of Sage used Webpack (pictured above) for the standard build tool out of the box, but in the newest version, Sage uses Vite, the now famous standard build tool used in a lot of modern projects. Of course, you can always re-wire any of your projects to use the build tool of your choice. I still have some old projects utilizing Laravel Mix (I personal favorite of mine – although I wouldn’t recommend it at this point because Vite is taking over as a tool that is actively maintained and used by lots of developers).

Why does that information matter?

Glad you asked. For starters, your old webpack.mix.js is gone. You’ll also need to review Vite’s documentation for updated ways of scripting the build process. You’ll have to update your package.json file with code like this:

{
  "scripts": {
    "dev": "vite", // start dev server, aliases: `vite dev`, `vite serve`
    "build": "vite build", // build for production
    "preview": "vite preview" // locally preview production build
  }
}

Generally speaking, Vite will come configured and ready to go for your build tool needs. You’ll probably need to run npm install and npm run build in the theme folder first though. You’ll notice the vite.config.js file in the root folder of version 11. This comes configured to get started out of the box. This is the contents of that file (you’ll notice it’s very different from the webpack setup from before):

import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite';
import laravel from 'laravel-vite-plugin'
import { wordpressPlugin, wordpressThemeJson } from '@roots/vite-plugin';

// Set APP_URL if it doesn't exist for Laravel Vite plugin
if (! process.env.APP_URL) {
  process.env.APP_URL = 'http://example.test';
}

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,
      assets: ['resources/images/**', 'resources/fonts/**'],
    }),

    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,
      disableTailwindBorderRadius: false,
    }),
  ],
  resolve: {
    alias: {
      '@scripts': '/resources/js',
      '@styles': '/resources/css',
      '@fonts': '/resources/fonts',
      '@images': '/resources/images',
    },
  },
})

Each setup is a bit different with different needs. Some previous setups you may have use Bootstrap, and you’ll need to slowly decouple Tailwind CSS from this setup and add Bootstrap back into it. With patience and a little problem solving tenacity, you’ll get it working. Just check the documentation often, and use help like search engines, and AI. Codex is very helpful in solving this problem because it can look at a previous setup and with the right prompts, edit the new setup correctly to include your frameworks and way of working.

Asset Handling & File Structure

Another thing you’ll notice that has changed in the newer version of Sage is the file structure. This is important to understand and lean into. Here’s a side by side file system view of Sage 9 and Sage 11.

Sage 9 File System

Sage 11 File System

I think the best way to describe the file changes in version 11 is as follows:

  • Cleaner, more opinionated structure in v11
  • Assets and resources are more modular
  • Better alignment with modern Laravel-style organization

Remember, you’re not going to be able to just “drop in” your old theme. You’ll likely port components, not copy files.

ES Modules

The way that Sage 11 treats Javascript allows for easier integration with modern frameworks. Legacy systems should probably be ported over to the new one. Some key elements and improvements include:

  • Native ES module syntax (import / export) is the default
  • Your code is organized into smaller, focused modules instead of large monolithic files
  • The browser (and modern build tools like Vite) understands your structure directly
  • Near-instant hot module replacement (HMR)
  • Faster builds compared to older Webpack setups
  • Better performance during development

NPM / Yarn

The newer setup in the newest version of Sage allows for improved workflows and cleaner, leaner builds. Because dependencies are managed through npm/Yarn and processed by modern tools (like Vite), you get:

  • Tree-shaking (only shipping what you actually use)
  • Smaller bundle sizes
  • Better performance out of the box

Backend Changes

At a high level, Sage moves away from the traditional “drop logic into functions.php” approach and toward a more structured, object-oriented system. Like other versions of Sage, it still uses Laravel as the back-bone of the theme, but leans more into it. You still get the Blade that you love, but even more Laravel.

Service Container & Dependency Injection

Sage 11 uses a service container (via Acorn) that allows you to register and resolve dependencies cleanly. Instead of instantiating classes manually or relying on global functions you can:

  • Inject dependencies where they’re needed
  • Swap implementations more easily
  • Keep your code loosely coupled

In other words, your theme acts more like an application and can be scaled and tested waaay better.

Clear Separation of Concerns

Logic that used to live in scattered template files or functions.php is now organized into service providers, view composers, and dedicated classes. For example:

  • Business logic lives in classes—not templates
  • Data passed to Blade views is handled in composers
  • App bootstrapping happens in providers

This allows you to keep your templates clean and focused purely on presentation. When you need to scale, it’s Laravel easy and a breeze to maintain.

The Bottom Line

My best advice to you is when you’re attempting to upgrade to a newer version of Sage, you should write everything down that needs to change, make a checklist somewhere. Make sure you’re using a staging environment like the setup I mentioned in this article. Go step by step on your local environment, and seek help if you get into trouble with any step along the way. ChatGPT, Codex and/or Claude Code are great troubleshooting helps if you get into trouble. Good luck!