Skip to content

Themes

Themes include layouts, templates, styles, frontend code and translations (i18n).

By default, the frontend area uses the Lux theme, while the backend area uses the Hadron theme. A different theme can be used for both areas, although using Hadron for the backend area is recommended.

Themes support multiple inheritance of layouts and templates. Meaning if a theme has a parent theme defined and a layout or template is missing, it will be loaded from the parent theme or the parent's parent etc.

Note

Both Lux and Hadron use Bootstrap 5. If you don't want to depend on Bootstrap and/or you're working on a fully custom design, you may not want to inherit such a theme. You can always build a standalone theme without a parent.

Create a theme


Theme file

design/Vendor/ThemeName/Theme.php
<?php

declare(strict_types=1);

namespace Vendor\ThemeName;

use Amarant\Framework\Contract\Module\ThemeInterface;
use Amarant\Framework\Data\DataObject;
use Amarant\Framework\Data\View\Theme\BuildContext;
use Amarant\Framework\Module\AbstractTheme;
use Override;

final class Theme extends AbstractTheme
{
    #[Override] public function name(): string
    {
        // (1)
        return 'Vendor_ThemeName';
    }

    #[Override] public function getThemeType(): string
    {
        // (2)
        return ThemeInterface::TYPE_FRONTEND;
    }

    #[Override] public function build(BuildContext $buildContext): void
    {
        // (3)
        $buildContext->addAliasResolve( // (4)
            "{find: '@fortawesome', replacement: path.resolve(__dirname, 'node_modules/@fortawesome')}"
        );

        // (5)
        $buildContext->addPlugin('some-plugin');
    }

    #[Override] public function complete(BuildContext $buildContext): void
    {
        // do something when theme build completes
    }

    public function defaults(): DataObject
    {
        return new DataObject(
            [
                // (6)
                'parent' => 'Amarant_Lux',
                // (7)
                'inherit_css' => false,
                // (8)
                'inherit_js' => false,
                // (9)
                'inherit_entrypoints' => false,
            ]
        );
    }
}
  1. Theme name.
  2. Theme area.
  3. Add imports to Vite build file.
  4. Add Vite aliases.
  5. Add Vite plugins.
  6. Specify a parent theme.
  7. Inherit parent themes CSS entrypoint files (theme.css, theme.scss) - default is true
  8. Inherit parent themes JS entrypoint files (theme.js) - default is true
  9. Inherit parent themes bootstrap files (bootstrap.js) - default is true

Auto imports

These files will be automatically imported if found in the theme directory:

  • theme.ts or theme.js
  • theme.scss or theme.css

Note

To use only templates and layouts of a parent theme without including its CSS and JS, you can set the --inherit-entry-points to 0 when running the build command.

Bootstrap file

The bootstrap file must exist and return a function, even an empty one.

design/Vendor/ThemeName/bootstrap.js
1
2
3
4
5
const boot = () => {
    // your theme's bootstrap code that will run on every request on the frontend
};

export default boot;

Stylesheets

The email and print stylesheets must exist under the theme's root folder:

web/css/print.css
web/css/email.css

These will be included when creating PDF content or email content.

Preprocessing

The theme build preprocessing will generate a new theme bootstrap file, where it includes all auto imports, bootstraps each application module and finally calls the bootstrap code from design/Vendor/ThemeName/bootstrap.js.

This file then becomes the input in the Vite build configuration.

Application module aliases


All aliases should automatically be resolved and created in Vite configuration and jsconfig/tsconfig.json files.

So in your code you can just import using aliases, like so:

import {baseStore} from "@AmarantFramework/app/store/store";
import {confirmation} from "@AmarantUi/js/notifier";
import {t} from "@AmarantUi/js/i18n";

Static files


A theme can have static files that are copied to the build directory. They are automatically hashed and resolved when used from a template.

This means you can add this in a template:

<img class="logo" src="{{ store_url(theme_static_asset('page/logo.png')) }}" alt="logo"/>

Which will result in something like this:

<img class="logo" src="/static/assets/themes/Amarant_Lux/page/logo-1671533e071292aa2e3e0a9c6a3959c9.png" alt="logo"/>

If a subdirectory web/static exists in your theme, all files will be automatically copied to the build directory.

Note

Static files are not copied in development mode. You have to make a production build for that to happen.

Unhashed files

Copy your files to web/static-unhashed instead to avoid hashing.

This means when you add this in a template:

<img class="logo" src="{{ store_url(theme_static_asset('page/logo.png')) }}" alt="logo"/>

It will result in this:

<img class="logo" src="/static/assets/themes/Amarant_Lux/page/logo.png" alt="logo"/>

Theme static files referencing

To reference static files in CSS/SCSS files, add an alias in the theme build method:

design/Vendor/ThemeName/Theme.php
1
2
3
4
5
#[Override] public function build(BuildContext $buildContext): void
{
    $iconsPath = dirname(__FILE__) . '/web/static/icons';
    $buildContext->addAliasResolve("{find: '@vendorthemeicons', replacement: '$iconPath'}"   
}

Then use something like this in your style:

background-image: url("@vendorthemeicons/some-icon.svg");

You could, of course, add an alias to the whole static directory of the theme like this:

design/Vendor/ThemeName/Theme.php
1
2
3
4
5
#[Override] public function build(BuildContext $buildContext): void
{
    $themeStaticPath = dirname(__FILE__) . '/web/static';
    $buildContext->addAliasResolve("{find: '@vendorthemestatic', replacement: '$themeStaticPath'}"   
}

And then use it like this:

background-image: url("@vendorthemestatic/icons/some-icons.svg");

Build


Development mode with hot reload

php bin/ama view:theme:build frontend # (1)

php bin/ama view:theme:build backend  # (2)
  1. Build using the frontend area theme.
  2. Build using the backend area theme.

Production

php bin/ama view:theme:build frontend --build-mode=build # (1)

php bin/ama view:theme:build backend --build-mode=build  # (2)

php bin/ama view:theme:build frontend --build-mode=build --build-all  # (3)

php bin/ama view:theme:build backend --build-mode=build --build-all  # (4)
  1. Build using the frontend area theme.
  2. Build using the backend area theme.
  3. Build all registered frontend themes.
  4. Build all registered backend themes.

Command line options

--theme-name

Optionally specify a theme you want to build/develop. Default theme for an area will be used if no theme name is specified.

Default: Current area theme

--inherit-entry-points

Inherit entrypoints (bootstrap.js) from all parent themes.

Default: true