Category: Static Site Generators

Learning – Jekyll

Learning - Jekyll

Developers describe Jekyll as "Blog-aware, static site generator in Ruby". It is classified as "Static Site Generators" and "Self-Hosted Blogging / CMS", similar to WordPress for blogging.

Pros

  • Simple - No more databases, file based.
  • Static - Markdown (or Textile), Liquid templating language, HTML & CSS, etc.
  • Blog-aware - Includes permalinks, categories, pages, posts, and custom layouts.
  • Theme - Can be downloaded from rubygem
  • Github - Integration allow publish to Github

Cons

  • No search, but it is SEO friendly
  • No plugin
  • No image resizing
  • No tag

Installation

Both Ruby and Gem need to be installed.

gem install jekyll bundler

Verify

jekyll -v

Create a Site

jekyll new ga_blog

Then there is ga_blog folder created.

Launch the Site

For the first time, run

bundle exec jekyll serve

Subsquence time

jekyll serve

Then the website can be accessed from http://localhost:4000/

Folder structure

The _posts folder hosts posts.

The _site folder hosts the finial product of website.

Front Matter

Content

___
layout: post
title: "Welcome To Jekyll!"
date: 2017-09-24 15:58:59 -0700
categories: jekyll update
___

URL

http://localhost:4000/jekyll/update/2017/09/24/welcome-to-jekyll!.html

Also can create custom attribute in Front Matter.

Writing Posts

The posts can be in subfolders too, the URL will add subfolder in the path.

Filename format

_posts/2017-09-24-my-first-blog-post.md

Layout

layout: "post"

Overwrite

title: "This is the new title"
date: 2017-09-20 15:58:59 -0700

Drafts

Create folder called _drafts, and save draft posts in this folder with name only, the date will be the today's date.

my-draft-blog-post.md

Then run following command

jekyll serve --draft

Pages

Create page in root folder, such as donate.md, and set layout as page

layout: "page"

Then the URL will be

http://localhost:4000/donate

Premalinks

permalink: "/my-new-url/"

or

permalink: /:categories/:year/:month/:day/:title.html

Default Front Matter

Defined in _config.yml file

defaults:
  -
    scope:
      path: ""
      type: "posts"
    values:
      layout: "post"
      title: "My Title"

Then restart jekyll server.

Theme

Default theme is minima, other themes can be downloaded from https://rubygems.org, and search jekyll-theme.

Update Gemfile

gem: "jekyll-theme-hacker"

Then stop Jekyll server and run command

bundle install

Update _config.yml file

theme: jekyll-theme-hacker

Then start jekyll server using following command

bundle exec jekyll serve

If there is no output on the page, normally, it is because no layout defined in theme.

Layouts

Create <layout_name>.html in _layouts folder

<h1>This is page</h1>
<hr>

{{ content }}

Define sub layout, then can be used in other layout.

For example, in post.html layout

---
layout: wrapper
---

<h1>This is a post</h1>
<hr>

{{ content }}

Then it will use wrapper layout defined in wrapper.htm below

<html>
<head>
  <meta charset="UTF-8">
  <title>Doument</title>
</head>
<body>
  Wrapper <br>
  {{ content }}
  <br> Wrapper
</body>
</html>

Use this method for other layouts, then can have html skeleton.

Variables

Front Matter variables

{{ layer.author}}
{{ page.title }}
{{ page.author }}
{{ site.title }}

The site values are from _config.yml file

Other variables can be found in https://jekyllrb.com/docs/variables/.

Includes

Create a folder called _includes

Create a file called header.html in _includes folder as below

<h1>{{ site.title }}</h1>

Then update wrapper.html file

<html>
<head>
  <meta charset="UTF-8">
  <title>Doument</title>
</head>
<body>
  {% include header.html %}
  {{ content }}
</body>
</html>

Then every page using wrapper.html will use header.html to display header.

To define variable during include as below

{% include header.html color="blue" %}

Then access in header.html file as below

<h1 style="color: {{ include.color }}">{{ site.title }}</h1>

Looping Through Posts

Update _layouts/home.html

{% for post in site.posts %}
  <li><a href="{{ post.url }}">{{ post.title }}</a></li>
{% endfor %}

Conditionals

{% if page.title == ... %}
{% elsif page.title == ... %}
{% else %}
{% endif %}

For example

{% for post in site.posts %}
  <li><a style="{% if page.url == post.url %}color:red;{% endif %}" href="{{ post.url }}">{{ post.title }}</a></li>

Data file

Create a folder called _data, put YAML, JSON or CSV files in it.

For example, people.yml file

- name: "Mike"
  occupation: "Giraffe Academy"

- name: "Steve"
  occupation: "Firefighter"

...

In home.html file

{{ site.data.people }}

or

{% for person in site.data.people %}
  {{ person.name }}, {{ person.occupation }} <br>
{% endfor %}

Static Files

Those files have no Front Matter, can be stored in any folder. For example, in assets folder, in home.html file,

{% for file in site.static_files %}
  {{ file.path }} <br>
{% endfor %}

Configure Front Matter in _config.yml file

defaults:
  - scope:
      path: "assets/img"
    values:
      image: true

Then restart jekyll server

Update home.html file

{% for file in site.static_files %}
  {% if file.image %}
    <img src="{{ file.path }}" alt="{{ file.name }}">
  {% endif %}
{% endfor %}

Hosting on Github Pages

Create repository called ga_blog, and don't init with README.

Update _config.yml file

baseurl: "ga_blog"

Then

git init
git checkout -b gh-pages
git add .
git commit -m "initial commit"

Add remote repo

git remote add origin https://github.com/<name>/ga_blog.git

Push

git push origin gh-pages

Then go to setting in Github page, find out published URL

References

Tutorials

Learning – Hugo – Static Site Generator

Learning - Hugo - Static Site Generator

Installation

Windows

hugo version

MacOS

  • Install Homebrew

  • Install hugo

brew install hugo
hugo version

Create a new site

hugo new site <site_name>

Then the folder created.

Site contents

  • archetypes - data type
  • content
  • data
  • layouts
  • static
  • themes
  • config.toml

Theme

theme = "ga-hugo-theme"

Create content

hugo new a.md
hugo new dir1/b.md

Run hugo in draft mode

hugo server -D

Single content

Display one page content.

List content

List other single contents in the page. The list page for Level 1 directories are automatically created hugo.

Manually create list page

Force hugo create list page, create _index.md file in the directory, and update the content of _index.md file will show on the list page

hugo new dir1/dir2/_index.md

Front Matter

YAML

---
title: "title"
date: 2017-...
draft: true
---

TOML

+++
title = "title"
date = 2017-...
draft = true
+++

Archetypes

The file archetypes/default.md has the template of new files.

---
tltle: "{{ replace .TranslationBaseName "-" " " | title }}"
date: {{ .Date }}
draft: true
---

The template file can be named as directory name, such as dir1.md, it will be used for contents created in dir1

hugo new dir1/b.md

Shortcodes

The predefined shortcodes can be found in hugo shortcode page, it also can be customized using shortcode template.

{{< youtube w7Ft2ymGmfc >}}

Taxonomies

Tags and categories

---
tags: [ "tag1", "tag2", "tag3"]
categories: [ "cat1"]
---

The tags and categories will be shown in contents if using learning theme.

Access tags and categories from page

https://localhost:1313/tags/tag1/
https://localhost:1313/categories/cat1/

Custome taxonomy

In content file

---
Moods: [ "Happy", "Upbeat" ]
---

In config.toml file

[taxonomies]
  tag = "tags"
  category = "categories"
  mood = "moods"

Note: If taxonomies session exists in config.toml file, then tag and category also must be included.

  • Restart hugo server

Template Basics

Theme template

Templates are in themes/ga-hugo-theme/layouts/_default. The list.html is for list page, the single.html is for single page.

Custome template

List page

Create in layouts/_default/list.html

<html>
<head>
  <meta charset="UTF-8">

  <title>Document</title>
</head>
<body>
  {{.Content}}
  <ul>
    {{ range .Pages }}
      <li><a href="{{.URL}}">{{.Title}}</a></li>
    {{end}}
  </ul>
</body>
</html>

Single page

Create in layouts/_default/page.html

<html>
<head>
  <meta charset="UTF-8">

  <title>Document</title>
</head>
<body>
  <h1>Header</h1>
  <h3>{{.Title}}</h3>
  <h4>{{.Date}}</h4>
  {{.Content}}
  <h2>Footer</h2>
</body>
</html>

Home page

Home page is a special list page. Create in layouts/index.html.

Section template

Create in layouts/_default/<dir_name>/single.html, which replace the template for files in <dir_name>.

Base Templates & Blocks

Create in layouts/_default/baseof.html, it is the template for all pages.

<html>
<head>
  <meta charset="UTF-8">

  <title>Document</title>
</head>
<body>
  Top of baseof
  <hr>
  {{ block "main" . }}

  {{end}}

  {{ block "footer" . }}
  <br>
  {{end}}
  <hr>
  Bottom of baseof
</body>
</html>

The create layouts/_default/single.html

{{ define "main" }}
  This is the single template
{{end}}
{{ define "footer" }}
  This is the single footer
{{end}}

The create layouts/_default/list.html

{{ define "main" }}
  This is the list template
{{end}}

Note: no overwrite in layouts/_default/list.html for footer.

Variables

Hugo variables only can be used in templates in layout.

For example:

<h1 style="color: {{ .Params.color }}">Single Template</h1><hr><br>

{{ .Title }} {{ .Date }} {{ .URL }}
{{ .Params.myVar }}

The myVar and color are custom variables defined in markdown file

---
myVar: "myValue"
color: "blue"
---

Define in template

{{ $myVarName := "string value" }}

<h1>{{ $myVarName }}</h1>

https://gohugo.io/variables

Function

Hugo functions only can be used in templates in layout.

{{ funcName param1 param2 }}

For example:

{{ truncate 10 "This is a very long string" }}
{{ add 1 5 }}
{{ sub 1 5 }}
{{ singularize "dogs" }}
{{ range .Pages }}
  {{ .Title }} <br>
{{ end }}

https://gohugo.io/functions

If Statements

{{ $var1 := "dog" }}
{{ $var2 := "cat" }}

{{ if not (eq $var1 $var2) }}
  True
{{ else if ... }}
{{ else }}
  False
{{ end }}
{{ if and (lt $var1 $var2) (lt $var1 $var3) }}
eq
lt
le
gt
ge
not
{{ $title := .Title }}
{{ range .Site.Pages }}
  <li><a href="{{.URL}}" style="{{ if eq .Title $title }} background-color:yellow; {{end}}">{{.Title}}</a></li>
{{ end }}

Data Files

The JSON, YAML, TOML files, for example, data/states.json

{{ range .Site.Data.states }}
  {{.name}} <br> {{.capital}}
{{end}}

Partial Templates

Header, footer, etc. Create file in layouts/partials/header.html

<h1>{{.Title}}</h1>
<p>{{.Date}}</p>
<hr>
<br>

In layouts/_default/single.html

{{ partial "header" . }}
<h1>Single Template</h1><hr><br>

Note: The . after "header" is indicating the entire scope of variables.

Custom dictionary

<h1>{{.myTitle}}</h1>
<p>{{.myDate}}</p>
<hr>
<br>

In layouts/_default/single.html

{{ partial "header" (dict "myTitle" "myCustomTitle" "myDate" "myCustomDate")}}
<h1>Single Template</h1><hr><br>

Note: It is the same as myTitle := myCustomTitle, myDate := myCustomDate

Shortcode Templates

Shortcode is used in markdown file, created in layouts/shortcodes.

Using variable name

For example, layouts/shortcodes/myshortcode.html

This is my shortcode file.
<p style="color: {{.Get `color`}}">This is the frameworks text</p>

Note: the " is replaced to "`"

In markdown file

{{< myshortcode color="blue">}}

Using variable number

For example, layouts/shortcodes/myshortcode.html

This is my shortcode file.
<p style="color: {{.Get 0}}">This is the frameworks text</p>

Note: the " is replaced to "`"

In markdown file

{{< myshortcode blue >}}

Multiple lines

In markdown file

{{< myshortcode >}}
  This is the text inside the shortcode tags
{{< /myshortcode >}}

In template file

<p style="background-color: yellow;">{{.Inner}}</p>

If you want to use markdown in shortcode, do follow

{{% myshortcode %}}
  **bold text**
{{% /myshortcode %}}

Building your site

huge server -D

If you just want to build the site into public folder

huge

Note: delete public folder first.

References

Hugo - Static Site Generator | Tutorial

Learning – Hexo – Static Site Generator

Learning - Hexo - Static Site Generator

Installation

Install NodeJS and git.

node -v
git version

Install Hexo

npm install -g hexo-cli
hexo -v

Init project

hexo init ga-hexo

This will create a folder called ga-hexo.

Run

cd ga-hexo
hexo server

The server will be run as http://localhost:4000.

Directories

node_modules - used by NodeJS
scaffolds - content templates
source - content folder
source/_post - the posts
themes - themes used
themes/landscape - default theme
_config.yml - define default theme, etc.
.gitignore
db.json
package.json - used by NodeJS package

Write content

Create post

Posts are written in source/_post.

cd ga-hexo
hexo new <page_name>

This will create a file source/_post/<page_name>.md

Create draft

hexo new draft <page_name>

This will create a file source/_draft/<page_name>.md. To show draft in hexo server, run following command

hexo server --draft

Publish draft

hexo publish <page_name>

Create page

hexo new page <page_name>

This will create a folder with index.html file source/<page_name>/index.md. To show page in hexo server, access URL http://localhost:4000/<page_name>/

Default type of page

The default layout can be found in _config.yml file as below

default_layout: post

If modify it as below,

default_layout: draft

Then the following command will create draft

hexo new <page_name>

Front Matter

Can be YAML or JSON

title: A's Title
date: 2017-09-14 15:11:10
tags: [ Tag1, Tag2, Tag3 ]

Scaffolds

In scaffolds folder, has 3 files as template, draft.md, page.md and post.md.

For example the post.md file.

---
title: {{ title }}
date: {{ date }}
tags:
---

Default content

Custom scaffold file

For example scaffolds/giraffee.md

title: {{ title }}
date: {{ date }}
layout: {{ layout }}

Following command

hexo new griaffe f

Will create following file

title: f
date: 2017-09-14 15:11:10
layout: griaffe

Tags & Categories

Tags

tags: [ Tag1, Tag2, Tag3 ]

The page will be

http://localhost:4000/tags/Tag1/

Categories

Categories:
- [Cat1, Cat1.1]
- [Cat2]
- [Cat3]

Tag Plugins

{% codeblock lang:javascript %}
  alert("Hello world");
  var myVar = "Hello World";
{% endcodeblock %}
{% youtuble hY7m5jjJ9mM %}

Asset Folders

The asset folders are static file folders.

To use asset folders, set following line in _config.yml file.

post_asset_folder: true

When run following command, source/_posts/a.md and source/_posts/a/ are created.

hexo new a

To use asset, following statement can be used in markdown file

{% asset_img hexo.jpg Hexo Logo %}

Note: Hexo Logo is the title of image.

To link to asset, use following line

{% asset_link hexo.jpg Hexo Logo %}

To use image path, use following line

{% asset_path hexo.jpg %}

Theme

Install theme

Themes can be downloaded from https://hexo.io/themes/index.html.

Then change _config.yml file as below

theme: alpha-dust

Restart the hexo server.

Create own theme

  • Create folder themes/ga-theme

  • Create file themes/ga-theme/config.yml

  • Create folders

themes/ga-theme/languages
themes/ga-theme/layout
themes/ga-theme/scripts
themes/ga-theme/source
  • Modify _config.yml file
theme: ga-theme
  • Restart hexo server

A blank page will be displayed.

Layout

layout.ejs

Layout is in themes/ga-theme/layout.

  • Create a file called layout.ejs in layout folder.
<html>
...
<body>
  This is the layout.ejs file
  <br>
  <%- body %>
  <br>
  This is the layout.ejs file
</body>
</html>

index.ejs

  • Create another file called index.ejs in layout folder.
This is a index.ejs file.

Then the output will be as follow for all index files, such as http://localhost:4000/, http://localhost:4000/a/, http://localhost:4000/2017/09/13/a/, etc.

This is the layout.ejs file
This is a index.ejs file.
This is the layout.ejs file

So all the pages will use layout.ejs file. And the <%- body %> will be replaced by actual ejs file. In above case, it is index.ejs file.

post.ejs

Create a file called themes/ga-theme/layout/post.ejs

<h1>This is a post</h1>

This will be used for all posts.

page.ejs

Create a file called themes/ga-theme/layout/page.ejs, this will impact all pages.

<h1>This is a page</h1>

tag.ejs

<h1>This is a tag</h1>

category.ejs

Partials

  • Create a folder themes/layout/partial

  • Then create a header.ejs in partial folder.

<h1><%= title %></h1>
<hr> <br>
  • In layer.ejs file
<html>
...
<body>
  <%- partial('partial/header', {title: 'hello world'}) %>
  <br>
  <%- body %>
  <br>
  Footer
</body>
</html>

Variables

Access front matter variable inside layout. For example, in post.ejs

<h1><%- page.title %></h1>
<p><%- page.date %></p>
<hr>
<%- page.content %>

The variables can be found in https://hexo.io/docs/variables.html

Custom variable

<%- page.author %>

If statement

<% if (page.author == "Mike") { %>
  Mike is the author, he's the best
<% } else { %>
  this author sucks
<% } %>

For Loops

<% site.posts.forEach(function(post) { %>
  <li><a href="<%- post.path %>"<%- post.title %></a></li>
  <br>
<% }) %>

Helper

Helpers are small functions.

<%- trim('    This is my string   ') %>
<%- titlecase('This is my string') %>
<%- date(Date.now(), 'YYYY/M/D') %>
<%- date(Date.now(), 'h:mm:ss a') %>

Helps can be found in https://hexo.io/docs/helpers.html.

Data Files

Create folder source/_data, and data file can be JSON or YAML file. Such as myData.yml

var1: "Var1's Value"
var2: "Var2's Value"
var3: "Var3's Value"

In template, such as index.ejs

<%- site.data.myData.var1 %> <br>
<%- site.data.myData.var2 %> <br>
<% for (var value in site.data.myData) { %>
  <%- value %> <br>
<% } %>
<br>
<% for (var value in site.data.myData) { %>
  <%- site.data.myData[value] %> <br>
<% } %>

Plugins

Download from https://hexo.io/plugins/.

Normally, use npm install to install plugin. For example,

npm install hexo-admin

After installed, go to _config.yml, make sure that plugin is listed in dependencies.

Generating Site

Run following command to generate website

hexo generate

The site will be created in public folder.

References

Hexo - Static Site Generator

Learning – Gatsby – Static Site Generator

Learning - Gatsby - Static Site Generator

Installation

  • Install NodeJS
node --version
npm --version
  • Install gatsby
npm install --global gatsby-cli
gatsby --version

Create site

gatsby new ga_site https://github.com/gatsbyjs/gatsby-starter-hello-world

A new folder called ga_site is created.

Run

npm run develop

The site will be run on http://localhost:8000

Folders

node_modules - Used by NodeJS.
public - the site to be published
src - pages
src/pages/index.js - start up page
package.json - define NodeJS packages

Adding Content

In index.js, there are ReactJS scripts.

import React from "react"

export default() =>
  <div style={{color: 'tomato', backgroundColor: 'blue'}} >
    <h1>Hello world!</h1>
    <p>This is a paragraph</p>
  </div>

Note: When writing contents in ReactJS, only one HTML element can be used in one statement.

Linking Pages

Add Link in index.js

import React from "react"
import Link from "gatsby-link"

export default() =>
  <div style={{color: 'tomato', backgroundColor: 'blue'}} >
    <h1>Hello world!</h1>
    <p>This is a paragraph</p>
    <Link to="/page-2/">Page 2</Link>
  </div>

Create a file src/pages/page-2.js

import React from "react"
import Link from "gatsby-link"

export default() =>
  <div style={{color: 'tomato', backgroundColor: 'blue'}} >
    <h1>Page 2</h1>
    <Link to="/">Go Home</Link>
  </div>

Note: Pages also can be in sub directory

Interactive Pages

Create a file called src/pages/counter.js.

import React from "react"

class Counter extends React.Component {
  constructior() {
    super()
    this.state = { count: 0 }
  }
  render() {
    return
      <div>
        <h1>Counter</h1>
        <p>current count: {this.state.count}</p>
        <button onClick={() => this.setState({ count: this.state.count + 1})}>plus</button>
        <button onClick={() => this.setState({ count: this.state.count - 1})}>minus</button>
      </div>
  }
}

Building site

npm run build

The site will be built in folder public.

Components

Import a component in another page, such as index.js

import React from "react"
import Link from "gatsby-link"
import Counter from "./counter.js"

export default() =>
  <div style={{color: 'tomato', backgroundColor: 'blue'}} >
    <h1>Hello world!</h1>
    <p>This is a paragraph</p>
    <Link to="/page-2/">Page 2</Link>

    <Counter />
  </div>

Component Parameters

In index.js file

<Counter color="blue" />

Read parameter in counter.js.

{this.props.color}

or

<div style={{ clor: this.props.color}}>
  ...
</div>

Plugins

Plugins can be downloaded from https://www.gatsbyjs.org/docs/plugins

For example, install typography plugin

npm install --save gatsby-plugin-typography

Create gatsby-config.js file.

module.exports = {
  plugins: [`gatsby-plugin-typography`]
}

Then restart website

gats develop

Layouts

Create default layout in src/layouts/index.js

import React from "react"

export default({ children }) =>
  <div>
    <h1>Header</h1>
    {children()}
    <h3>Footer</h3>
  </div>

Site Data

Create a file called gatsby-config.js.

  module.exports = {
    siteMetadata: {
      title: "Giraffe Academy's Website",
      author: Mike,
    }
  }

In index.js, use graphql

import React from "react"

export default({data}) => (
  <div style={{color: 'tomato', backgroundColor: 'blue'}} >
    <h1>{data.site.siteMetadata.title}</h1>
    <p>{data.site.siteMetadata.author}</p>
  </div>
)

export const query = graphql`
  query FirstQuery {
    site {
      siteMetadata {
        title
        author
      }
    }
  }
`

Restart gatsby server.

Testing GraphiQL page

Access http://localhost:8000/___graphql

{
  site {
    siteMetadata {
      title
      author
    }
  }
}

File Data

Install gatsby-source-filesystem plugin

npm install --save gatsby-source-filesystem

Update gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `src`,
        path: `${__dirname}/src/`,
      }
    }
  ]
}

Restart gatsby server.

Use GraphiQL to query file or allFile

{
  allFile {
    edges {
      node {
        id
      }
    }
  }
}

Note: after key in allFile, press Control-Enter or Command-Enter, the information will be auto filled up.
Note: If delete id, press Control-Space, the available attributes will be shown.

For example,

node: {
  extension
  relativePath
}

Update index.js

import React from "react"

export default({data}) => (
  <div style={{color: 'tomato', backgroundColor: 'blue'}} >
    <table>
      <thead>
        <tr>
          <th>relativePath</th>
          <th>prettySize</th>
          <th>extension</th>
          <th>birthTime</th>
        </tr>
      </thead>
      <tbody>
        {data.allFile.edges.map({ node }) =>
          <tr>
            <td>
              {node.relativePath}
            </td>
            <td>
              {node.prettySize}
            </td>
            <td>
              {node.extension}
            </td>
            <td>
              {node.birthTime}
            </td>
          </tr>
        }
      </tbody>
    </table>
  </div>
)

export const query = graphql`
  query MyFilesQuery {
    allFile {
      edges {
        node {
          relativePath
          prettySize
          extension
          birthTime(fromNow: true)
        }
      }
    }
  }
`

Working with Markdown

Install plugin gatsby-transformer-remark

npm install --save gatsby-transformer-remark

Update plugin session in gatsby-config.js

module.exports = {
  plugins: [
    `gatsby-transformer-remark`,
  ]
}

In GraphiQL, can see two new options

markdownRemark
allMarkdownRemark

Create markdown file src/pages/myFirstPost.md

---
title: "My Markdown File"
author: "Mike"
---

This is the content in my markdown

To access attributes in markdown file

id
html
formatmatter
formatmatter {
  title
  date
  parent
}

References

Gatsby - Static Site Generator | Tutorial

Learning – Middleman – Static Site Generator

Learning - Middleman - Static Site Generator

Install

  • Install Ruby
ruby --version
  • Install middleman
gem install middleman
middleman version

Install on Mac

Install xcode on Mac

xcode-select --install

Fix version issue in Mac

If encounter error on Mac indicating version low, run following command to install ruby version manager

curl -L https://get.rvm.io | bash -s stable

Restart terminal and run following command

rvm install ruby-2.4.2
rvm --default use ruby-2.4.2
ruby -v

Creating a site

middleman init ga_site

Then a folder called ga_site is created.

Run

middleman server

Access website via http://localhost:4567

Folders

source
source/images
source/javascripts
source/layouts
source/layouts/layout.erb - default layout
source/stylesheets
source/index.html.erb - default home page
config.rb
Gemfile

Activate LiveReload

LiveReload is able to reload the pages when they changed.

In config.rb file, add following line.

...
page...
...

activate :livereload

In Gemfile, add following line

gem 'middleman-livereload'

In project file, run following command

bundle install middleman-livereload

Restart middleman server

middleman server

Create html file ga_site/source/a.html.erb or ga_site/source/dir1/b.html.erb, then can access file from browser.

Note: If use .html without .erb, then it will not use default template.

Create markdown file as ga_site/source/c.html.md.erb.

Front Matter

Front matter can use JSON or YAML

YAML

---
title: Middleman is Running
author: "Mike"
---

JSON

;;;
"title": "New Title"
;;;

Access front matter variable

<%= current_page.data.author %>

Layouts

All pages are using source/layouts/layout.erb to display erb files. So, can modify the layout.erb file to change layout.

Helper Methods

Helpers are small codes can be used in markdown file.

<%= link_to 'Giraffe Academy', 'http://giraffeacademy.com' %>

To include ga_site/sources/styllesheets/ga_style

<%= stylesheet_link_tag 'ga_style' %>

To include ga_site/sources/javascripts/ga_code.js

<%= javascript_include_tag 'ga_code' %>

To include ga_site/source/images/log.png

<%= image_tag 'logo.png' %>

Other helpers can be found in middlemanapp.com

Layout

Default layout

The file ga_site/source/layouts/layout.erb is for all pages.

Specific layout

Create another layout2.erb file, then can be used in other markdown file using front matter as below a.html.erb.

---
layout: layout2
---

This is a.html

Layout for one directory

If want to specify all files in one directory use specific layout, can configure in config.rb file as below.

page '/dir1/*', layout: 'layout2'

Wrap layout

For example, the layout2 needs to use default layout and wrap it around, can be defined in layout2.erb file

<% wrap_layout :layout do %>
  New Layout <br> <hr>
  <%= yield %>
  <br><hr>New Layout
<% end %>

Partial

  • Create a folder ga_site/source/partials/, this is not mandatory.

  • Create partial file called _header.erb file, the leading _ is mandatory.

<h1>This is the Title</h1>
<br><hr>

To include in layout.erb file,

<%= partial 'partials/header' %>

Note: the leading _ and the tailing .erb are not shown in this statement, middleman knows how to find the file.

Passing variable

In layout.erb file

<%= partial(:'partials/header', :locals => { :title => 'My Title', :color => "blue" })

In _header.erb file

<h1 style="color: <%= color %>"><%= title %></h1>
<br><hr>

Data Files

Create a data folder as ga_site/data, create data file can be YAML or JSON files. For example test.yml

dog: "Golden Retriever"
products:
  - Tooth Brush
  - Shampoo
  - Soap

In layout.erb or index.erb file

<%= data.test.dog %>

or

<% data.test.products.each do |f| %>
  <li><%= f %></li>
<% end %>

If Statement

<% if current_page.data.title == "A" and current_page.data.author %>
  This is the A file
<% elsif current_page.data.title == "B" %>
  This is the B file
<% else %>
  This is not A or B
<% end %>

Sitemap

In layout.erb file

<% sitemap.resources.each do |f| %>
  <% if f.content_type.include? "html" %>
    <% f.data.title %> <br>
    <% f.path %> <br>
    <% f.content_type %> <br>
    <li><a href="<%= f.path %>"><%= f.data.title %></a></li>
  <% end %>
<% end %>

or

<% current_resource.parent.data.title %>

<% current_resource.siblings.each do |f| %>
  <% f.data.title %> <br>
<% end %>

<% current_resource.children.each do |f| %>
  <% f.data.title %> <br>
<% end %>

Building a Blog

First install blog generator

gem install middleman-blog

Initialize blog site

middleman init myBlog --template=blog

Start middleman blog server

cd myBlog
middleman server

Any file wants to be blog needs to be named as YYYY-MM-DD-title.md or created by following command

middleman article MyNewArticle
middleman article MyNewArticle

Also can add tags in the article

tags: example

or

tags: [example, tag2]

To list down all articles

<% blog.articles[0...10].each do |article| %>

<% end %>

Project Templates

Go to https://directory.middlemanapp.com/#/templates/all to download middleman templates

Once select the good one, run command

middleman init -T <template> <folder_name>

For example

middle init -T dtcristo/middleman-cactus cactus

Pretty URLs

Normally, to remove the extension of file in URL, create a folder, move the file in the folder, and rename the file as index.html.erb.

This can be done using configuration in config.rb

activate :directory_indexes

Install Extensions

Download extension from https://directory.middlemanapp.com/#/extensions/all website.

First, update Gemfile, add gem

gem 'middleman-minify-html'

The add configure in config.rb file

activate :minify_html

Then install gem

bundle install

Building Site

Run following command

middleman build

Then the website will be built in build directory.

References

Middleman - Static Site Generator | Tutorial