Multi-theme

How to enable/configure multi-theming in your Vactory project


Vactory 4 Next has pre-configured support for multiple themes since it is a large-scale website. In this section, you will learn about the folder structure for multi-themes and how to set up multiple custom themes for your project.

Folder Structure

In the past, when we had a Single Shared Layout in Vactory 4 Next, we would call the Layout Component from components/global/Layout.jsx inside pages/_app.jsx

Now, we have implemented a new structure specifically designed for multi-themes. Inside your YOUR_WORKSPACE/themes directory, you will find all the themes for your projects. The main theme is named default which is your default theme, you might also find other themes such as dark & amp, but for now let's focus on default theme and break it down.

If you examine the structure of the default theme (or any other theme except the AMP theme), you will notice that it consists of four files:

  • Layout.jsx: This is where we define our custom Layout file.
  • index.js: A file used to export the Layout (since we are utilizing Path Aliases).
  • tailwind.config.js: The Tailwind CSS configuration file for this theme.
  • theme.css: A CSS file specific to this theme.

How Multi-theme functionality works

To comprehend how Multitheme works, we need to examine the following aspects:

Files in the "pages" Folder

Each file inside the /pages folder should include the following function to retrieve the selected theme for that specific page.

pages/search.jsx

Search.getLayout = function getLayout(page, theme) {
const Layout = loadThemeLayout(theme)
return <Layout {...page.props}>{page}</Layout>
}

app.jsx file's folder

which is _app.jsx, this file handles the functionality to render the selected theme's Layout using the following component:

_app.jsx

const Layout = ({ getLayout, Component, pageProps, theme }) => {
return getLayout(<Component {...pageProps} />, theme)
}

We call the above component within our App component, which accepts the following arguments:

  • getLayout

This property can be obtained using the following logic:

const getLayout = Component.getLayout ?? ((page) => page)

Use the Layout defined at the page, for example, if pages/search.jsx has a getLayout function, it will return the associated theme. If the function is not present, the page will be displayed without a custom theme.

  • Component: Represents the page

  • pageProps: Represents the page props

  • theme: Represents the page theme which we obtain using the following logic:

_app.jsx

const theme = isAmp ? "amp" : pageProps?.node?._theme || "default"

The above line of code returns amp if we are in AMP, otherwise it returns the theme specified for the page if selected, or default if not which is the default theme's name.

Adding New Theme

The following steps shows you how to add a new theme ( let's call it skyblue ) :

  • In the YOUR_WORKSPACE/themes folder, create a new folder called skyblue. This folder name will be used as the theme's ID in the back office.

  • Create a Layout.jsx file (It should look similar to the default Layout.jsx file, except if you want to add or remove something such as regions).

  • Create a tailwind.config.js file. This file will contain your TailwindCSS configuration, such as colors, fonts, breakpoints, etc.

  • Create a theme.css file and add the necessary styling to it.

    ⚠️
    Don't forget to import your tailwind.config.js file in this css file.
  • Create an index.js file to export you Layout.jsx from it.

  • Now, go to YOUR_WORKSPACE/themes/.runtime.js and:

  1. Dynamically import your new theme's Layout:

.runtime.js

import dynamic from "next/dynamic"
import { Layout as LayoutAmp } from "@/themes/amp"
const LayoutDefault = dynamic(() => import("@/themes/default").then((mod) => mod.Layout))
const LayoutAlt = dynamic(() => import("@/themes/alt").then((mod) => mod.Layout))
const LayoutDark = dynamic(() => import("@/themes/dark").then((mod) => mod.Layout))
const LayoutSkyBlue = dynamic(() => import("@/themes/skyblue").then((mod) => mod.Layout))
  1. Add your imported theme to THEMES object:

.runtime.js

const THEMES = {
amp: LayoutAmp,
alt: LayoutAlt,
default: LayoutDefault,
dark: LayoutDark,
skyblue: LayoutSkyBlue,
}

Et Voila! Your theme is ready to be used 🎉✨

⚠️
Make sure the following patch has been applied to your project, as it fixes some problems related to multitheming `patches/next+13.1.6.patch`

Your folder structure should look like this:

apps
|------ YOUR_WORKSPACE
|------|------ themes
|------|------|------ skyblue
|------|------|------|------ Layout.jsx
|------|------|------|------ index.js
|------|------|------|------ theme.css
|------|------|------|------ tailwind.config.js

The last step is to apply your theme to a specific page, content type, language or user role. Check the following Loom video to learn how to da that fron the backoffice:

AMP theme

The AMP theme is distinct and differs from the other themes, as we need to add rules/plugins to remove unnecessary functionalities such as "!important" in CSS rules, pseudo-elements, etc.

AMP theme folder structure looks like this:

apps
|------ YOUR_WORKSPACE
|------|------ themes
|------|------|------ amp
|------|------|------|------ Layout.jsx
|------|------|------|------ index.js
|------|------|------|------ theme.css
|------|------|------|------ tailwind.config.js
|------|------|------|------ postcss.config.js
|------|------|------|------ postcss-plugins
|------|------|------|------|------ remove-important
|------|------|------|------|------ remove-pseudo-elements.js
|------|------|------|------|------ remove-quotes-attr.js

As you can see above, the new folder/files contain PostCSS plugins that help in removing specific CSS rules.

But why do we have to do that ?

We may need to remove or modify certain CSS rules in AMP (Accelerated Mobile Pages) for several reasons:

  • Performance optimization: AMP focuses on delivering fast and optimized mobile experiences. By removing unnecessary CSS rules, we can reduce the file size and improve the loading speed of AMP pages.

  • Compliance with AMP guidelines: AMP has specific guidelines and restrictions to ensure a consistent and reliable user experience across different devices and platforms. Removing certain CSS rules helps to adhere to these guidelines and ensures that the AMP pages meet the required standards.

  • Eliminating potential conflicts: Some CSS rules may conflict with the functionality or design principles of AMP. By removing or modifying these conflicting rules, we can prevent layout issues, rendering problems, or unexpected behavior in AMP pages.

  • Simplifying the styling approach: AMP encourages a simplified and efficient approach to styling. Removing unnecessary CSS rules helps to maintain a clean and minimalistic stylesheet, which aligns with the lightweight and focused nature of AMP.

Overall, removing specific CSS rules in AMP aims to improve performance, ensure compliance, avoid conflicts, and promote a streamlined and optimized mobile browsing experience.

Got it ? If the answer is yes, let's delve deeper into AMP in Vactory Next and explore additional use cases.