Skip to content

Child Theme Development ​

Child themes allow you to customize an existing theme without modifying its original files. This approach makes it easy to update the parent theme while preserving your customizations.

Overview ​

A child theme inherits all functionality, assets, and views from its parent theme. You only need to include the files you want to modify or add.

Benefits:

  • Safe updates: Parent theme can be updated without losing customizations
  • Minimal code: Only override what you need to change
  • Easy maintenance: Clear separation between original and custom code
  • Multiple variations: Create different theme variants from one parent

Creating a Child Theme ​

Step 1: Copy Parent Theme ​

The simplest way to create a child theme is to copy the parent theme folder:

bash
# Copy the parent theme to a new folder
cp -r platform/themes/shofy platform/themes/shofy-custom

Step 2: Update theme.json ​

Edit platform/themes/shofy-custom/theme.json:

json
{
    "id": "botble/shofy-custom",
    "name": "Shofy Custom",
    "namespace": "Theme\\ShofyCustom\\",
    "author": "Your Name",
    "url": "https://yoursite.com",
    "version": "1.0.0",
    "description": "Custom child theme based on Shofy",
    "required_plugins": ["ecommerce"]
}

Important

  • Change the id to a unique value
  • Change the name to your theme name
  • Update the namespace to match (use PascalCase, no hyphens)

Step 3: Configure Inheritance ​

Edit platform/themes/shofy-custom/config.php:

php
<?php

use Botble\Theme\Theme;

return [
    'inherit' => 'shofy',  // Parent theme folder name

    'events' => [
        'beforeRenderTheme' => function (Theme $theme): void {
            // Add your custom assets
            $theme->asset()->usePath()->add('custom-theme', 'css/theme.css');
        },
    ],
];

For a minimal child theme, you can remove most files and keep only:

platform/themes/shofy-custom/
├── assets/               # Your custom assets (if any)
├── config.php            # Required - with 'inherit' setting
├── partials/             # Only partials you want to override
├── views/                # Only views you want to override
├── public/               # Compiled public assets
├── screenshot.png        # Theme screenshot for admin
└── theme.json            # Required - theme metadata

Step 5: Activate the Theme ​

  1. Go to Admin → Appearance → Themes
  2. Find your child theme
  3. Click Activate

Or use the command line:

bash
php artisan cms:theme:activate shofy-custom

Theme Inheritance Mechanism ​

When a theme has 'inherit' => 'parent-theme' in its config, Thesky9 CMS:

  1. First looks for views/partials in the child theme
  2. Falls back to the parent theme if not found
  3. Applies parent theme's events before child theme's events
php
// In Theme.php - simplified view lookup
$hints[] = platform_path($childThemePath);   // First priority
$hints[] = platform_path($parentThemePath);  // Fallback

Overriding Views ​

Override a Partial ​

To override a partial, create the same file path in your child theme:

Parent: platform/themes/shofy/partials/header.blade.phpChild: platform/themes/shofy-custom/partials/header.blade.php

blade
{{-- platform/themes/shofy-custom/partials/header.blade.php --}}
<header class="custom-header">
    {{-- Your custom header content --}}
</header>

Override a View ​

Similarly for views:

Parent: platform/themes/shofy/views/page.blade.phpChild: platform/themes/shofy-custom/views/page.blade.php

Override Shortcode Templates ​

To customize shortcode appearance:

platform/themes/shofy-custom/partials/shortcodes/
├── ecommerce-categories/
│   ├── index.blade.php
│   └── grid.blade.php
└── ecommerce-product-groups/
    └── tabs.blade.php

Customizing Assets ​

Adding Custom CSS/JS ​

In config.php:

php
'events' => [
    'beforeRenderTheme' => function (Theme $theme): void {
        // Add custom CSS
        $theme->asset()->usePath()->add('custom-styles', 'css/custom.css');

        // Add custom JS (in footer)
        $theme->asset()->container('footer')->usePath()->add(
            'custom-scripts',
            'js/custom.js',
            attributes: ['defer']
        );
    },
],

Overriding Parent Assets ​

php
'beforeRenderTheme' => function (Theme $theme): void {
    // Remove parent asset
    $theme->asset()->remove('parent-style');

    // Add your version
    $theme->asset()->usePath()->add('parent-style', 'css/my-version.css');
},

Working with Theme Options ​

Child themes inherit all parent theme options. To customize default values:

php
'beforeRenderTheme' => function (Theme $theme): void {
    $theme->partialComposer('header.*', function (View $view): void {
        // Override default theme option values
        $headerBackgroundColor = theme_option('header_background_color', '#ffffff');
        $headerTextColor = theme_option('header_text_color', '#000000');

        $view->with(compact('headerBackgroundColor', 'headerTextColor'));
    });
},

Minimal Child Theme Example ​

Here's a complete minimal child theme structure:

platform/themes/shofy-beauty/
├── assets/
│   └── css/
│       └── theme.css           # Custom styles
├── partials/
│   ├── footer.blade.php        # Overridden footer
│   └── section-title.blade.php # Overridden section title
├── public/
│   └── css/
│       └── theme.css           # Compiled CSS
├── config.php                  # Theme configuration
├── screenshot.png              # 1200x900px recommended
├── theme.json                  # Theme metadata
└── webpack.mix.js              # Asset compilation (optional)

config.php:

php
<?php

use Botble\Theme\Theme;
use Illuminate\View\View;

return [
    'inherit' => 'shofy',

    'events' => [
        'beforeRenderTheme' => function (Theme $theme): void {
            $theme->asset()->usePath()->add('shofy-theme', 'css/theme.css');

            $theme->partialComposer('header.*', function (View $view): void {
                $headerTopBackgroundColor = theme_option('header_top_background_color', '#fff');
                $headerTopTextColor = theme_option('header_top_text_color', '#010f1c');
                $headerMainBackgroundColor = theme_option('header_main_background_color', 'transparent');
                $headerMainTextColor = theme_option('header_main_text_color', '#010f1c');

                $view->with(compact(
                    'headerTopBackgroundColor',
                    'headerTopTextColor',
                    'headerMainBackgroundColor',
                    'headerMainTextColor'
                ));
            });
        },
    ],
];

theme.json:

json
{
    "id": "botble/shofy-beauty",
    "name": "Shofy Beauty",
    "namespace": "Theme\\ShofyBeauty\\",
    "author": "thesky9",
    "url": "https://thesky9.com",
    "version": "1.0.0",
    "description": "Beauty variant of Shofy theme",
    "required_plugins": ["ecommerce"]
}

Including Parent Partials ​

You can include parent theme partials within your overridden views:

blade
{{-- Call a different style from parent theme --}}
{!! Theme::partial('footer.style-2') !!}

{{-- Include parent theme's original partial --}}
@include(Theme::getThemeNamespace('partials.section-title-inner'))

Building Assets ​

If your child theme has custom SCSS/JS, ship a vite.build.mjs inside the theme directory. The project-wide runner discovers it automatically.

platform/themes/my-child-theme/vite.build.mjs:

js
export default {
    js:   [{ src: 'assets/js/theme.js',     out: 'theme.js' }],
    sass: [{ src: 'assets/sass/theme.scss', out: 'theme.css' }],
}

Build from the project root:

bash
# Development (unminified)
npm run dev

# Production (minified + ships compiled assets inside the theme's public/ folder)
npm run production

For the full descriptor spec, SFC Vue support, RTL CSS variants, and migrating from the old Laravel Mix setup, see Asset Compilation (Vite).

Current Limitations ​

WARNING

The theme package currently supports view file inheritance only. These are not inherited:

  • PHP class files (functions, helpers)
  • Language files
  • Widget configurations
  • Some asset paths

For complex customizations beyond view overrides, consider:

  • Registering custom functions in your child theme's functions/functions.php
  • Using hooks and filters to modify behavior
  • Creating custom plugins for major functionality

Troubleshooting ​

Theme Not Appearing ​

  1. Verify theme.json syntax is valid JSON
  2. Check file permissions (755 for folders, 644 for files)
  3. Clear cache: php artisan cache:clear

Views Not Overriding ​

  1. Ensure file path matches exactly (case-sensitive)
  2. Clear view cache: php artisan view:clear
  3. Verify 'inherit' is set correctly in config.php

Assets Not Loading ​

  1. Run php artisan cms:theme:assets:publish
  2. Check asset paths in browser developer tools
  3. Verify public_theme_name config if using custom public folder

Parent Theme Updates ​

After updating the parent theme:

  1. Check for breaking changes in views you've overridden
  2. Compare your overridden files with new parent versions
  3. Test thoroughly before deploying

Best Practices ​

  1. Override minimally - Only copy files you need to change
  2. Document changes - Comment why each file is overridden
  3. Version control - Track child theme separately from parent
  4. Test updates - Always test parent theme updates in staging
  5. Use hooks - Prefer hooks over view overrides when possible
  6. Keep screenshot - Update screenshot to reflect child theme appearance