Google map in your blog posts

Here is an easy way to add Google maps to your blog, using the Google Map Embed API.

Run the usual command to create a new post:

new post

Add some Google Map Embed API variables to your page front-matter YAML:

location:         Buckingham Palace, London, UK
maptype:          satellite
zoom:             18

Then add the following template partial to your post/page:


Save and build your page, then finally, view your page in a browser.

You should see a "place map", like this one:

You get a "Place map" by default, but there are different types!

Read more about "Google map in your blog posts"...

How to setup e-commerce with Mdsh

Adding e-commerce features, such as PayPal payment buttons, as well as managing your products, is now much easier thanks to the latest updates in mdsh.

You can have an online store up and running in about 5 mins.

But first, here are some example products with PayPal payment buttons.

Example: List of products

Here is a list of some of the products defined in assets/data/products.yml:

Product one

  • Price: £5.00
  • Shipping: 0.50


  • Colour:
  • Size:

Product three

  • Price: £5.00
  • Shipping: 0.50


  • Colour:
  • Size:

Example: Single product

Here is a single product, defined in the YAML front matter of this page:

How to setup e-commerce with Mdsh

  • Price: $5.00
  • Shipping: $0.50


  • Colour:

  • Size:

You can include your products in your markdown so they appear inline in your blog posts, or, you can create separate templates specifically for listing your products - it's up to you!

Read more about "How to setup e-commerce with Mdsh"...

Embedding Youtube videos, Tweets, Codepens and..

Using embedded content in your posts is easier than ever - just put the URL to the content on its own line in your Markdown and the URL will be automatically converted to the relevant embedded content at build time.

Supported services so far:

  • youtube
  • twitter
  • vimeo
  • instagram
  • tumblr
  • codepen
  • imgur
  • soundcloud

Read more about "Embedding Youtube videos, Tweets, Codepens and other third-party content"...

Easier stylesheet selection

  • 3 mins
  • sc0ttj
  • blog

You can now set stylesheets in the front matter of your posts and pages or in assets/data/site.yml - providing an easy way to style your pages with default stylesheets, or unique ones per page.

Settings a default website stylesheet

Your websites default styles are defined in assets/data/site.yml:

stylesheet: <name>
code_stylesheet: <name>

..where <name> matches a CSS file in assets/css/ (without the .css extension, or pygments- prefix).

Setting a page stylesheet

You can override the site defaults by defining stylesheet in your pages front matter (top of the .mdsh file) in the same way:

stylesheet: <name>
code_stylesheet: <name>

Stylesheet files are in assets/css/

The current stylesheets available are main and simple. Each stylesheet must have a .css file in assets/css/.

Stylesheets should not start with an underscore or 'pygments' - as these are "partials" and to be included in other stylesheets.

Using stylesheets in your templates

The following variables are available to use in your templates:

  • {{page_stylesheet}}: the main stylesheet for your page, falls back to site defaults.
  • {{page_code_stylesheet}}: the stylesheet for any highlighted code blocks on your page, falls back to site defaults.

Also available, but you probably won't need to use them:

  • {{site_stylesheet}}: the default stylesheet for your site.
  • {{site_code_stylesheet}}: the default stylesheet for any highlighted code blocks on your site.

Easier layout selection

  • 2 mins
  • sc0ttj
  • blog

You can now choose a page layout when creating new posts and pages - this provides an easy way to render your pages with different mustache templates, with varying layouts and structure.

The current layouts available are main and simple. Each layout must have a .mustache template file in .app/templates/[html]/, such as main.mustache or simple.mustache.

Layouts should not start with an underscore - as templates whose names begin with an underscore are "partials" and to be included in other templates.

The page_layout variable is available a build time, and taken from your post or pages front matter. For example, here is the YAML front matter for this post:

title:        Easier layout selection
slug:         easier-layout-selection
descr:        You can now choose a page layout when creating new posts and pages - this provides an easy way to render your pages with different mustache templates, with varying layouts and structure.
time_to_read: 2 mins
created:      2019-09-13T06:15:27Z
category:     blog
tags:         yaml
layout:       main
author:       sc0ttj
email:        foo@example.com
twitter:      @foobar
language:     en
modified:     2019-09-13T06:15:27Z


More layouts will be added in the future, to make it even easier to customise your pages.

Better site rebuilding

  • 3 mins
  • sc0ttj
  • blog

Now it's much easier to update/rebuild only the parts of the site you need to.

The rebuild command has been greatly improved, so you can (re)build specific index pages, and keep your site up-to-date much more easily.

How it works

The rebuild command now accepts options in the following format:

rebuild <index-page>[:item1,item2,...]


rebuild tags:templating,yaml

rebuild authors:sc0ttj categories:games

rebuild search

All rebuild options:

$ rebuild 404                 # update 404.html

$ rebuild homepage            # update index.html (the homepage)

$ rebuild archive             # update archive.html (lists all blog posts)

$ rebuild search              # update search.html (your website search page)

$ rebuild sitemap             # update sitemap.xml (used by search engines)

$ rebuild rss                 # update feed.rss (your RSS new feed)

$ rebuild authors             # update all pages in authors/

$ rebuild authors:foo,bar     # update pages authors/foo.html and tags/bar.html

$ rebuild categories          # update all pages in categories/

$ rebuild categories:foo,bar  # update pages categories/foo.html and tags/bar.html

$ rebuild tags                # update all pages in tags/

$ rebuild tags:foo,bar        # update pages tags/foo.html and tags/bar.html

$ rebuild years               # update all posts/<years>/index.html index pages

$ rebuild years:foo           # update posts/foo/index.html specifically

$ rebuild months 2019         # update all monthly index pages in posts/2019/

$ rebuild months:foo 2019     # update posts/2019/foo/index.html specifically

Chaining commands

The commands above can also be combined like so:

$ rebuild tags:foo,bar year:2019 authors:someone search

Permalinks for your posts

A new permalinks feature has been added, so you can create shorter, easier, custom URLs for your blog posts.

Simply run the command new post -all and follow the on-screen instructions.

Your page will be available at its normal URL (posts/year/month/day/post-name.html, as well as the permalink, which can be simply post-name, if you wish.

Example: If the post $site_domain/$site_url/posts/2019/09/07/13/liquid-filters.html had the permalink docs/liquid-filters, then it would be available at $site_domain/$site_url/docs/liquid-filters.

The permalink is saved in the front matter of your .mdsh files, and (ideally) should not be changed.

Better data and template handling

Some big improvements have been made to the handling of site and page data, as well as improvements to the templating system - all of which makes it much easier to include custom data in your pages.

The assets/data folder

A new folder has been created, which serves a special purpose - any data defined in any .csv, .sh or .yml files found in assets/data will be included available to your templates. This feature should be familiar to users of Jekyll, which has a _data folder for the same purpose.

The data is namespaced by the file in which it lives - a file called products.yml would be available in all your templates as an object called products, and so on.

Here's an example:

File assets/data/products.yml:

  name: Product one
  price: 1000
  name: Product two
  price: 2000
  name: Product three
  price: 3300
  name: Product four
  price: 4440
  name: Product five
  price: 5555

can be accessed in your templates with the new foreach iterator:

{{#foreach product in products}}
  Product {{product.name}} costs {{product.price | money '£'}}

Once you have your templates and data files in place, you can (re)build your pages as before:

# rebuild the page from its source file
rebuild path/to/some/file.mdsh > path/to/file.html

# update the homepage, index pages, etc

That's all there is to it.

Supported data types:

The assets/data folder supports CSV files (must contain headers!), a subset of YAML, and .sh files, which are sourced and in which you can define variables, arrays and functions as usual.

Read more about "Better data and template handling"...

Liquid Filters

mdsh now has a new feature, inspired by Liquid filters.

The Liquid templating system was created by Shopify and is used in the templating system of Jekyll.

Here's a description of "liquid filters" from the liquid filters documentation:

Filters are simple methods that modify the output of numbers, strings, variables and objects. They are placed within an output tag {{ }} and are denoted by a pipe character |.

As mdsh is written in shell, and uses mo as its Mustache library, I've implemented a rip-off version of liquid filters.

You can use the filters in your .mustache templates files, and in your .mdsh source files. You pass the variables through a filter using the pipe symbol |.

Usage and examples:

1. Template usage

Filtering basic page data (strings):

<h2>{{page_name | uppercase}}</h2>

^ this will output the page title in upper case.

Here is a more advanced example:

<h2>{{page_name | truncate_words 6 ".." | strip_newlines}}</h2>

^ this will truncate to 6 words, and append `..` if truncated, and strip new lines.

These filters also can also be applied to whole sections (if you must!):

{{page_header | strip_html}}

Filtering arrays:

In your templates various places use arrays to iterate over lists, such as recent posts. These lists can also be "filtered", in much the same way as the page data variables described above.

In your templates, normal `arrays` work as iterators, that can also take filters.

For example:

{{#someArray | sort_array desc | limit 3}}
  {{. | titlecase}}

Associative arrays also work nicely with the `foreach` iterator:

{{#foreach item in someAssocArray | sort_by "age" "asc" | limit 3}}
  Hi {{item.name | titlecase}},
  at {{item.address | uppercase | newline_to_br}}

2. Markdown usage

You can even use them in the sub-shells of your `*.mdsh` source files:

< ?bash echo "$something" | replace_all foo bar ;? >

Read more about "Liquid Filters"...

Faster site rebuilds

Re-building your site is now faster than before, thanks to a few improvements made in the latest commit:

  • rebuild only the relevant index pages after creating a new post
  • cache parts of the site which dont change during a site build:
    • site header
    • site navigation
    • site footer

Other fixes added in this commit include:

  • updated help info in various scripts
  • keep onwards journeys of all posts up-to-date when adding a new post

Read more about "Faster site rebuilds"...