âšī¸Adding Dynamic Layouts to Themes & Modules
Configuring Dynamic Layouts
These instructions are very similar whether you are following the theme or module creator pathway, so both tutorials converge here.
Step 1 - Create the File Structure for Dynamic Layouts
Each Layout gets its own folder in the file structure. It's position in the file structure is affected by its theme and its module.
Most Siteglide layouts actually consist of more than one layout, so Within that folder, you need to create the same number of source files inside your module folder.
How you organise your files into folders within your layout folder is optional, however, you will need to reference these source files' exact paths in the "src" property of the "files" array in the layout config later.
Module creators will normally have multiple theme folders with a single module folder and single layout_config file in each. For example:
Theme creators will normally have only a single theme folder containing multiple module folders to organise layouts accordingly. For Example:
Layouts in the same module but different sub-modules will still share the same module folder. The sorting of sub_modules is done instead based on the layout_config file, see the next section.
If you want to see the format for adding layout source code to the files in this structure, look at step 4. Otherwise, move on to step 2.
Step 2 - Create the Layout Config File
While the actual code for each layout goes in its own file, SiteBuilder also needs Layout Config Files to give it the metadata needed to display and install layouts correctly.
A layout_config file is needed for each theme you want to add layouts for.
Theme creators need only create a single layout_config file for their module. For example, if you're creating a theme, your layout_config file should be at the following path:
modules/module_<module_vanity_id>/private/views/partials/sitebuilder<secret_key_preceded_by_underscore>/theme_<module_vanity_id>/layout_config.liquid
Module creators will need a layout_config file per theme they wish to add their module layouts to. For example if a module creator wants to offer their users both Bootstrap and Flowbite layouts (they would have also set the "extends_themes" key in their module_config to include the same IDs "theme_01" and "theme_02"), they'll need to add files at the following paths:
modules\module_<module_vanity_id>\private\views\partials\sitebuilder<secret_key_preceded_by_underscore>\theme_01\layout_config.liquid
modules\module_<module_vanity_id>\private\views\partials\sitebuilder<secret_key_preceded_by_underscore>\theme_02\layout_config.liquid
You'll see the main difference is that the folder named after the theme will either point at a theme you created or a theme created by someone else, depending if you are a theme or a module creator. The theme folder will also contain folders for layout code files as well as the config file.
Step 3 - Configuring the Layout Config Files
The following example is from a module creator's layout_config file.
Perhaps the most complex and important part of the configuration to pay attention to is the files array. When SiteBuilder installs a layout, it takes a copy of the layout source code you've stored in the private folder and adds those copied files to the marketplace_builder folder where they can be freely read and edited by the module user. It is therefore important to note the difference between the src property which points at the files you add and the dest property that points to where you wish the files to be installed.
Step 4 - Adding the Content to Layout Source Files
Adding Liquid to Layouts using the Raw Tag
In step 1, you created the folder structure for the layouts, but this section shows how you can format the layout code within each file.
It's up to you what kind of Liquid code to add to layouts, but there is one important rule:
Where your layout contains any Liquid code which you wish to render at runtime, you need to wrap it in the `` liquid tags, see https://documentation.platformos.com/api-reference/liquid/introduction#raw. In almost all cases, you can just wrap this tag around your entire layout. Without this tag, Liquid will run at build-time while SiteBuilder is creating your layout, which would most likely mean the Liquid would be rendered to nothing, or to something unexpected.
Important! Once you put raw tags into a layout, the Siteglide-CLI will ignore any errors in your code. So if you have an unexplained file in your layout that is not installing properly, try taking out the raw tags, syncing, then putting them back in. You may discover the error in the CLI.
If you're using VSCode, you can use find & replace to add raw tags to all files in a folder.
![VSCode regex find and replace ((.|\n)*) with $1.]https://res.cloudinary.com/sitegurus/image/upload/v1667563298/modules/module_86/documentation/adding_raw_tags.png
Pagination
Layouts should aim to be self-contained. This often means that Siteglide's default pagination position is too low and it's better to move the pagination higher up in the DOM (so that it has the correct padding after it.)
The recommendation is that you use the following code to position custom pagination:
To use it, the module_user must both set show_pagination: 'false'
on the include tag to remove the default pagination and then set a custom pagination_layout
.
Built-in module module_s2
can be used to add new pagination layouts to a theme.
Adding Settings (Optional)
As well as this rule, there are also some helpful conventions which you can follow when writing layouts. One of these is Layout settings.
The main purpose of Layout settings is to gather together at the top of the file, variables which cannot be handled completely dynamically and require the module user to enter some input to make the layout work as expected. For example, if you've got a link from the layout to another page, there's no way of a layout knowing the context of the site and which URL to link to.
This adds convenience to the user; instead of searching through the layout to find the variables they'll almost certainly want to change, they can look at the top of the layout first.
Here is an example of settings being implemented in a SiteBuilder Layout:
Notes:
Where a layout contains multiple files, the settings block should be placed at the top (under the tag) of the first file that will be outputted, which would normally be called the
wrapper
.The entire settings block should be wrapped between two Liquid comments `
` and ``. 3. Each setting should be preceded by another comment with the name of the setting (6 dashes before and after), then a comment to explain the purpose of the setting. 4. Finally, each setting should contain a Liquid tag to set the variable. This variable's value should be read where needed within the rest of the file and within any other files in the layout which may need to use it. Due to Liquid inheritance, the variable will be available for any files included by the file that contains the setting block.
These conventions help to keep the settings consistent and readable for the module user (and the developer). Following them now will also allow your layouts to take advantage of future improvements when settings are further integrated into the SiteBuilder UI. Watch this space!
Sitebuilder Component IDs (optional)
Another convention we use when building layouts with JavaScript interactivity is the Sitebuilder component ID.
Where JavaScript needs to be given an element query selector in order to make that element interactive, you can normally pass it an element ID. However, you need to think about what would happen if the user added more than one similar (or the same) layout to the page.
Using the following code, we dynamically generate a unique ID for each layout that needs one. Since this is generated by Liquid at runtime, it doesn't matter if the same layout is used twice- the ID will still be unique. This is by convention generated straight after the settings.
Instead of including JS within the layout to capture these variables, it is possible to store the ID in data-attributes and target all the elements at once. This allows your JS to run asynchronously for better performance.
Liquid
JS
Using these conventions from the beginning should help you avoid bugs arising from conflicting IDs.
Nesting or embedding layouts (optional)
In the previous sections, the documentation alluded to nested or embedded layouts. This is an advanced feature of SiteBuilder which allows layouts from one module to embed within them modules from another.
Look back at the example for step 1 to see the file-structure for embedding a testimonials layout within a module layout (the layout folder is "2").
Look back at step 2 to see how the embedded layout is configured.
You also need finally in your Layout code to add the Liquid tag which will include the embedded layout itself.
The main limitation of embedded layouts, is that it's not always possible to know all of the information you'd need to embed a layout successfully. This will depend on context on a case-by-case basis.
One piece of information which you will have which might surprise you however, is the name of the layout. Due to the way we set up the layout config, the embedded layout will have the same layout name as the parent layout (they are installed at the same time!). This means whatever the module-user chooses to name the layout, you will be able to access it! Use the example below:
In this example, the layout_config files array contains a file with the dest: testimonials/list/wrapper
. Since list and wrapper are handled by Siteglide ( you need to add the type: "list"
parameter though), only the "testimonials" part of the path is needed. Any other optional additional folders should also be added to the capture tag. We also prepend the name of the current parent layout. The embedded layout will have been created at the same time, with the same name, so we can reference it using the inherited {{layout}}
variable.
Resetting _top_model
for consistent layout paths
The unusual looking _top_model: nil
parameter is useful for making sure the nested Siteglide tag looks in a consistent location for layouts. Due to legacy reasons, where an `
` tag is nested inside another, Siteglide will look inside the parent module folder for all child module layouts. This is inconsistent with other tags, for example secure zones where Siteglide will look in the child module's folder, so it's easier to use this parameter to tell Siteglide to ignore the parent layout and look in the module folder for the current module. That way you can always store layouts safely accordingly to their own functionality rather than the functionality of the layout they're nested inside.
Preserving the Layout Variable across multiple layers of Liquid
If you're nesting layouts in more than two layers, you may experience a difficulty where the first layer redefines the layout
variable and it's not accessible in layers below. In this case, at the top layer, you should assign a new variable on the very top layer which will reliably not be overwritten:
Datasources
If you wish, you can also make this embedded layout into a datasource! Here we use one of the datasource fields in the parent layout to store Testimonial IDs we can use to filter by.
Troubleshooting Layouts
Check the JSON for each config file validates to correct JSON when you "include" and "output" the file on a test page with Liquid. A comma in the wrong place can invalidate your JSON and cause errors.
If there are missing files in your layout, try temporarily removing the raw tags from that file and syncing with Siteglide-CLI. The raw tags may be causing a syntax erro to go undiscovered.
Check that the raw tags are present in each file.
Check that the number of files listed in the layout_config file matches, or is less than, the number of files in your layout's file structure.
When your layout is working, but you're working on improving the layout's functionality and styling, try using PageBuilder to quickly generate multiple test layouts, and use the view page feature to view. When done, close the modal with the top-righthand corner close button and run the test again when you're readyby giving the page a new name.
Last updated