An extremely simple, pluggable static site generator for NodeJS
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Command-line interface for running Metalsmith builds from configuration files with various options and environment variable support. The CLI provides a convenient way to run builds without writing JavaScript code.
The Metalsmith CLI provides commands for building static sites from configuration files.
# Default build command
metalsmith [options]
# Explicit build command
metalsmith build [options]Configure CLI behavior with command-line options.
# Configuration file location (default: metalsmith.json)
metalsmith --config <path>
metalsmith -c <path>
# Set or override environment variables
metalsmith --env <setting...>
# Set or override DEBUG environment variable (shortcut)
metalsmith --debug <namespaces>
# Process files without writing to filesystem
metalsmith --dry-runUsage Examples:
# Build from default metalsmith.json
metalsmith
# Build from custom config file
metalsmith --config lib/config.json
metalsmith -c build/metalsmith.js
# Override environment variables
metalsmith --env NODE_ENV=production TZ=Europe/London
# Enable debug output
metalsmith --debug @metalsmith/*
metalsmith --debug metalsmith-markdown,metalsmith-layouts
# Dry run (process without writing files)
metalsmith --dry-run
# Combined options
metalsmith --config site.json --env NODE_ENV=production --debug @metalsmith/*The CLI supports both JSON and JavaScript configuration files.
JSON Configuration (metalsmith.json):
{
"source": "src",
"destination": "build",
"clean": true,
"concurrency": 50,
"metadata": {
"sitename": "My Static Site",
"siteurl": "https://example.com/",
"description": "Site description"
},
"env": {
"NODE_ENV": "$NODE_ENV",
"DEBUG": false
},
"frontmatter": true,
"ignore": ["**/.DS_Store", "**/Thumbs.db"],
"plugins": [
{ "@metalsmith/drafts": true },
{ "@metalsmith/collections": { "posts": "posts/*.md" } },
{ "@metalsmith/markdown": { "gfm": true } },
{ "@metalsmith/permalinks": "posts/:title" },
{ "@metalsmith/layouts": { "pattern": "**/*.html" } }
]
}JavaScript Configuration (metalsmith.js):
import Metalsmith from 'metalsmith';
import drafts from '@metalsmith/drafts';
import collections from '@metalsmith/collections';
import markdown from '@metalsmith/markdown';
import permalinks from '@metalsmith/permalinks';
import layouts from '@metalsmith/layouts';
export default Metalsmith(__dirname)
.source('src')
.destination('build')
.clean(true)
.metadata({
sitename: 'My Static Site',
siteurl: 'https://example.com/',
description: 'Site description'
})
.use(drafts())
.use(collections({ posts: 'posts/*.md' }))
.use(markdown({ gfm: true }))
.use(permalinks('posts/:title'))
.use(layouts({ pattern: '**/*.html' }));The CLI resolves configuration files using the following priority:
--config optionmetalsmith.js in current directorymetalsmith.json in current directoryMulti-directory Support:
# CLI adjusts working directory based on config file location
cd /project/subdirectory
metalsmith --config ../config/metalsmith.json
# Working directory becomes: /project/config/
# Relative paths in config resolve from config file locationJSON configuration files support environment variable expansion.
{
"env": {
"NODE_ENV": "$NODE_ENV",
"API_URL": "$API_URL",
"DEBUG": "$DEBUG"
},
"metadata": {
"baseUrl": "$SITE_URL"
}
}Usage:
# Set environment variables
export NODE_ENV=production
export SITE_URL=https://example.com
export DEBUG=@metalsmith/*
# Run build (variables will be expanded)
metalsmithConfigure plugins in JSON using object syntax.
{
"plugins": [
// Plugin with boolean (use defaults)
{ "@metalsmith/drafts": true },
// Plugin with options object
{ "@metalsmith/markdown": {
"gfm": true,
"tables": true
}},
// Plugin with string option (shorthand)
{ "@metalsmith/permalinks": "posts/:title" },
// Local plugin (relative to config file)
{ "./plugins/custom-plugin": { "option": "value" } },
// Plugin array syntax (alternative)
{ "plugin-name": { "key": "value" } }
]
}The CLI automatically sets environment flags that plugins can detect.
// Plugins can check if running via CLI
function cliAwarePlugin(files, metalsmith, done) {
const isCliMode = metalsmith.env('CLI');
if (isCliMode) {
console.log('Running via CLI');
// CLI-specific behavior
}
done();
}The CLI provides formatted error messages and build status.
Success Output:
$ metalsmith
Metalsmith · reading configuration from: /path/to/metalsmith.json
Metalsmith · successfully built to: /path/to/buildError Output:
$ metalsmith --config invalid.json
Metalsmith · it seems like invalid.json is malformed or unsupported.
Encountered error: Unexpected token '}' in JSON at position 45
$ metalsmith --config missing.json
Metalsmith · could not find a configuration file 'missing.json'.
$ metalsmith --config empty.js
Metalsmith · it seems like empty.js is empty. Make sure it exports a metalsmith config object.
$ metalsmith --config plugin-error.json
Metalsmith · failed to require plugin "non-existent-plugin".
$ metalsmith --config broken-plugin.json
Metalsmith · error using plugin "broken-plugin"...
TypeError: Cannot read property 'foo' of undefined
at plugin (/path/to/plugin.js:10:5)Common CLI usage patterns and workflows.
Development Workflow:
# package.json scripts
{
"scripts": {
"build": "metalsmith",
"build:dev": "metalsmith --env NODE_ENV=development --debug @metalsmith/*",
"build:prod": "metalsmith --env NODE_ENV=production",
"preview": "metalsmith --dry-run",
"test": "metalsmith --config test/metalsmith.json --dry-run"
}
}
# Run development build
npm run build:dev
# Production build
npm run build:prod
# Preview without writing files
npm run previewMulti-environment Setup:
# Directory structure:
# config/
# metalsmith.development.json
# metalsmith.production.json
# metalsmith.test.json
# Build for different environments
metalsmith --config config/metalsmith.development.json
metalsmith --config config/metalsmith.production.json --env NODE_ENV=production
metalsmith --config config/metalsmith.test.json --dry-runCI/CD Integration:
#!/bin/bash
# build.sh
set -e # Exit on error
echo "Building site for environment: $NODE_ENV"
# Install dependencies
npm install
# Run build with environment-specific config
if [ "$NODE_ENV" = "production" ]; then
metalsmith --config config/production.json --env NODE_ENV=production
else
metalsmith --config config/development.json --env NODE_ENV=development --debug @metalsmith/*
fi
echo "Build completed successfully"The CLI resolves plugins using Node.js module resolution:
./path/to/plugin.js (relative to config file)@metalsmith/markdown or metalsmith-layoutsPlugin Loading Examples:
{
"plugins": [
// Official scoped plugin
{ "@metalsmith/markdown": true },
// Community plugin
{ "metalsmith-layouts": { "pattern": "**/*.html" } },
// Local plugin file
{ "./lib/custom-plugin": { "enabled": true } },
// Local plugin directory (with index.js)
{ "./plugins/image-processor": {} }
]
}Debug the CLI itself and plugin loading process.
# Enable CLI debugging
DEBUG=metalsmith:cli metalsmith --debug @metalsmith/*
# Debug plugin resolution
DEBUG=metalsmith:plugins metalsmith
# Full debug output
DEBUG=* metalsmith --debug @metalsmith/*