Template Files

Templates are files that indicate how content and data should be used in the pages that Eleventy renders.

The index.html previously created is a template. It uses a template language to indicate how and where to use data from the front matter in the template's HTML. Markdown files and Layouts are also types of templates.

Markdown

Markdown files in Eleventy are like the README.md files you find in GitHub repos. They use the same syntax. They can also have front matter added. They are used to contain data and content, which Eleventy can then render into HTML, or which can be inserted into another template file (i.e. a Layout file).

Create the file about.md :

# Animals About Page

This is the Animals about page
		

A new folder _site/about should appear, and inside that an index.html file (the About page). In that file should be the content :

<h1>Animals About Page</h1>
<p>This is the Animals about page</p>
		

The markdown text with the # has been automatically inserted into a new <H1> tag, with the remaining content inserted into a new <P> tag.

Layouts

Layout files have content, usually HTML, that is meant to wrap other content, such as from Markdown files. A markdown file uses its front matter to specify what layout file to use. Eleventy will then assemble the two and create a folder for the new file. The folder will be named after the markdown file and will contain an index.html file.

Edit the about.md file to add front matter :

---
layout: layout.html
---

# Animals About Page

This is the Animals about page
			

Create a new folder _includes. Inside of that create a file layout.html. This will be the layout template. Eleventy defaults to _includes to find templates files :

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    {{ content }}
</body>
</html>
			

In the about.md file is the front matter that specifies the layout template, in this case _includes/layout.html. Since Eleventy defaults to the _includes folder, that part doesn't need to be added. Below that is the markdown content.

In the layout.html file can be seen a tag {{ content }}. Eleventy will automatically format and insert the content of the about.md here.

The about/index.html file should now have the content :

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <h1>Animals About Page</h1>
    <p>This is the Animals about page</p>
</body>
</html>
			

Folder Structure

Again, Eleventy is for creating static web sites. It assumes there is no database backend or server rendering, that the pages are delivered as they are stored on the web host. It also assumes that the web hosting is intended for static web sites, and does not offer things like redirects or other server processing.

To achieve the preferred URL style of domain/folder/ as opposed to page names like index.html, it creates a folder for every page that would be delivered, which then contains an index.html. Since index.html is always a default for web servers, it is not needed in the URL, providing a clean address structure. The index.html also helps prevent exposing any other files that might be in that folder, thus adding a little more security.

Layouts and Markdown With Front Matter

Both layout and markdown files can contain and use front matter as well as markdown content.

Add a variable in the about.md file :

---
layout: layout.html
title: Animals About Page 2
---

# {{ title }}

This is the Animals about page version 2
			

You should see the <H1> text of the About page change to match the title variable.

Add a variable in the layout.html file :

---
disclaimer: This is a disclaimer from layout.html
---
<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    {{ content }}
    <p>{{ disclaimer }}</p>
</body>
</html>
			

The front matter disclaimer variable should appear in the About page as well as the markdown and front matter from the markdown. You should also see that the title variable carried over from the markdown.

Now try adding a title variable to the layout front matter.

---
disclaimer: This is a disclaimer from layout.html
title: Title from layout.html
---
<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    {{ content }}
    <p>{{ disclaimer }}</p>
</body>
</html>
			

The title on the page should not change. Eleventy has a cascade that prioritizes which variables are finally applied. In this case, the markdown front matter wins out. In the layout file, try changing it to this :

---
disclaimer: This is a disclaimer from layout.html
title2: Title from layout.html
---
<!DOCTYPE html>
<html>
<head>
    <title>{{ title2 }}</title>
</head>
<body>
    {{ content }}
    <p>{{ disclaimer }}</p>
</body>
</html>
			

Now the layout front matter title shows up instead. More information about Eleventy's data cascade can be found here.

Collections

A Collection groups data based on a common tags value. If the front matter in a markdown file contains a particular tags value, that markdown will be included in a collection and provided to templates that call for it. The tags variable can contain multiple values, which means the same markdown can belong to multiple collections.

We'll be creating a set of Blog Post markdown files which use _includes/layout.html, so you'll need to revert it so that you're using the markdown file's title:

---
disclaimer: This is a disclaimer from layout.html
---
<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    {{ content }}
    <p>{{ disclaimer }}</p>
</body>
</html>
			

Create a markdown file post-01.md.

---
tags: post
title: Blog Post 01
date: 2019-01-01
layout: layout.html
---

# First Blog Post
Welcome to the blog.
			

Create a postlist.html as well:

<!DOCTYPE html>
<html>
<head>
    <title>Blog Posts</title>
</head>
<body>
    <ul>
        {% for post in collections.post -%}
        <li>{{ post.data.title }}, {{ post.data.date }}</li>
        {% endfor -%}
    </ul>
</body>
</html>
			

As can be seen, there is a for loop cycling through collections.post. The collections object contains the post collection created by the tag "post" in the markdown page's front matter.

A new folder _site/postlist should appear, containing an index.html file. The file should contain :

<!DOCTYPE html>
<html>
<head>
    <title>Blog Posts</title>
</head>
<body>
        <li>Blog Post 01, Mon Dec 31 2018 19:00:00 GMT-0500 (Eastern Standard Time)</li>
</body>
</html>
			

There should also be a new folder _site/post-01, containing an index.html file. This is the actual permalink page for the post. The file should contain:

<!DOCTYPE htm>
<html>
<head<
    <title>Blog Post 01</title>
</head>
<body>
    <h1>First Blog Post</h1>
    <p>Welcome to the blog.</p>

    <p>This is a disclaimer from layout.html</p>
</bod>
</htm>
			

This is the post markdown using the original layout template created before.

Create two more markdown files, post-02.md and post-03.md.

---
tags: post
title: Blog Post 02
date: 2019-01-02
layout: layout.html
---

# Second Blog Post
Down to business.
			
---
tags: post
title: Blog Post 03
date: 2019-01-03
layout: layout.html
---

# Third Blog Post
Even more news today.
			

The _site/postlist/index.html file should now look like:

<!DOCTYPE html>
<html>
<head>
    <title>Blog Post</title>
</head>
<body>
    <ul>
        <li>>Blog Post 01, Mon Dec 31 2018 19:00:00 GMT-0500 (Eastern Standard Time)</li>
        <li>>Blog Post 02, Tue Jan 01 2019 19:00:00 GMT-0500 (Eastern Standard Time)</li>
        <li>>Blog Post 03, Wed Jan 02 2019 19:00:00 GMT-0500 (Eastern Standard Time)</li>
    </ul>
</body>
</html>
			

And you should have two more folders, _site/post-02 and _site/post-03 with their index.html files.

It can be seen that Eleventy gathered up all the markdown files with the post tag, and included them in the list items in postlist/index.html.

To allow better organizing, the three post-*.md files can be moved from the root into a dedicated folder, e.g. posts. Eleventy will still process them the same way, except the post-* folders will be under _site/posts now.

Linking to a Collection Item

To turn the list items in postlist/index.html into links, edit postlist.html to add {{ post.url }} as a link :

<!DOCTYPE html>
<html>
<head>
    <title>Blog Posts</title>
</head>
<body>
    <ul>
        {% for post in collections.post -%}
        <li><a href="{{ post.url }}">{{ post.data.title }}, {{ post.data.date }}</a></li>
        {% endfor -%}
    </ul>
</body>
</html>
			

The resulting list items should all now look similar to this :

<li><a href="/posts/post-01/">Blog Post 01, Mon Dec 31 2018 19:00:00 GMT-0500 (Eastern Standard Time)</a></li>
			

Collections and Markdown Content

When a markdown file uses a layout template, that template only uses the content found in that specific markdown, via the {{ content }} value. As noted previously, that content is preformatted as HTML before insertion into the layout.

However, when using the collection object, the markdown content must be acquired from the particular collection being iterated. In the above example, the value would be found in post.templateContent. Note that it is not part of post.data.

The post.templateContent is not raw data, but is the preformatted HTML. But as part of a collection, Eleventy considers the content a value, and will encode it as character entities before inserting it into the template, so that the HTML code displays on the page. To preserve the HTML tags, post.templateContent can be piped to the safe filter.

To see this work, add post.templateContent and safe to postlist.html :

<!DOCTYPE html>
<html>
<head>
    <title>Blog Posts</title>
</head>
<body>
    <ul>
        {% for post in collections.post -%}
        <li><a href="{{ post.url }}">{{ post.data.title }}, {{ post.data.date }}</a>
        {{ post.templateContent | safe }}
        </li>
        {% endfor -%}
    </ul>
</body>
</html>
				

This should result in the formatted content for each post appearing below the links in the list.

Eleventy and Date Values

It can be seen that Eleventy is not handling date as a string but as a date value, and assumes date is entered as a UTC time, and then adjusts it for the local time zone.

Another thing about date is that it is a variable generated by Eleventy anyway, based on the file creation date. This means that even if there was no date in the front matter, it would still be available to templates. Adding your own date value in front matter overrides the automatic value.

If the front matter has a value with the form of YYYY-MM-DD, Eleventy will process it as a date, regardless of the variable name. And if that format is seen in the filename, Eleventy will let that override the file creation date.

The timezone and the format of the date can be changed. Refer to the article on using a filter to format a date.