How to Create a Static Site with Metalsmith
The previous article discussed the reasons for whether to use a static website generator. In short, static website generators build page files that contain only HTML from templates and raw data (usually included in Markdown files). It offers some CMS benefits without the overhead of hosting, performance and security.
Static websites may be suitable for a variety of projects, including:
- Small website or personal blog. A website with dozens of pages, infrequent posts and one or two authors might be ideal.
- Technical documentation, such as REST API.
- Application prototypes that require a series of web views.
- E-Books—Markdown files can be converted to PDF or other formats and HTML.
Essentially, a static website generator is a building tool. You can use it to run tasks or project scaffolding like you would with Grunt or Gulp.
Key Points
- Metalsmith is a flexible pluggable static website generator that is ideal for creating lightweight websites without the overhead of traditional CMS.
- The installation and setup of Metalsmith requires Node.js, which involves initializing a new project directory and installing the necessary plugins via npm.
- The project structure in Metalsmith involves organizing source files, templates, and assets, and clearly distinguishes between development and production construction.
- Metalsmith uses various plug-ins to extend functionality, such as processing Markdown files, creating RSS feeds, and generating sitemaps, all configured in build files.
- Custom plugins can be created to handle specific tasks, such as setting up metadata or adding debug information, enhancing Metalsmith's versatility in managing website content and structure.
- The build process of Metalsmith can be integrated with task runners such as Gulp to deal with more complex scenarios, although Metalsmith itself is sufficient for simpler processes.
Why choose Metalsmith?
The undisputed static website champion is Jekyll – a Ruby project launched in 2008. You don't necessarily need Ruby expertise to use Jekyll, but that will help. Fortunately, most popular languages have a wide variety of open source static website generators. JavaScript options include Hexo, Harp, and Assemble. For simpler projects, you can also use build tools like Gulp.
I chose Metalsmith for this tutorial because it:
- Not targeting specific types of projects (such as blogs)
- Support various template and data format options
- Lightweight
- Seldom dependencies
- Using modular structure
- Provides a simple plug-in architecture, as well as
- Easy to get started.
This tutorial has built a demo website. It won't win any design awards, but it illustrates the basic concept. Metalsmith build code can be checked and installed from the GitHub repository. Alternatively, you can follow the instructions here and create your own basic site.
I've used Metalsmith a few times-please don't think this is the ultimate way to build every static website!
Installation Metalsmith
Make sure you have Node.js installed (for example using nvm), then create a new project directory, such as project and initialize your package.json file:
<code>cd project && cd project npm init -y </code>
Install Metalsmith now and the various plugins we will use to build the site. These are:
- metalsmith-assets — Include static assets in your Metalsmith build
- metalsmith-browser-sync — Integrate BrowserSync into your workflow
- metalsmith-collections — Add a collection of files to global metadata
- metalsmith-feed — Generate RSS feed for collections
- metalsmith-html-minifier — compress HTML files using kangax/html-minifier
- metalsmith-in-place — render template syntax in source file
- metalsmith-layouts — Apply layout to your source file
- metalsmith-mapsite — Generate sitemap.xml file
- metalsmith-markdown — Convert Markdown files
- metalsmith-permalinks — Apply custom permalink mode to files
- metalsmith-publish — Posts that support draft, private and future dates
- metalsmith-word-count — Calculate the word count/average reading time for all paragraphs in an HTML file
<code>npm install --save-dev metalsmith metalsmith-assets metalsmith-browser-sync metalsmith-collections metalsmith-feed metalsmith-html-minifier metalsmith-in-place metalsmith-layouts metalsmith-mapsite metalsmith-markdown metalsmith-permalinks metalsmith-publish metalsmith-word-count handlebars </code>
Project structure
We will use the following structure as the source (src) and build (build) directory in our project.
You can create sample files as follows, or copy them directly from the demo src directory.
Page
Page Markdown file is included in src/html. This can contain a first-level subdirectory for each website section, i.e.
- src/html/start — Pages that describe the project in a specific order
- src/html/article — Various articles arranged in anti-chronological order
- src/html/contact — Single contact page
Each directory contains an index.md file, which is the default page for that section. Other pages can use any unique name.
The build process converts these files into directory-based permalinks, such as
- src/html/start/index.md becomes /start/index.html
- src/html/start/installation.md becomes /start/installation/index.html
Each Markdown file provides content and meta information, called "preface" is located at the top between -- marks, e.g.
<code>--- title: My page title description: A description of this page. layout: page.html priority: 0.9 date: 2016-04-19 publish: draft --- This is a demonstration page. ## Example title Body text.</code>
Most preface questions are optional, but you can set:
- priority: A number between 0 (low) and 1 (high), which we will use to sort menus and define XML sitemaps.
- publish: Can be set as draft, private, or future date to ensure it is not published before it is needed.
- date: The date of the article. If not set, we will use any future release dates or file creation dates.
- layout: The HTML template to use.
Template
HTML page template is included in src/template. Two templates have been defined:
- src/html/template/page.html Default layout
- src/html/template/article.md Article layout that displays date, before and after links, etc.
Although other options are supported, the Handlebars template system is used. A typical template requires a {{{ contents }}} tag to contain the page content and any preface values, such as {{ title }}:
<code>cd project && cd project npm init -y </code>
The references to {{> meta }}, {{> header }} and {{> footer }} are partially...
Part
Thesection—or the HTML snippet file—is contained in src/partials. These are mainly used in templates, but can also be included in the content page using the following code:
<code>npm install --save-dev metalsmith metalsmith-assets metalsmith-browser-sync metalsmith-collections metalsmith-feed metalsmith-html-minifier metalsmith-in-place metalsmith-layouts metalsmith-mapsite metalsmith-markdown metalsmith-permalinks metalsmith-publish metalsmith-word-count handlebars </code>
where partialname is the name of the file in the src/partials directory.
Static Assets
Static assets (such as images, CSS, and JavaScript files) are included in src/assets. All files and subdirectories will be copied as is to the root of the website.
Custom Plugin
The custom plugins required to build the site are included in the lib directory.
Build directory
The website will be built in the build directory. We will build the website in two ways:
- Development Mode: HTML will not be compressed and will start the test web server.
- Production mode: If NODE_ENV is set to production, the build directory is cleared and the final compressed file is generated.
Define your first build file
You can create a basic example called build.js in the root directory of the project directory:
<code>--- title: My page title description: A description of this page. layout: page.html priority: 0.9 date: 2016-04-19 publish: draft --- This is a demonstration page. ## Example title Body text.</code>
Run it with node ./build.js and a static website will be created in the build directory. Markdown will be parsed as HTML, but it is not available because we did not include the template during the build process.
Metalsmith plugin
On the surface, the Metalsmith build file looks similar to the one used in Gulp (although it does not use streams). Call the plugin by passing it to the Metalsmith use method using any appropriate arguments. The plugin itself must return another function, which accepts three parameters:
- A files array containing information about each page
- A metalsmith object containing global information, such as metadata, and
- A done function that must be called after the plugin completes its work
This simple example logs all metadata and page information to the console (it can be defined in build.js):
<code> lang="en"> > {{> meta }} > > {{> header }} <main>></main> > {{#if title}} <h1 id="gt">></h1>{{ title }}> {{/if}} {{{ contents }}} > > {{> footer }} > > </code>
Metalsmith build code can be updated to use this plugin:
<code>{{> partialname }}</code>
This debugging function can help you create your own custom plugins, but most of the features you may need are already written – there is a long list of plugins on the Metalsmith website.
Make a better build
The main parts of the demo site build file are explained below.
If the NODE_ENV environment variable is set to production (export NODE_ENV=production on Mac/Linux or NODE_ENV=production on Windows), the variable devBuild will be set to true:
<code>cd project && cd project npm init -y </code>
Home directory is defined in the dir object so that we can reuse them:
<code>npm install --save-dev metalsmith metalsmith-assets metalsmith-browser-sync metalsmith-collections metalsmith-feed metalsmith-html-minifier metalsmith-in-place metalsmith-layouts metalsmith-mapsite metalsmith-markdown metalsmith-permalinks metalsmith-publish metalsmith-word-count handlebars </code>
Load Metalsmith and plug-in modules. Note:
- Excellent Browsersync test server is only required when creating a development build
- HTML compressor module referenced by htmlmin is only required when creating a production build
- Three custom plugins have been defined: setdate, moremeta, and debug (explained in more detail below)
<code>--- title: My page title description: A description of this page. layout: page.html priority: 0.9 date: 2016-04-19 publish: draft --- This is a demonstration page. ## Example title Body text.</code>
siteMeta object is defined using information applied to each page. Important values are domain and rootpath, which are set based on development or production build:
<code> lang="en"> > {{> meta }} > > {{> header }} <main>></main> > {{#if title}} <h1 id="gt">></h1>{{ title }}> {{/if}} {{{ contents }}} > > {{> footer }} > > </code>
also defines a templateConfig object to set the template default values. This will be used by the metalsmith-in-place and metalsmith-layouts plugins, which enable in-page and template rendering using Handlebars:
<code>{{> partialname }}</code>
Metalsmith object is now initialized as before, but we also pass the siteMeta object to the metadata method to ensure that this information is available for each page. So we can refer to items like {{ name }} in any page to get the site name.
<code>// basic build 'use strict'; var metalsmith = require('metalsmith'), markdown = require('metalsmith-markdown'), ms = metalsmith(__dirname) // the working directory .clean(true) // clean the build directory .source('src/html/') // the page source directory .destination('build/') // the destination directory .use(markdown()) // convert markdown to HTML .build(function(err) { // build the site if (err) throw err; // and throw errors }); </code>
Our first plugin call metalsmith-publish, which removes any file whose preface publish value is set to draft, private, or future date:
<code>function debug(logToConsole) { return function(files, metalsmith, done) { if (logToConsole) { console.log('\nMETADATA:'); console.log(metalsmith.metadata()); for (var f in files) { console.log('\nFILE:'); console.log(files[f]); } } done(); }; }; </code>
setdate is a custom plugin included in lib/metalsmith-setdate.js. It ensures that each file has a "date" value set, and even if no value is defined in the previous question, it can be achieved by falling back to the release date or file creation time as much as possible:
<code>ms = metalsmith(__dirname) // the working directory .clean(true) // clean the build directory .source('src/html/') // the page source directory .destination('build/') // the destination directory .use(markdown()) // convert Markdown to HTML .use(debug(true)) // *** NEW *** output debug information .build(function(err) { // build the site if (err) throw err; // and throw errors }); </code>
metalsmith-collections is one of the most important plugins because it assigns each page to a category or taxonomy based on its location or other factors in the source directory. It can reorder files using prefaces such as dates or priorities and allows you to set custom metadata for the collection. Code definition:
- The start collection of each file in the src/html/start directory. It sorts them by priority values set in the previous question in the file.
- The article collection of each file in the src/html/article directory. It sorts them in anti-chronological order
- The page collection of each default page named index.*. It sorts them by priority values set in the previous question in the file.
<code>devBuild = ((process.env.NODE_ENV || '').trim().toLowerCase() !== 'production') </code>
The next is the Markdown to HTML conversion, followed by the metalsmith-permalinks plugin, which defines the directory structure for the build. Please note that moremeta sets :mainCollection for each file below:
<code>dir = { base: __dirname + '/', lib: __dirname + '/lib/', source: './src/', dest: './build/' } </code>
metalsmith-word-count Calculates the number of words in an article and calculates how long it takes to read it. Parameter { raw: true } Output only numbers:
<code>metalsmith = require('metalsmith'), markdown = require('metalsmith-markdown'), publish = require('metalsmith-publish'), wordcount = require("metalsmith-word-count"), collections = require('metalsmith-collections'), permalinks = require('metalsmith-permalinks'), inplace = require('metalsmith-in-place'), layouts = require('metalsmith-layouts'), sitemap = require('metalsmith-mapsite'), rssfeed = require('metalsmith-feed'), assets = require('metalsmith-assets'), htmlmin = devBuild ? null : require('metalsmith-html-minifier'), browsersync = devBuild ? require('metalsmith-browser-sync') : null, // custom plugins setdate = require(dir.lib + 'metalsmith-setdate'), moremeta = require(dir.lib + 'metalsmith-moremeta'), debug = consoleLog ? require(dir.lib + 'metalsmith-debug') : null, </code>
moremeta is another custom plugin included in lib/metalsmith-moremeta.js. It attaches other metadata to each file:
- root: The absolute or calculated relative file path to the root directory
- isPage: Set to true for the default partial page named index.* mainCollection: The main collection name, i.e. start or article
- layout: If not set, the layout template can be determined from the metadata of the main collection
- navmain: Array of top-level navigation objects
- navsub: Array of secondary navigation objects
<code>cd project && cd project npm init -y </code>
<code>npm install --save-dev metalsmith metalsmith-assets metalsmith-browser-sync metalsmith-collections metalsmith-feed metalsmith-html-minifier metalsmith-in-place metalsmith-layouts metalsmith-mapsite metalsmith-markdown metalsmith-permalinks metalsmith-publish metalsmith-word-count handlebars </code>
<code>--- title: My page title description: A description of this page. layout: page.html priority: 0.9 date: 2016-04-19 publish: draft --- This is a demonstration page. ## Example title Body text.</code>
<code> lang="en"> > {{> meta }} > > {{> header }} <main>></main> > {{#if title}} <h1 id="gt">></h1>{{ title }}> {{/if}} {{{ contents }}} > > {{> footer }} > > </code>
<code>{{> partialname }}</code>
- metalsmith-mapsite Generate XML sitemap
- metalsmith-feed Generate an RSS feed for pages in the article collection
- metalsmith-assets Copy files and directories in src/assets to build without modification.
<code>// basic build 'use strict'; var metalsmith = require('metalsmith'), markdown = require('metalsmith-markdown'), ms = metalsmith(__dirname) // the working directory .clean(true) // clean the build directory .source('src/html/') // the page source directory .destination('build/') // the destination directory .use(markdown()) // convert markdown to HTML .build(function(err) { // build the site if (err) throw err; // and throw errors }); </code>
<code>function debug(logToConsole) { return function(files, metalsmith, done) { if (logToConsole) { console.log('\nMETADATA:'); console.log(metalsmith.metadata()); for (var f in files) { console.log('\nFILE:'); console.log(files[f]); } } done(); }; }; </code>
What to pay attention to
I learned a lot when building a simple Metalsmith website, but be aware of the following issues:
Incompatible plug-ins
Plugins may conflict with other plugins. For example, calculating the metalsmith-rootpath of the relative root path is not very compatible with metalsmith-permalinks that create custom build directory structures. I solved this problem by writing custom root path calculation code in the lib/metalsmith-moremeta.js plugin.
Plugin order is crucial
If the plugins are placed in the wrong order, the plugins may depend on or conflict. For example, the metalsmith-feed plugin that generates RSS must be called after metalsmith-layouts to ensure that RSS XML is not generated in the page template.
Browsersync rebuild issue
When Browsersync runs and edits the file, the collection is reparsed, but the old data still seems to exist. This may be an issue with the lib/metalsmith-moremeta.js custom plugin, but the menu and front and back links may be out of sync. To fix it, stop the build and restart the build using Ctrl/Cmd C.
Do you still need Gulp?
People using task managers such as Gulp will notice that Metalsmith provides a familiar build process. There are plug-ins for CSS preprocessing, image compression, file connection, vilification and more with Sass. For a simpler process, it might be enough.
However, Gulp has a wider range of plugins and allows for complex build activities such as lint, deployment, and PostCSS processing using auto-prefixer. There are some Gulp/Metalsmith integration plugins, although I have some problems and they should not be necessary because Gulp tasks can run Metalsmith directly, e.g.
<code>cd project && cd project npm init -y </code>
This process prevents the Browsersync rebuild problem mentioned above. Remember to use .clean(false) to ensure that Metalsmith never clears the build folder when other tasks are active.
Is Metalsmith suitable for you?
Metalsmith is ideal if you have simple or highly customized website needs. Maybe try using a document project and add one feature at a time. Metalsmith isn't as fully functional as alternatives like Jekyll, but it's not designed to be that way. You may need to write your own plugin, but it's easy to do so, which is a huge benefit for JavaScript developers.
Creating a Metalsmith build system takes time, and we haven't considered the amount of work involved in HTML templates and deployment. However, once you have a process available, adding, editing, and deleting Markdown files becomes very simple. It may be easier than using CMS, and you have all the benefits of a static website.
FAQs about creating static websites with Metalsmith
What is Metalsmith and why should I use it to create static websites?
Metalsmith is a simple and easy-to-use pluggable static website generator. It is based on Node.js and uses a modular structure that allows you to add functionality as needed through plugins. This makes it incredible flexibility and customizability. You should use Metalsmith to create a static website because it allows you to build your website exactly as you wish without being restricted by traditional CMS. In addition, static websites are faster, safer, and easier to maintain than dynamic websites.
How to install Metalsmith?
To install Metalsmith, you need to install Node.js and npm on your computer. After installing these, you can install Metalsmith by running the command npm install metalsmith in the terminal. This will install Metalsmith and all its dependencies.
How to create a new Metalsmith project?
To create a new Metalsmith project, first navigate in the terminal to the directory where you want to create the project. Then, run the command metalsmith to create a new project. This will create a new directory with the name of your project, and within this directory it will create a basic structure for your static website.
How to add plugins to my Metalsmith project?
To add plugins to your Metalsmith project, you need to install them via npm and then reference them in your Metalsmith configuration file. For example, to add the markdown plugin, you first need to run npm install metalsmith-markdown, and then in your configuration file, you need to add var markdown = require('metalsmith-markdown'); and add .use(markdown()) Go to your Metalsmith build chain.
How to build my Metalsmith website?
To build your Metalsmith website, you need to run the command metalsmith build in the terminal. This compiles all the files and outputs them to the build directory, which you can then deploy to your server.
How to customize the layout of my Metalsmith website?
To customize the layout of your Metalsmith website, you can use template engines such as Handlebars or Jade. These allow you to create reusable templates for different parts of your website, such as headers, footers, and individual pages.
How to add content to my Metalsmith website?
To add content to your Metalsmith website, you can create a markdown file in the source directory. When building a website, these files are converted to HTML. You can also use CMS such as Netlify CMS to manage your content.
How to deploy my Metalsmith website?
To deploy your Metalsmith website, you can use services such as Netlify or GitHub Pages. These services will host your static website and automatically deploy changes when you push to the repository.
How to update my Metalsmith website?
To update your Metalsmith website, you simply change the source file and rebuild your website. Changes will be reflected in the build directory, which you can then deploy to your server.
Can I use Metalsmith for large and complex websites?
Yes, Metalsmith is highly scalable and can be used for large and complex websites. Its modular structure allows you to add functionality as needed, and its use of static files means it can handle a lot of content without slowing down.
The above is the detailed content of How to Create a Static Site with Metalsmith. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

Frequently Asked Questions and Solutions for Front-end Thermal Paper Ticket Printing In Front-end Development, Ticket Printing is a common requirement. However, many developers are implementing...

JavaScript is the cornerstone of modern web development, and its main functions include event-driven programming, dynamic content generation and asynchronous programming. 1) Event-driven programming allows web pages to change dynamically according to user operations. 2) Dynamic content generation allows page content to be adjusted according to conditions. 3) Asynchronous programming ensures that the user interface is not blocked. JavaScript is widely used in web interaction, single-page application and server-side development, greatly improving the flexibility of user experience and cross-platform development.

There is no absolute salary for Python and JavaScript developers, depending on skills and industry needs. 1. Python may be paid more in data science and machine learning. 2. JavaScript has great demand in front-end and full-stack development, and its salary is also considerable. 3. Influencing factors include experience, geographical location, company size and specific skills.

How to merge array elements with the same ID into one object in JavaScript? When processing data, we often encounter the need to have the same ID...

Learning JavaScript is not difficult, but it is challenging. 1) Understand basic concepts such as variables, data types, functions, etc. 2) Master asynchronous programming and implement it through event loops. 3) Use DOM operations and Promise to handle asynchronous requests. 4) Avoid common mistakes and use debugging techniques. 5) Optimize performance and follow best practices.

Discussion on the realization of parallax scrolling and element animation effects in this article will explore how to achieve similar to Shiseido official website (https://www.shiseido.co.jp/sb/wonderland/)...

In-depth discussion of the root causes of the difference in console.log output. This article will analyze the differences in the output results of console.log function in a piece of code and explain the reasons behind it. �...

The latest trends in JavaScript include the rise of TypeScript, the popularity of modern frameworks and libraries, and the application of WebAssembly. Future prospects cover more powerful type systems, the development of server-side JavaScript, the expansion of artificial intelligence and machine learning, and the potential of IoT and edge computing.
