Blacksmith
A generic static site generator built using flatiron, plates, and marked.
Install / Use
/learn @flatiron/BlacksmithREADME
blacksmith
A generic static site generator built using flatiron, plates, and marked.
- Creating a site with Blacksmith
- Components of a Blacksmith site
- How does blacksmith render my Site?
- Tests
Creating a site with blacksmith
Blacksmith sites have a specific directory structure for storing the various parts of your site: settings, layout, partials, pages, and content. Content exists in two forms:
- Markdown files that
blacksmithwill render. - Supporting content such as css and images.
All content will be rendered into /public. To render a blacksmith site:
Install Blacksmith
$ npm install blacksmith -g
Render a Site
#
# Defaults to `cwd`
#
$ blacksmith /path/to/your/site
Here's an example of a simple blog that blacksmith would render.
/site-name
#
# Settings for this blacksmith site.
#
.blacksmith
/content
#
# Actual Markdown content to render.
#
/posts
a-post.md
another-post.md
/layouts
#
# Layouts to use for pages. You can specify
# multiple layouts, but default.html is ... the default.
#
default.html
/metadata
#
# Metadata entities which can be reference in content metdata
#
/authors
author-name.json
/partials
#
# HTML for partials inside of pages
#
post.html
sidebar.html
/pages
#
# Metadata for rendering specific pages
#
index.json
post.json
/public
#
# Any additional files for viewing the site. All
# rendered HTML will be placed here. e.g.:
#
/css
styles.css
/img
favicon.png
Components of a blacksmith site
Each blacksmith site defines a hierarchical set of components which can be composed to create any type of site you want! A couple of examples:
- A Blog
- A Documentation Site
- A Custom Splash Page or Content Site
Lets examine each of these components and where they are stored in your filesystem:
Site Settings
The settings for a given blacksmith site are stored in the .blacksmith file located in the root directory of your site.
{
//
// Default Layout. Specifying a name here will cause Blacksmith to attempt to read
// /layouts/layout-name.json for rendering info. If no layout-name.json file is found
// blacksmith will use `/layouts/layout-name.html`
//
// Default: default
//
"layout": "layout-name",
"pages": {
//
// These settings will be used for all content in
// /content/posts
//
"post": {
"layout": "custom-layout-for-posts",
"partials": {
"html-id": "additional-partials",
"another-id": "for-this-page-only"
}
}
}
}
You can define settings for all components of your site in the .blacksmith file or break them out into individual files within component directories. For example, the above example is equivalent to:
/.blacksmith
{
"layout": "layout-name"
}
/pages/post.json
{
"layout": "custom-layout-for-posts",
"partials": {
"html-id": "additional-partials",
"another-id": "for-this-page-only"
}
}
Layouts
Layouts are fully-formed HTML files; they are the top of the rendering hierarchy. All content will be inserted into a layout inside of the HTML element with the id="content". Lets look at the worlds simplest layout:
<html>
<head>
<title>Simple Layout</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<div id="content">
<!-- All rendered content place here-->
</div>
</body>
</html>
Settings for a layout may be specified in your .blacksmith file or in /layouts/layout-name.json. Lets look at an example:
/layouts/layout-name.json NOTE: These properties are not yet supported. See Roadmap for more details.
{
//
// The "template" property specifies which HTML file within the /layouts directory
// to use when rendering this layout. In this way a single HTML file can be reused with
// different partials.
//
// If no template is specified then blacksmith will look for /layouts/layout-name.html
// when rendering.
//
"template": "shared-layout.html",
//
// The "partials" property specifies which HTML partial (or partials) to insert at a given
// id within the layout. These partials will be rendered with the metadata for a given
// individual page with content.
//
"partials": {
"sidebar-container": "sidebar",
//
// Multiple partials can be concatentated into a single HTML id.
//
"multi-container": ["partial1", "partial2"]
}
}
Pages
Pages allows you to specify what type of content you wish to render and where to render it within a given layout. As with layouts, pages may be specified in your .blacksmith file or in /pages/page-name.json. Lets look at two examples from our blog:
/pages/index.json
The above example demonstrates particular interest: index.json will always be used to render index.html. The following example specifies that blacksmith should render a list of post content, which should be truncated and limited to a maximum of 20 posts. Note: All lists are sorted descending by the date the content was created.
{
//
// The "content" property specifies what blacksmith should render
// inside the HTML element with id="content"
//
"content": {
"list": "post",
"truncate": true,
"limit": 20
}
}
/pages/post.json
The rendering information for an individual post is much simpler than our index.json. By creating this file, blacksmith will:
- Render all Markdown files in
/content/postsusing the partial found at/partials/post.html. - Render the partial found at
/partials/sidebar.htmlwith the metadata for each Markdown file in/content/postsand append it to the HTML element with id="content"
{
"partials": {
"content": "sidebar"
}
}
It is important to take note of the convention:
Convention: By default, page content will be rendered in a partial of the same name.
Alternatively we could have specified an explicit partial to use. If no partial is specified and the default partial is not found then no metadata would be rendered (in this case author name, date of post, etc).
All Page Options
A list of all available options that can be specified in a page.json file are listed below:
{
//
// Specifies the layout for the page.
// Default: Layout for the site.
//
"layout": "custom-layout-for-page",
//
// Specifies a mapping of HTML ids to partial(s). If "content" is specified
// then it is appended after the rendered markdown content.
//
"partials": {
"html-id": "partial-name",
"another-id": ["multiple-partials"]
},
//
// Case 1: Rendering content with a partial
//
"content": "custom-partial"
//
// Case 2: Consolidating multiple content sources in a list.
//
"content": {
"list": "post",
"truncate": true,
"limit": 20
}
}
Content
In blacksmith, "content" is raw Markdown and supporting files (e.g. images) located within the /content directory. Content for individual pages should be placed under /content/page-name.
In our example all content for the post page should be placed under /content/posts. It is important to take note of the convention:
Convention: Page names are always singular, but their content folder will always be plural.
The content for an individual page may also be a directory where supporting files (such as images can be placed). For example if we wanted to create a post with images, the directory structure would be:
/site-name
/content
/posts
/post-with-supporting-files
content.md
an-image.png
another-image.png
some-code.js
The directory structure will be respected, but the /content prefix will be dropped. So the full-url for an-image.png would be http://your-site.com/post-with-supporting-files/an-image.png.
Specifying Metadata
All metadata associated with content is stored within the individual Markdown files as link definitions prefixed with 'meta:'. Because of a small limitation in the Markdown format you must use the following syntax to specify metadata:
[meta:author] <> (Author Name)
[meta:title] <> (A Really Long Title Different from the Filename)
[meta:nested:values] <> (Are also supported)
Content Snippets
In large content pages it is often useful to have examples or references to other files to be inserted later in rendering. A classic example is code samples in a blog post. This is easy in blacksmith using Content Snippets. Consider the content:
/content
/dir-post
index.md
whatever.js
This is a piece of markdown content to be rendered later. It has a reference to the file "whatever.js"
<whatever.js>
In
