InertiaThemes

Documentation

Learn how to build switchable themes with composable blocks for your Laravel/Inertia applications.

1 Installation

Install InertiaThemes via Composer:

Terminal
$ composer require inertiathemes/inertiathemes

Then publish the assets for your framework:

Vue / React / Svelte
# Vue
$ php artisan vendor:publish --tag=inertiathemes-vue

# React
$ php artisan vendor:publish --tag=inertiathemes-react

# Svelte
$ php artisan vendor:publish --tag=inertiathemes-svelte

2 Configuration

Publish the configuration file:

Terminal
$ php artisan vendor:publish --tag=inertiathemes-config

Configure your default theme in config/inertiathemes.php:

config/inertiathemes.php
return [
    'default_theme' => \App\Themes\DefaultTheme::class,
    'themes_path' => app_path('Themes'),
    'blocks_path' => app_path('Blocks'),
    'components_path' => resource_path('js/Blocks'),
];

3 Quick Start

Create your first theme and block:

Terminal
# Create a theme
$ php artisan make:theme DefaultTheme

# Create a block
$ php artisan make:block HeroBlock

Then render blocks in your Inertia page:

Page.vue
<template>
  <Blocks />
</template>

Themes

Themes are PHP classes that define your application's visual identity. They contain colors, typography settings, and other design tokens.

app/Themes/DefaultTheme.php
<?php

namespace App\Themes;

use InertiaThemes\BaseTheme;

class DefaultTheme extends BaseTheme
{
    public function name(): string
    {
        return 'Default';
    }

    public function colors(): array
    {
        return [
            'primary' => '#3B82F6',
            'secondary' => '#1F2937',
            'accent' => '#10B981',
            'background' => '#FFFFFF',
            'text' => '#111827',
        ];
    }

    public function fonts(): array
    {
        return [
            'heading' => 'Inter',
            'body' => 'Inter',
        ];
    }
}

Blocks

Blocks define the content schema for each section of your page. They specify what data each block type needs.

app/Blocks/HeroBlock.php
<?php

namespace App\Blocks;

use InertiaThemes\BaseBlock;

class HeroBlock extends BaseBlock
{
    public function name(): string
    {
        return 'Hero';
    }

    public function schema(): array
    {
        return [
            'title' => 'string',
            'subtitle' => 'string',
            'cta_text' => 'string',
            'cta_url' => 'string',
            'background_image' => 'string|null',
        ];
    }

    public function defaults(): array
    {
        return [
            'title' => 'Welcome',
            'subtitle' => 'Build something amazing',
            'cta_text' => 'Get Started',
            'cta_url' => '#',
            'background_image' => null,
        ];
    }
}

Components

Components are the frontend templates for your blocks. They're organized by theme and can be Vue, React, or Svelte files.

resources/js/Blocks/Default/HeroBlock.vue
<script setup>
defineProps({
  title: String,
  subtitle: String,
  cta_text: String,
  cta_url: String,
  background_image: String,
  theme: Object,
})
</script>

<template>
  <section
    class="hero min-h-screen flex items-center justify-center"
    :style="{ backgroundColor: theme.colors.primary }"
  >
    <div class="text-center">
      <h1 class="text-5xl font-bold mb-4">{{ title }}</h1>
      <p class="text-xl mb-8">{{ subtitle }}</p>
      <a :href="cta_url" class="btn">{{ cta_text }}</a>
    </div>
  </section>
</template>

Tip: Components receive the current theme object as a prop, allowing you to access theme colors and settings dynamically.

Rendering Blocks

Use the <Blocks /> component to render your blocks. You can render all blocks or filter by area.

Page.vue
<template>
  <!-- Render all blocks -->
  <Blocks />

  <!-- Render blocks by area -->
  <header>
    <Blocks area="header" />
  </header>

  <main>
    <Blocks area="content" />
  </main>

  <footer>
    <Blocks area="footer" />
  </footer>
</template>

Pass blocks from your controller:

PageController.php
use InertiaThemes\Facades\InertiaThemes;

public function show(Page $page)
{
    return Inertia::render('Page', [
        'blocks' => InertiaThemes::renderBlocks($page->blocks),
        'theme' => InertiaThemes::currentTheme()->toArray(),
    ]);
}

Global Blocks

Global blocks appear on every page of your application. This is useful for headers, footers, navigation, and other persistent elements.

To implement global blocks, create a custom BaseBlock in your application that extends the package's BaseBlock:

app/Blocks/BaseBlock.php
<?php

namespace App\Blocks;

use InertiaThemes\BaseBlock as PackageBaseBlock;

/**
 * Application Base Block
 *
 * Extends the package BaseBlock with app-specific features like global blocks.
 */
abstract class BaseBlock extends PackageBaseBlock
{
    /**
     * Whether this block is global (appears on all pages).
     */
    protected bool $isGlobal = false;

    /**
     * Position for global blocks: 'before' or 'after' page content.
     */
    protected string $globalPosition = 'before';

    /**
     * Check if this block is global.
     */
    public function isGlobal(): bool
    {
        return $this->isGlobal;
    }

    /**
     * Get the global position.
     */
    public function globalPosition(): string
    {
        return $this->globalPosition;
    }

    /**
     * Convert the block definition to an array for frontend consumption.
     */
    public function toArray(): array
    {
        return array_merge(parent::toArray(), [
            'isGlobal' => $this->isGlobal(),
            'globalPosition' => $this->globalPosition(),
        ]);
    }
}

Now create a global block by extending your custom BaseBlock:

app/Blocks/HeaderBlock.php
<?php

namespace App\Blocks;

class HeaderBlock extends BaseBlock
{
    protected bool $isGlobal = true;
    protected string $globalPosition = 'before';

    public function name(): string
    {
        return 'Header';
    }

    public function schema(): array
    {
        return [
            'logo' => 'string',
            'navigation' => 'array',
        ];
    }
}

Note: Set $globalPosition to 'before' for headers/navigation or 'after' for footers.

Theme Switching

Switch themes dynamically based on user preference, tenant, or any other criteria:

Controller or Middleware
use InertiaThemes\Facades\InertiaThemes;

// Set theme by class
InertiaThemes::setTheme(DarkTheme::class);

// Set theme by name
InertiaThemes::setThemeByName('dark');

// Get current theme
$theme = InertiaThemes::currentTheme();

// Get all registered themes
$themes = InertiaThemes::getThemes();

Block Areas

Areas allow you to organize blocks into logical sections of your page:

app/Blocks/HeroBlock.php
class HeroBlock extends BaseBlock
{
    protected string $area = 'content';

    // Available areas: 'header', 'content', 'sidebar', 'footer'
}

API Reference: BaseTheme

Method Return Description
name() string Theme display name
colors() array Theme color palette
fonts() array Typography settings
settings() array Additional theme settings
toArray() array Serialize theme for frontend

API Reference: BaseBlock

Method Return Description
name() string Block display name
schema() array Content field definitions
defaults() array Default field values
component() string Frontend component path
toArray() array Serialize block for frontend

API Reference: InertiaThemes Facade

Method Description
setTheme($class) Set the active theme by class
setThemeByName($name) Set the active theme by name
currentTheme() Get the current theme instance
getThemes() Get all registered themes
renderBlocks($blocks) Prepare blocks for frontend rendering
registerTheme($class) Register a theme class