# Theme Development

# Quick Start

Sample Theme Repository: https://github.com/beikeshop/beikeshop-sample-theme

You can download the sample theme first and refer to its directory structure and code for development:

# Download the sample theme
git clone https://github.com/beikeshop/beikeshop-sample-theme.git

# Copy the SampleTheme folder to the plugins/ directory of beikeshop
# Then modify and develop according to the instructions in this document

# I. Theme Architecture Overview

BeikeShop supports developing template themes in the form of plugins. The same functionality can have completely different user interfaces.

# Template Loading Mechanism

The system adopts the following template loading strategy:

  1. Priority is given to the enabled theme template
  2. If a file does not exist in the enabled template, it falls back to the default template file under the themes/default directory

This means you only need to override the template files you want to customize; you do not need to copy all files.

# Core Directory Structure

beikeshop/
├── plugins/                          # Plugin directory
│   └── YourTheme/                    # Your template plugin (folder name, PascalCase)
│       ├── config.json               # Plugin configuration (required)
│       ├── Bootstrap.php             # Plugin bootstrap file (required)
│       ├── Resources/                # Development source files (SCSS/JS)
│       │   └── beike/shop/your_theme/
│       │       ├── css/
│       │       │   ├── bootstrap/bootstrap.scss
│       │       │   └── app.scss
│       │       └── js/
│       │           └── app.js
│       ├── Themes/                   # Blade template files
│       │   └── your_theme/
│       │       ├── layout/
│       │       │   └── master.blade.php
│       │       ├── home.blade.php
│       │       └── ...
│       ├── Static/                   # Static assets (published to public)
│       │   ├── image/
│       │   │   ├── logo.png          # Plugin icon
│       │   │   └── theme.jpg         # Theme preview image
│       │   └── public/
│       │       └── build/beike/shop/your_theme/
│       │           ├── css/
│       │           │   ├── bootstrap.css  # Compiled CSS
│       │           │   └── app.css
│       │           └── js/
│       │               └── app.js
│       └── Seeders/                  # Demo data (optional)
│           └── ThemeSeeder.php
├── themes/                           # System template directory (auto-copied during installation)
│   └── your_theme/                   # Copied from plugins/YourTheme/Themes
└── public/                           # Public resource directory (auto-copied during installation)
    └── plugin/your_theme/            # Copied from plugins/YourTheme/Static

# II. Creating a Theme Plugin

# 2.1 Create the Plugin Directory

Create your template folder under the plugins/ directory, for example, Fashion:

mkdir plugins/Fashion

# 2.2 Create config.json

Create config.json in the plugin root directory. This is the core configuration file for the plugin:

{
    "code": "fashion",
    "name": {
        "zh_cn": "Fashion Theme",
        "en": "Fashion Theme"
    },
    "description": {
        "zh_cn": "A fashionable e-commerce theme",
        "en": "A fashionable e-commerce theme"
    },
    "type": "theme",
    "version": "v1.0.0",
    "icon": "/image/logo.png",
    "theme": "/image/theme.jpg",
    "author": {
        "name": "Your Name",
        "email": "your@email.com"
    }
}

Important Field Descriptions:

Field Description Example
code Template unique identifier, lowercase + underscore naming fashion, my_theme
name Template name, supports multiple languages {"zh_cn": "Fashion Theme", "en": "Fashion Theme"}
type Must be theme theme
icon Plugin icon path, relative to the Static/ directory, size 500×500 /image/logo.png
theme Template preview image path, relative to the Static/ directory, size 740×856 /image/theme.jpg

# 2.3 Create Bootstrap.php

Create Bootstrap.php in the plugin root directory. This is the plugin bootstrap file:

<?php
namespace Plugin\Fashion;

class Bootstrap
{
    public function boot()
    {
        // Add hook logic here
        // For example: add custom CSS/JS to the page
        add_hook_blade('layout.header.code', function ($callback, $output, $data) {
            return view('fashion::shop.custom-code');
        });
    }
}

Naming Rules:

  • namespace must be Plugin\YourPluginFolderName (PascalCase)
  • Class name must be Bootstrap
  • Must contain the boot() method

# III. Developing Template Files

# 3.1 Blade Template Files

Template files are placed under the Themes/ directory. The directory structure should be consistent with themes/default.

Development Workflow:

  1. Copy the template files you need to modify from themes/default to your plugin directory:

    themes/default/home.blade.php
    → plugins/Fashion/Themes/fashion/home.blade.php
    
  2. Only modify the files you need to customize; files that don't need modification can remain default

  3. System loading order:

    • First look for themes/fashion/xxx.blade.php
    • If it doesn't exist, fall back to themes/default/xxx.blade.php

Example Directory Structure:

plugins/Fashion/Themes/fashion/
├── layout/
│   ├── master.blade.php      # Main layout (optional override)
│   ├── header.blade.php      # Header (optional override)
│   └── footer.blade.php      # Footer (optional override)
├── home.blade.php            # Homepage
├── category.blade.php        # Category page
├── product/
│   └── product.blade.php     # Product detail page
└── cart/
    └── cart.blade.php        # Shopping cart page

# 3.2 SCSS/CSS Styles

Style source files are placed under Resources/beike/shop/your_theme/css/.

Directory Structure:

plugins/Fashion/Resources/beike/shop/fashion/css/
├── bootstrap/
│   └── bootstrap.scss        # Bootstrap custom variables
├── app.scss                  # Main style file
├── global.scss               # Global styles
├── header.scss               # Header styles
├── footer.scss               # Footer styles
└── home.scss                 # Homepage styles

app.scss Example:

// Import bootstrap variables
@import 'bootstrap/bootstrap';

// Import module styles
@import 'global';
@import 'header';
@import 'footer';
@import 'home';

# 3.3 JavaScript

JS source files are placed under Resources/beike/shop/your_theme/js/.

Directory Structure:

plugins/Fashion/Resources/beike/shop/fashion/js/
├── app.js                    # Main JS file
├── common.js                 # Common functions
├── header.js                 # Header interactions
└── product.js                # Product page interactions

app.js Example:

import './common';
import './header';
import './product';

# IV. Compilation Configuration (Key Point)

# 4.1 Configure webpack.mix.js

This is the most critical step. When developing a new template, you must configure the webpack.mix.js file.

Open the webpack.mix.js file in the project root directory, find the commented-out template compilation code segment (around lines 30-55), uncomment it and modify themeFileName to your plugin folder name (PascalCase):

/* If developing a new theme, uncomment the following code and set themeFileName to your theme folder name */
const themeFileName = 'Fashion';  // ← Modify to your plugin folder name (PascalCase)
const themeCode = themeFileName.replace(/([A-Z])/g,"_$1").toLowerCase().replace(/^_/,'');

// Copy template blade files to the themes directory
if (!mix.inProduction()) {
  mix.copy(`plugins/${themeFileName}/Themes`, 'themes');
}

// Compile template scss/js to public/build
mix.sass(`plugins/${themeFileName}/Resources/beike/shop/${themeCode}/css/bootstrap/bootstrap.scss`, `public/build/beike/shop/${themeCode}/css/bootstrap.css`)
.then(() => {
  fs.copyFileSync(`public/build/beike/shop/${themeCode}/css/bootstrap.css`, `plugins/${themeFileName}/Static/public/build/beike/shop/${themeCode}/css/bootstrap.css`);
});

mix.sass(`plugins/${themeFileName}/Resources/beike/shop/${themeCode}/css/app.scss`, `public/build/beike/shop/${themeCode}/css/app.css`)
.then(() => {
  fs.copyFileSync(`public/build/beike/shop/${themeCode}/css/app.css`, `plugins/${themeFileName}/Static/public/build/beike/shop/${themeCode}/css/app.css`);
});

mix.js(`plugins/${themeFileName}/Resources/beike/shop/${themeCode}/js/app.js`, `public/build/beike/shop/${themeCode}/js/app.js`)
.then(() => {
  fs.copyFileSync(`public/build/beike/shop/${themeCode}/js/app.js`, `plugins/${themeFileName}/Static/public/build/beike/shop/${themeCode}/js/app.js`);
});

Important Notes:

Variable Description Example
themeFileName Plugin folder name, PascalCase naming Fashion, MyTheme
themeCode Auto-converted code (lowercase + underscore) fashion, my_theme

Conversion Rules:

Fashion    → fashion
MyTheme    → my_theme
Fashion4   → fashion4

# 4.2 Compilation Commands

Development Phase (watch file changes, auto-compile):

npm install          # Required for the first time to install dependencies
npm run watch        # Watch mode, auto-compiles after file modification

Production Environment (minified build):

npm run prod         # Minified compilation of CSS/JS

# 4.3 Compilation Output Description

After compilation, the following files will be automatically generated:

public/build/beike/shop/fashion/
├── css/
│   ├── bootstrap.css
│   └── app.css
└── js/
    └── app.js

At the same time, through the .then() callback, the compiled files will be automatically copied to the plugin's Static/public/build/ directory:

plugins/Fashion/Static/public/build/beike/shop/fashion/
├── css/
│   ├── bootstrap.css
│   └── app.css
└── js/
    └── app.js

# 4.4 ⚠️ Must Confirm Compiled Files Are Synced Before Packaging

This is a critical point that many developers easily overlook!

Before packaging and publishing the template, you must ensure:

  1. The compiled CSS/JS files already exist in the Static/public/build/ directory
  2. These files will be packaged with the plugin, so users will have styles after installation

How to ensure:

  • Method 1 (Recommended): Use the auto-copy function configured in webpack.mix.js

    • Uncomment the template compilation code
    • Run npm run prod
    • Compiled files will be automatically copied to the Static/public/build/ directory
  • Method 2 (Manual): Manually copy compiled files

    • Copy files from public/build/beike/shop/your_theme/
    • Paste to plugins/YourTheme/Static/public/build/beike/shop/your_theme/

If you forget this step, users will have no styles after installing the template!


# V. Installing and Enabling the Template

# 5.1 Install the Template

  1. Go to Admin Panel → Plugin List
  2. Find your template plugin
  3. Click Install

During installation, the system will automatically:

  • Copy Blade templates from the Themes/ directory to themes/your_theme/
  • Copy static assets from the Static/ directory to the corresponding public/ directory

# 5.2 Enable the Template

  1. Go to Admin Panel → DesignTemplate Settings
  2. Find your template and click Enable
  3. Optional: Check "Import Demo Data" (if the template provides Seeders)
  4. Confirm enable

# 5.3 Visit the Storefront

After enabling, visit the storefront to see the effect of the new template.


# VI. Template Data Seeders (Optional)

If your template needs to include demo data (such as homepage layout configuration), you can use Seeders.

# 6.1 Create a Seeder

Create ThemeSeeder.php under the Seeders/ directory:

<?php
namespace Plugin\Fashion\Seeders;

use Beike\Repositories\SettingRepo;
use Illuminate\Database\Seeder;

class ThemeSeeder extends Seeder
{
    public function run()
    {
        $homeSetting = $this->getHomeSetting();
        SettingRepo::update('system', 'base', ['design_setting' => $homeSetting]);
    }

    private function getHomeSetting(): array
    {
        // Return homepage layout configuration
        // Data format references the design_setting value in the settings table
        return [
            // ... your homepage configuration data
        ];
    }
}

# 6.2 How to Get Homepage Configuration Data

  1. Configure the homepage layout in the admin design editor
  2. Go to the database settings table, find the record where name = 'design_setting'
  3. Copy the JSON data from the value field
  4. Use a tool to convert JSON to PHP array: https://uutool.cn/json2php/
  5. Put the converted array into the getHomeSetting() method

# 6.3 Import Data When Enabling

When users enable the template in the admin panel, check the "Import Demo Data" option, and the system will automatically run the Seeder to import data.


# VII. Static Asset Management

# 7.1 Static Directory Structure

plugins/Fashion/Static/
├── image/
│   ├── logo.png          # Plugin icon (displayed in admin plugin list)
│   └── theme.jpg         # Theme preview image (displayed on template settings page)
├── public/
│   └── build/beike/shop/fashion/
│       ├── css/          # Compiled CSS (must include)
│       └── js/           # Compiled JS (must include)
└── catalog/fashion/      # Images used by the template (banner, icon, etc.)
    └── demo/

# 7.2 Accessing Assets

Access static assets in templates:

{{-- Access plugin static files --}}
<img src="{{ plugin_asset('fashion', 'image/logo.png') }}">
<img src="{{ asset('plugin/fashion/catalog/fashion/demo/banner.jpg') }}">

{{-- Access compiled CSS/JS (automatically loaded by the system) --}}
{{ mix('/build/beike/shop/fashion/css/app.css') }}
{{ mix('/build/beike/shop/fashion/js/app.js') }}

# VIII. Packaging and Publishing

# 8.1 Pre-Packaging Checklist

  • [ ] All SCSS/JS have been compiled, and compiled files are in Static/public/build/
  • [ ] logo.png and theme.jpg have been replaced with your own assets
  • [ ] config.json information is complete and accurate
  • [ ] Bootstrap.php namespace is correct
  • [ ] Template file paths are correct (Themes/your_theme/)
  • [ ] Test installation, enable, and switch functions are working properly

# 8.2 Packaging

Package the plugin folder as a ZIP archive:

cd plugins
zip -r Fashion.zip Fashion/

# 8.3 Publishing

  1. Log in to the BeikeShop official website
  2. Go to User Center → Plugin Marketplace
  3. Upload the ZIP package to publish
  4. Other users can purchase and install it from the admin plugin marketplace

# IX. Frequently Asked Questions

# Q1: No styles after template installation?

Cause: The compiled CSS/JS files are not included in the plugin's Static/public/build/ directory.

Solution:

  1. Ensure the template compilation code in webpack.mix.js is uncommented
  2. Run npm run prod to compile
  3. Confirm that compiled files exist under plugins/YourTheme/Static/public/build/

# Q2: Modified SCSS but no changes on the storefront?

Cause: Not recompiled or cache not refreshed after compilation.

Solution:

  1. Use npm run watch in the development phase to listen for auto-compilation
  2. Wait a few seconds after modification for auto-compilation to complete
  3. Refresh the browser (may need force refresh Ctrl+Shift+R)

# Q3: Template file modifications not taking effect?

Cause: Blade template cache not cleared.

Solution:

php artisan view:clear
php artisan cache:clear

# Q4: How to override only some template files?

You don't need to copy all files. The system will first look for files under themes/your_theme/, and if they don't exist, fall back to themes/default/. So you only need to override the files you need to modify.

# Q5: What is the difference between themeFileName and themeCode?

  • themeFileName: Plugin folder name, PascalCase naming, e.g., Fashion
  • themeCode: Template unique identifier, lowercase + underscore, e.g., fashion
  • The two are automatically converted via regex; usually you only need to modify themeFileName

# X. Best Practices

  1. Only override needed files: Don't copy all default template files, only override the ones you need to modify
  2. Keep code clean: Follow the project's existing coding style
  3. Manage versions properly: Modify the version in config.json for each release update
  4. Test multilingual support: Ensure the template displays correctly in different languages
  5. Responsive design: Ensure the template displays well on mobile devices
  6. Performance optimization: Use WebP format for images, compress CSS/JS before publishing
  7. Backup data: Back up existing configuration data before enabling a new template

# Appendix: Naming Convention Quick Reference

Item Naming Rule Example
Plugin folder PascalCase Fashion, MyTheme
config.json code lowercase + underscore fashion, my_theme
namespace Plugin\FolderName Plugin\Fashion
themeCode lowercase + underscore fashion
Resource path lowercase + underscore beike/shop/fashion/css/
Blade file lowercase + underscore home.blade.php