Themes Development

Introduction

Themes are essential for a website as they define its entire appearance. Dozens of ready-to-use themes are available on the market. However, you can also create your own themes to tailor your website to your preferences.

Installing Azuriom locally is highly recommended to simplify theme development. When Azuriom is installed locally, debug mode can be enabled for easier development, by editing the following lines in the .env file:

APP_ENV=local
APP_DEBUG=true

Creating a Theme

The recommended way to create a theme is to use the following command, which generates the required files:

php artisan theme:create <theme name>

Theme Structure

themes/ <-- Folder containing all installed themes
| example/ <-- ID of the theme
| | theme.json <-- The file containing the theme information
| |  assets/  <-- The folder containing the theme assets (CSS, JS, images, etc.)
| | views/ <-- The folder containing the views of the theme
| | config/
| | | config.blade.php <-- The view containing the configuration form of the theme
| | | rules.php <-- The validation rules for the configuration of the theme
| | config.json <-- The default configuration of the theme

theme.json file

A theme must include a theme.json file at the root of its directory, containing the basic information about the theme.

{
    "id": "example",
    "name": "Example",
    "version": "1.0.0",
    "description": "A great theme.",
    "url": "https://azuriom.com",
    "authors": [
        "Azuriom"
    ],
    "azuriom_api": "1.2.0"
}

Identifier

A theme must have a unique id that contains only numbers, lowercase letters, and hyphens. The id is used to identify the theme within the system and must match the name of the theme’s folder. For example, a theme named Hello World might have the id hello-world.

Views

Azuriom is based on Laravel and uses the Blade template engine to create views. For more information on Blade, see the Blade documentation.

When rendering a view, Azuriom first searches for it within the theme; if not found, it then looks for it in Azuriom or in a plugin. Parts of the views can be located in different places, allowing you to customize the default layout of Azuriom while retaining the default content of a view.

Layout

The main layout for Azuriom is located in the file views/layouts/base.blade.php. This layout contains the basic structure of the website, including the header, footer, and page content (displayed using the @yield('content') directive). All pages except the home page extend a sub-layout, views/layouts/app.blade.php, which extends the base layout.

Components can be included in the layout using the @include directive; for example, to include the navigation bar:

@include('elements.navbar')

It is highly recommended not to modify views other than the layout, components (such as the navbar), and the homepage, as doing so may cause compatibility issues with plugins and future updates.

Instead, CSS should be used to customize the appearance of the site.

Theme Color

The default primary color of Bootstrap is blue (#0d6efd), but Azuriom provides an easy way to change it by adding the following line in the <head> section of the layout (after the Bootstrap CSS file), where $color is the hexadecimal color value:

@include('elements.theme-color', ['color' => $color])

Assets

Azuriom is based on Bootstrap 5 to ensure a consistent design across the website and its plugins, and to benefit from a variety of great built-in components and utilities. For more information on Bootstrap, see the Bootstrap documentation.

You can add new CSS/JavaScript files and images to the theme by placing them in its assets directory. These files can then be included in the layout using the theme_asset function, which generates the correct URL for each asset.

<link href="{{ theme_asset('css/style.css') }}" rel="stylesheet">

Please avoid using jQuery in your theme, as it is not included in Azuriom by default and can easily be replaced by vanilla JavaScript.

Configuration

Themes can include a configuration form that allows users to easily customize the theme from the admin panel.

The configuration form is created in a Blade view file called config.blade.php (located in the theme’s config directory), which contains the fields required to configure the theme.

<form action="{{ route('admin.themes.update', $theme) }}" method="POST">
    @csrf

    <div class="form-group">
        <label for="discordInput">{{ trans('theme::messages.discord') }}</label>
        <input type="text" class="form-control @error('discord') is-invalid @enderror" id="discordInput" name="discord" required value="{{ old('discord', theme_config('discord')) }}">

        @error('discord')
        <span class="invalid-feedback" role="alert"><strong>{{ $message }}</strong></span>
        @enderror
    </div>

    <button type="submit" class="btn btn-primary">
        <i class="bi bi-save"></i> {{ trans('messages.actions.save') }}
    </button>
</form>

To be able to save the configuration, the form must be submitted to the admin.themes.update route, with the theme as a parameter. The configuration must be validated by providing a rules.php file in the theme’s config directory, which contains the validation rules:

<?php

return [
    'discord' => 'required|string',
];

The validation rules are the same as the Laravel validation rules, see the Laravel documentation for more information.

To set a default configuration for the theme, create a config.json file in the theme’s root directory containing the default configuration in JSON format.

{
    "discord": "https://azuriom.com/discord"
}

Finally, you can access the configuration in your views using the theme_config helper function, which accepts the configuration key as a parameter.

<a href="{{ theme_config('discord') }}">Discord</a>

Translations

Azuriom is fully translated into several languages, and themes can also be translated using Laravel’s translation system. Translations for a theme are stored in its lang directory, with one subdirectory per language containing PHP files with the translations.

For example, an English translation file would be stored in lang/en/messages.php:

<?php

return [
    'hello' => 'Hello',
];

A translation can then be displayed in a view using the trans function with the theme:: prefix:

<p>{{ trans('theme::messages.hello') }}</p>

To translate a boolean, you can use the trans_bool function, which returns “Yes” or “No” in English: {{ trans_bool($boolean) }}. A date can be formatted with the format_date or format_date_compatct functions, which return the date formatted with the current language: format_date($date).

For more information on translations, see the Laravel documentation.

Common Functions

Azuriom provides several functions to facilitate theme development and ensure consistency across the website:

Function Description
site_name(): string Return the site name, as defined in the settings
site_logo(): string Returns the URL of the logo as defined in the settings
favicon(): string Returns the URL of the favicon as defined in the settings
format_date(Carbon $carbon): string Formats a date according to the current language. The $carbon argument must be an instance of Carbon\Carbon
money_name(): string Returns the name of the website’s currency
format_money(float $amount): string Returns $amount formatted using the website’s currency
dark_theme(bool $defaultDark = false): bool Returns true if the current user is using the dark theme, false otherwise.
hex2rgb(string $hex): [int, int, int] Converts the $hex color to an array containing the R,G,B values as integers.
color_contrast(string $hex): string Returns either #000 (black) or #fff (white), whichever provides higher contrast for the given $hex color
trans(string $key): string Return the translation corresponding to the given $key
trans_bool(bool $value): string Returns the translation of the given boolean value. In English, this is ‘Yes’ or ‘No’
auth()->user(): \Azuriom\Models\User Returns the authenticated user, or null if no user is authenticated

Laravel provides a lot of functions to facilitate the development of a website, for more information, see the Laravel documentation.

Blade Directives

Azuriom and Laravel provide several Blade directives to facilitate theme development:

Directive Description
@plugin('<plugin id>') ... @endplugin Includes the enclosed code only if the plugin with the specified id is enabled
@route('<route'>) ... @endroute Includes the enclosed code only on the specified route
@auth ... @endauth Includes the enclosed code only if the user is authenticated
@guest ... @endguest Includes the enclosed code only if the user is not authenticated
@can('<permission>') ... @endcan Includes the enclosed code only if the user has the given permission