Appearance
Building Assets
Introduction
Vue themes are built with Vite and laravel-vite-plugin, plus a small plugin from kitloom/themes that understands themes: where a theme lives, what it inherits from, and what installed modules contribute to the front end.
Blade themes have nothing to build.
The Vite plugin
js
import kitloomTheme, { themeEntry } from './vendor/kitloom/themes/vite/index.js';
const theme = process.env.APP_THEME || 'Portfolio';
export default defineConfig({
plugins: [
laravel({
input: [themeEntry(theme)],
buildDirectory: `build-${theme}`,
}),
kitloomTheme({ theme }),
vue(),
],
});| Export | What it does |
|---|---|
kitloomTheme({ theme, base?, root? }) | The plugin. base is read from the theme's declaration when omitted. |
themeEntry(theme, { file? }) | Path of the theme's entry (resources/app.js by default) relative to the app root — for input. Pass { file: 'resources/ssr.js' } for the SSR entry. |
buildableThemes() | Names of installed themes that have resources/app.js. |
declaredThemes(root) | Themes declared by installed packages: name → { base, directory }. |
The theme directory is themes/{Theme} in your application, or the package directory in vendor/ — the same lookup PHP uses.
Aliases
| Alias | Points to |
|---|---|
@ | The theme's resources/js. In a child theme, a file the child lacks is taken from the base. |
@base | The base theme's resources/js |
@baseRes | The base theme's resources |
ziggy-js | Ziggy from your application's vendor/ — a theme that imports it requires tightenco/ziggy |
A global APP_THEME constant holds the theme name being built.
Virtual modules
virtual:theme-css
Imports the theme's resources/css/app.css, or the base theme's if the child has none:
js
import 'virtual:theme-css';virtual:shortcode-components
A map of shortcode → Vue component, collected from every installed package that declares components in its composer.json:
json
{
"extra": {
"kitloom": {
"shortcode-components": {
"slide-anything": "resources/js/SlideAnything.vue"
}
}
}
}The theme merges it into its own component map, without knowing which modules are installed. Its own component for the same shortcode wins:
js
import moduleComponents from 'virtual:shortcode-components';
import ContactForm from '@/Components/Shortcodes/ContactForm.vue';
export const shortcodeComponents = {
...moduleComponents,
'contact-form-7': ContactForm,
};Imports are static, so a component's styles are part of the build and present in server-rendered markup.
Images, fonts and the sprite
Before a build, the plugin:
- copies the theme's
resources/imagesandresources/fontstopublic/images/{Theme}andpublic/fonts/{Theme}— reference them with absolute URLs from CSS; - stitches icons from
resources/images/theme/iconsinto a spritepublic/images/{Theme}/theme/sprite.{hash}.webpand writesresources/css/sprite.css. The dev server rebuilds the sprite when an icon changes.
The sprite needs sharp and spritesmith in your application's devDependencies — only if the theme has icons.
Dependencies of packaged themes
A theme installed as a package — often a symlink in development — has no node_modules of its own. Bare imports from its files (import axios from 'axios') are resolved from your application's node_modules. Install the theme's JavaScript dependencies in the application, as listed in the theme's README or the skeleton's package.json.
The dev server is allowed to serve files from the package directories automatically.
Building every theme
bash
npm run build:themes # all buildable themes
npm run build:themes MyTheme Foo # selected themesbuild:themes is node vendor/kitloom/themes/vite/build-themes.js: it runs your npm run build once per theme with APP_THEME set. Each theme gets its own public/build-{Theme} with its own manifest, and the PHP side points @vite at the active theme's directory. Build all themes on deploy so any of them can be activated from the admin.
A theme counts as built when its manifest exists — or when the Vite dev server is running (public/hot).