Convenient
Metalsmith works with all the tools and data formats you already know and use: NodeJS, npm, markdown, json, yaml and the templating language of your choice.
Simple
Metalsmith translates a directory tree to plain Javascript objects that you can manipulate effortlessly with your selection of plugins.
Pluggable
You shouldn't have to bend your project needs to a specific framework or tool. Metalsmith gives you full control of how you want to conceptualize, structure and build your project.
Versatile
Use Metalsmith to generate anything from a static site, to a scaffolder, backup, command-line, or deploy tool. Configuration over code or code over configuration: Metalsmith supports both.
Install it
npm install metalsmith
yarn add metalsmith
pnpm add metalsmith
Or use a starter
Get the feel of it
You want to build a website or blog with a static site generator. Well, here is our elevator pitch. It's as easy as that:
metalsmith.mjs
import { fileURLToPath } from 'node:url'
import { dirname } from 'node:path'
import Metalsmith from 'metalsmith'
import collections from '@metalsmith/collections'
import layouts from '@metalsmith/layouts'
import markdown from '@metalsmith/markdown'
import permalinks from '@metalsmith/permalinks'
const __dirname = dirname(fileURLToPath(import.meta.url))
const t1 = performance.now()
Metalsmith(__dirname) // parent directory of this file
.source('./src') // source directory
.destination('./build') // destination directory
.clean(true) // clean destination before
.env({ // pass NODE_ENV & other environment variables
DEBUG: process.env.DEBUG,
NODE_ENV: process.env.NODE_ENV
})
.metadata({ // add any variable you want & use them in layout-files
sitename: "My Static Site & Blog",
siteurl: "https://example.com/",
description: "It's about saying »Hello« to the world.",
generatorname: "Metalsmith",
generatorurl: "https://metalsmith.io/"
})
.use(collections({ // group all blog posts by internally
posts: 'posts/*.md' // adding key 'collections':'posts'
})) // use `collections.posts` in layouts
.use(markdown()) // transpile all md into html
.use(permalinks()) // change URLs to permalink URLs
.use(layouts({ // wrap layouts around html
pattern: '**/*.html'
}))
.build((err) => { // build process
if (err) throw err // error handling is required
console.log(`Build success in ${((performance.now() - t1) / 1000).toFixed(1)}s`)
});
metalsmith.cjs
const Metalsmith = require('metalsmith')
const collections = require('@metalsmith/collections')
const layouts = require('@metalsmith/layouts')
const markdown = require('@metalsmith/markdown')
const permalinks = require('@metalsmith/permalinks')
const t1 = performance.now()
Metalsmith(__dirname) // parent directory of this file
.source('./src') // source directory
.destination('./build') // destination directory
.clean(true) // clean destination before
.env({ // pass NODE_ENV & other environment variables
DEBUG: process.env.DEBUG,
NODE_ENV: process.env.NODE_ENV
})
.metadata({ // add any variable you want & use them in layout-files
sitename: "My Static Site & Blog",
siteurl: "https://example.com/",
description: "It's about saying »Hello« to the world.",
generatorname: "Metalsmith",
generatorurl: "https://metalsmith.io/"
})
.use(collections({ // group all blog posts by internally
posts: 'posts/*.md' // adding key 'collections':'posts'
})) // use `collections.posts` in layouts
.use(markdown()) // transpile all md into html
.use(permalinks()) // change URLs to permalink URLs
.use(layouts({ // wrap layouts around html
pattern: '**/*.html'
}))
.build((err) => { // build process
if (err) throw err // error handling is required
console.log(`Build success in ${((performance.now() - t1) / 1000).toFixed(1)}s`)
})
metalsmith.json
{
"source": "src",
"destination": "build",
"clean": true,
"env": {
"DEBUG": "$DEBUG",
"NODE_ENV": "$NODE_ENV"
},
"metadata": {
"sitename": "My Static Site & Blog",
"siteurl": "https://example.com/",
"description": "It's about saying »Hello« to the world.",
"generatorname": "Metalsmith",
"generatorurl": "https://metalsmith.io/"
},
"plugins": [
{ "@metalsmith/collections": { "posts": "posts/*.md" }},
{ "@metalsmith/markdown": {}},
{ "@metalsmith/permalinks": { "relative": false }},
{ "@metalsmith/layouts": {}},
]
}
The package exposes both a JavaScript API, and a CLI if you prefer. To see how they're used check out the examples or the walkthrough.
You can follow along with a detailed walkthrough or have a go with a very minimal example:
git clone https://github.com/metalsmith/metalsmith.git
cd metalsmith/examples/static-site
npm install
npm start
Build anything
We mainly refer to Metalsmith as a "static site generator", but it's a lot more than that. Since everything is a plugin, the core library is just an abstraction for manipulating a directory of files.
Which means you could just as easily use it to make...
A Project Scaffolder
- Read template files from a directory.
- Parse files for template placeholders.
- Prompt user to fill in each placeholder.
- Render files with a templating engine.
- Write filled-in files to a new directory.
A Build Tool
- Read files from a source directory.
- Convert Sass files to CSS.
- Concatenate CSS files.
- Minify the CSS file.
- Compress images files.
- Sprite images in a certain folder.
- Write files to a public directory.
An eBook Generator
- Read chapter files from a directory.
- Build a table of contents from the tree.
- Convert Markdown to HTML.
- Convert Markdown to PDF.
- Convert Markdown to ePUB.
- Convert Markdown to MOBI.
- Write compiled files to a directory.
Technical Docs
- Read files from a source directory.
- Convert Markdown files to HTML.
- Build a navigation from the tree.
- Render each file with a template.
- Write HTML to the static directory.
Deploy anywhere
Metalsmith builds are static folders. They can be compressed, archived, deployed to a CDN, Netlify, Github Pages, Gitlab Pages, SFTP'd to a shared host, or SSH'd to a custom server.
Showcase
Built with Metalsmith
Particle Docs
JSDoc
OpenLayers
PlayCanvas Developer Docs
ScenicByways
Algolia create-instantsearch-app
DotEco
Jim Nielsen's blog
Design System Gov UK
National Archives Design System
RTR Nettest
CTU-Nettest
Foxxtrot blog
qooxdoo framework
Async.js
Basisproject
Eric Dorsey's blog
Andrew Lock's blog
Christian Emmer
Moleculer CLI
glinka.co personal blog
blue Systems Research Group
Bodies in balance pilates
SchildiChat
Use a starter
metalsmith/startbootstrap-clean-blog
Code| Demogit clone https://github.com/metalsmith/startbootstrap-clean-blog cd startbootstrap-clean-blog && npm install
wernerglinka/metalsmith-bare-bones-starter
Code| Demogit clone https://github.com/wernerglinka/metalsmith-bare-bones-starter cd metalsmith-bare-bones-starter && npm install
wernerglinka/metalsmith-blog-starter
Code| Demogit clone https://github.com/wernerglinka/metalsmith-blog-starter cd metalsmith-blog-starter && npm install
wernerglinka/metalsmith-company-starter
Code| Demogit clone https://github.com/wernerglinka/metalsmith-company-starter cd metalsmith-company-starter && npm install
webketje/metalsmith-starter-resume
Code| Demogit clone https://github.com/webketje/metalsmith-starter-resume cd metalsmith-starter-resume && npm install