Building Pages with Metalsmith Components
Metalsmith Components provide a modular approach to page construction. Instead of embedding all content within markdown body text, pages are assembled from reusable components defined in structured frontmatter. This approach produces cleaner layouts, better code organization, and consistent component reuse across pages.
Pages are built by defining a content model in the frontmatter. Each page specifies its layout template and an array of section components. The layout template orchestrates these sections while individual component files handle specific rendering logic.
This page demonstrates the component-based approach:
layout: pages/sections.njk
bodyClasses: 'sections-page'
hasHero: true
navigation:
navLabel: 'Home'
navIndex: 0
seo:
title: Metalsmith Components
description: 'A collection of section components for use with Metalsmith'
socialImage: '/assets/images/sample2.jpg'
canonicalURL: ''
sections:
- sectionType: hero
# hero configuration
- sectionType: text-only
# text-only configuration
- sectionType: code-snippet
# code-snippet configuration
Configuration Properties:
layout
determines the template file for page renderingbodyClasses
adds CSS classes to the body elementnavigation
defines menu label and positionseo
contains metadata for search engine optimizationsections
array defines the sequence of components to render
Composable Sections
Components are built from smaller, reusable partials. The media-image section demonstrates this composition pattern by combining text, call-to-action buttons, and image partials.
Media Section Configuration
- sectionType: media-image
containerTag: aside
classes: ''
id: ''
isDisabled: false
isReverse: false
containerFields:
inContainer: true
isAnimated: true
noMargin:
top: false
bottom: true
noPadding:
top: true
bottom: true
background:
color: ''
image: ''
imageScreen: 'none' # light, dark, none
text:
leadIn: 'And what is this?'
title: Media Section Example
titleTag: 'h2'
isCentered: true
subTitle: ''
prose: Example of a media section with text and image. Change the image/text positions by setting the 'isReverse' property in the section data. The text area has a lead-in, title, sub-title, and prose. The prose is markdown text. All of the text parts are optional. There can be multiple CTAs, which are optional and may be buttons or links.
ctas:
- url: 'https://metalsmith.io'
label: 'Metalsmith Central'
isButton: true
buttonStyle: 'primary'
- url: 'https://wernerglinka.substack.com/p/a-better-way-to-build-web-pages'
label: 'Read more about this'
isButton: false
buttonStyle: 'primary'
image:
src: '/assets/images/sample7.jpg'
alt: 'nunjucks'
caption: 'Tortor Bibendum Sit Egestas'
Component Properties
The media section combines three primary elements:
Text Component:
leadIn
: Introductory text above the titletitle
: Main heading texttitleTag
: HTML heading level (h1-h6)is-centered
: Centers title over default columnssubTitle
: Secondary heading textprose
: Body content supporting markdown formatting
CTA Component:
url
: Link destinationlabel
: Display textisButton
: Boolean for button vs text link stylingbuttonStyle
: Visual style variant
Image Component:
src
: Image file pathalt
: Alternative text for accessibilitycaption
: Optional descriptive text
Template Implementation
The Nunjucks template demonstrates how these components are assembled:
{% from "components/_partials/ctas/ctas.njk" import ctas %}
{% from "components/_partials/text/text.njk" import text %}
{% from "components/_partials/image/image.njk" import image %}
<div class="media-image content {% if section.isReverse %}is-reverse{% endif %}">
{% if section.image %}
<div class="image">{{ image(section.image)}}</div>
{% endif %}
{% if section.text and section.ctas | length > 0 %}
<div class="text flow">
{% if section.text %}
<div class="prose flow">{{ text(section.text)}}</div>
{% endif %}
{% if section.ctas | length > 0 %}
{{ ctas(section.ctas) }}
{% endif %}
</div>
{% endif %}
</div>
The template imports partial functions and conditionally renders components based on the presence of data. The isReverse
property controls layout direction, allowing flexible image/text positioning without template duplication.
Benefits of Component-Based Architecture
The component-based approach provides significant advantages over traditional monolithic templates. Each component exists as an independent unit with its own template and configuration schema, enabling development, testing, and maintenance in isolation. This modularity creates a foundation for systematic page construction.
Components work across different page types and layouts without modification. A hero section defined once can appear on homepages, landing pages, or blog posts without duplication. This reusability eliminates redundant code and ensures consistency across the site. When component logic needs updating, changes happen in one location and propagate automatically. Updating the CTA button styling, for example, affects all instances across the site without hunting through multiple template files.
Page restructuring becomes straightforward through frontmatter configuration. Reordering sections or trying different layouts requires no template modifications - simply adjust the sections array in the frontmatter. This flexibility extends to content management where the separation between content structure and presentation logic allows content editors to work with data while developers focus on component implementation. The frontmatter defines what appears on the page while templates determine how it renders.
And here is the rendered media-section: