Code example: creating a master layout
A very common practice when working with templates is to create a master (or main or wrapper) template that contains all the parts of your site that are repeated on every page. If every layout on your site includes a Header and Footer, you don't need to rewrite those for every template file.
When using JS.SSG, you can achieve this by creating a template file that can wrap around the content within other layouts. If you've ever writen a React component that has "children", you'll recognize this concept.
For this example, we'll create several template files: a Header
component to generate a reusable header for every page, a Master
template to serve as the "wrapper", and two layouts (Home
and Post
).
├── templates/
| ├── Header.jsx
| ├── Home.jsx
| ├── Master.jsx
| └── Post.jsx
The "master" layout template
The thing that make this work is the children
prop that is passed into the component function. You can include any properties you like here (we're using site
in this example), but "children" is a special keyword that allows us to wrap other components with this component.
// Master.jsx
import Header from "./Header.js";
export default ({ site, children }) => (
<html lang="en">
<head>
<meta charSet="UTF-8" />
<title>{site.title}</title>
</head>
<body className="outer">
<Header title={site.title} />
<main className="main">
<div className="container">{children}</div>
</main>
</body>
</html>
);
Using the master layout within other layout files
Now we can use the Master
component within our Home
and Post
layout files.
Don't forget that any template that is used as a page layout accepts three props: content
, page
, and site
. More detail about layout components can be found on the JSX Templates page.
// Post.jsx
import Master from "./Master.js";
export default ({ content, page, site }) => (
<Master site={site}>
<h1>{page.title}</h1>
<div dangerouslySetInnerHTML={{ __html: content }} />
</Master>
);
// Home.jsx
import Master from "./Master.js";
export default ({ content, page, site }) => (
<Master site={site}>
<h1>{site.title}</h1>
<img
className="hero-image"
src={page.frontmatter.image}
alt={page.frontmatter.imageAlt}
/>
<div
className="home-content"
dangerouslySetInnerHTML={{ __html: content }}
/>
</Master>
);
Now we have two layouts (Home
and Post
) that we can use in our content pages' frontmatter. Both of these layouts share the same header component and outer HTML structure, but can be customised for their specific use cases.