Skip to main content
Fear Goidte
Pronounced like “Far Gotcha”. The splendid online isolation of me, James Ó Nuanáin, wherein I gather together any loose cleverness that I manage to accumulate. This site is, primarily an exegesis on how it was made. For the moment, it is mostly beak and bone with very little feather and fur.
  1. Home
  2. Archives
  3. Copyright
  4. Access keys
  5. Web feed
  6. Colophon

A little something eXtra for the Middleman

James Ó Nuanáin

Estimated reading time: four minutes

Tagged with

A short inexhaustive guide to adapting Middleman 4.0.0 to output X.H.T.M.L. rather than H.T.M.L.

Whilst the following article might still have some use for converting an existing site, I have put together an X.H.T.M.L. Middleman template which, in one fell swoop, sets up up everything.

I’m not going to prattle on about which mark-up version is better. Suffice to say, I made the switch a long time ago and prefer to use X.H.T.M.L.

This is based on a vanilla setup of Middleman 4.0.0 and middleman-blog with the blog template used to initiate the Middleman skeleton project. my_test_website is used to refer to the directory which contains the Middleman skeleton project files.


Since X.H.T.M.L. has strict syntax you’ll want to switch your Markdown render to its X.H.T.M.L. version. In the case of Redcarpet (the default in Middleman 4.0.0), by adding the following to my_test_website\config.rb:

# Markdown settings
set :markdown_engine, :redcarpet
set :markdown, xhtml: true

Directory indices

It’s always a good idea to use ‘pretty’ U.R.L.s which exclude file extensions since they leave us open to changing language in the future and Cool U.R.I.s don’t change.

Directory indices in Middleman default to index.html so in my_test_website\config.rb underneath:

# Activate directory indices and remove file extensions from urls
activate :directory_indexes

Add the line:

set :index_file, 'index.xhtml'

Blog settings

The blog helper defaults to specifying .html files, so in my_test_website\config.rb you need to change the following settings:

  # blog.permalink = "{year}/{month}/{day}/{title}.html"
  # blog.sources = "{year}-{month}-{day}-{title}.html"
  # blog.taglink = "tags/{tag}.html"
  # blog.year_link = "{year}.html"
  # blog.month_link = "{year}/{month}.html"
  # blog.day_link = "{year}/{month}/{day}.html"
  blog.tag_template = "tag.html"
  blog.calendar_template = "calendar.html"

To (a simple find and replace from .html to .xhtml):

  blog.permalink = '{year}/{month}/{day}/{title}.xhtml'
  blog.sources = '{year}-{month}-{day}-{title}.xhtml'
  blog.taglink = 'tags/{tag}.xhtml'
  blog.year_link = '{year}.xhtml'
  blog.month_link = '{year}/{month}.xhtml'
  blog.day_link = '{year}/{month}/{day}.xhtml'
  blog.tag_template = 'tag.xhtml'
  blog.calendar_template = 'calendar.xhtml'

The important thing is to uncomment all the lines that now contain .xhtml.

Source file extensions

In the directory my_test_website\source files, you need to change:

As well as any other none-article\blog .xhtml files you want to add to source.

For any existing articles/post you need to change the extensions from html.markdown to xhtml.markdown.

Since Middleman 4.0.0.rc.2:

Rather than applying layouts to all files which are not .txt, .css, .js, .json: the new behavior is to only default layouts to active for .html

This means that in my_test_website\config.rb you need to replace:

# Per-page layout changes:
# With no layout
page '/*.xml', layout: false
page '/*.json', layout: false
page '/*.txt', layout: false

# With alternative layout
# page "/path/to/file.html", layout: :otherlayout

# Proxy pages (
# proxy "/this-page-has-no-template.html", "/template-file.html", locals: {
#  which_fake_page: "Rendering a fake page with a local variable" }


# Per-page layout changes:
page '/*.xhtml', layout: 'layout'
page '/articles/*.xhtml', layout: 'article'

This behaviour is set to change again soon so that the default layout will be applied to .htm and .xhtml files as well as .html. This will make the above two lines redundant. Middleman’s new behaviour makes the other page settings redundant as well as the line:

page "/feed.xml", layout: false

The layout file

Open my_test_website\source

Delete the blank last line.

Add a trailing slash to

    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="viewport" content="width=device-width, initial-scale=1" />


    <meta charset="utf-8" />


<!doctype html>


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>
<html xmlns="" xml:lang="en-gb-oxendict">

Where en-gb-oxendict matches the language code for the language of the website.


If you followed the above steps, you should now have a Middleman build serving up X.H.T.M.L.