Reusing common layouts across pages using templates.
Templates are a way to apply shared layouts to multiple pages, without having to duplicate any code.
Templates are located in the templates
folder at the root of your project source. If you are not already viewing the full project source, tap on Pages at the bottom of the sidebar, and select the Source view.
This will reveal the full project file tree:
A template is a JSX component that receives, among others, a children
property, holding the content of the page to which the template is applied. In addition, a meta
variable can be defined, holding information about the template, such as its display name. Here is a rudimentary template, that wraps a page in a div with a padding and a lime background color:
export const meta = {
name: "Blog",
}
export const Template = ({ children }) => {
return <div className="p-8 bg-lime-100">
{children}
</div>
}
export default (props) => <Template {...props} />
The full ES module syntax is supported, so we can import components from other pages, use JavaScript logic to define variables and hold state, and so on:
export const meta = {
name: "Blog",
}
import { Navbar } from "@components/navbar"
export const Template = ({ children }) => {
return <div>
<Navbar />
<div className="p-8 bg-lime-100">
{children}
</div>
</div>
}
export default (props) => <Template {...props} />
To learn more about layouts, make sure to read the Layouts article.
In addition to children
, the template is served other properties that allow you to customize the behavior depending on the page that it is being applied to.
export const Template = ({
filename,
path,
meta,
files,
children
}) => {
console.log("Page filename:", filename)
console.log("Page path:", path)
console.log("Page meta:", JSON.stringify(meta))
console.log("Project files:", JSON.stringify(files))
// ...
}
filename
: the name of the file to which the template is being applied.path
: its full path as it appears when published, e.g. /blog/post-1
.meta
: the page metadata.files
: the public pages file tree, e.g. to build an index of all published pages.For instance, you may want to display the page title and publication date of your blog posts in a coherent way across your pages. You can achieve that by setting page metadata for each post, e.g.:
---
title: My first blog post
date: 2022-02-21
---
and then access the values in your template via the meta
property:
export const Template = ({ meta, children }) => {
<div>
<h1>{meta.title}</h1>
<h2>{new Date(meta.date).toDateString()}</h1>
<div>{children}</div>
</div>
}
Read more about this in the metadata article →
In order to apply a template to a page, open the document sidebar (by hitting the document icon next to the Share button), and select the template via the dropdown.
Alternatively, head over to the motif.json
configuration file (hit and type motif.json
). Under the templates
keys, you can create rules mapping page paths to templates. This allows you to say things such as "all pages in the blog folder should use the blog
template", without having to explicitly select the template for each page.
{
"templates": {
"**/*": "main",
"/blog/*": "blog",
"about": "about",
},
Read more about these rules in the Motif configuration article.