A close-up of slightly out-of-focus monthly planner printed on a white paper.
Photo by Eric Rothermel on Unsplash

This will be a short one, mainly for my own fuĀ­ture refĀ­erĀ­ence and for othĀ­ers movĀ­ing to eleventy and facĀ­ing this isĀ­sue. Youā€™ll noĀ­tice this is my third post on eleventy in the past month, and I have no reĀ­grets. I enĀ­joy usĀ­ing it.

Letā€™s get to it.

What are we tryĀ­ing to ļ¬x?

I have a bunch of blog posts in a diĀ­recĀ­tory named _posts, each of which has a YAML front-matĀ­ter. If this set up sounds faĀ­milĀ­iar to you, itā€™s beĀ­cause I moved from Jekyll.

Each blog post has a draft propĀ­erty, which takes a boolean value: true or false.

Whether you use a cusĀ­tom colĀ­lecĀ­tion or the colĀ­lecĀ­tions built by eleventy usĀ­ing the tags front-matĀ­ter — one thing it doesĀ­nā€™t do out of the box is skip buildĀ­ing posts which have a draft value set to true.

This acĀ­tuĀ­ally makes sense. It is not blog-aware like Jekyll is.

Unfortunately, this also means anyĀ­one can view such pages/ā€‹posts even on a pubĀ­lished site, if they are able to guess the permaĀ­link for a draft post or if you forĀ­get to set a meta tag for search enĀ­gines to not inĀ­dex the draft pages or posts.

A straightĀ­forĀ­ward soĀ­luĀ­tion is to just move draft posts to a _drafts diĀ­recĀ­tory, and add it to your .eleventyignore dot ļ¬le.

If that works for you, great.

I use Forestry and not only did I want a more CMS-friendly soĀ­luĀ­tion, but also the abilĀ­ity to see all my draft posts on the deĀ­velĀ­opĀ­ment and stagĀ­ing enĀ­viĀ­ronĀ­ments, but not proĀ­ducĀ­tion.

Thereā€™s a clean soĀ­luĀ­tion to this. šŸ™‚

Tell me more. Whatā€™s the ļ¬x?

@11ty/eleventy, in its 0.11.0 reĀ­lease, feaĀ­tures an elevenĀ­tyĀ­ComĀ­puted propĀ­erty which can be set usĀ­ing a diĀ­recĀ­tory data ļ¬le, among other opĀ­tions.

It alĀ­lows you to dyĀ­namĀ­iĀ­cally set front-matĀ­ter valĀ­ues at build-time. Eleventy comĀ­putes them how you tell it to. Makes sense?

Creating a _posts.11tydata.js ļ¬le unĀ­der the _posts diĀ­recĀ­tory, we can conĀ­trol the front-matĀ­ter data for all of the ļ¬les in this diĀ­recĀ­tory.

We want to specĀ­ify a front-matĀ­ter of permalink: false where draft is true. When a colĀ­lecĀ­tion item is not a draft, we want to reĀ­turn the same permalink value weā€™d have set in the layĀ­out ļ¬les. In my case, I use Liquid, so the variĀ­ables get parsed by Liquid.

// _posts.11tydata.js
module.exports = {
eleventyComputed: {
permalink: data => {
let postPermalink =
"/blog/{{ page.date | date: '%Y/%m/%d' }}/{{ slug }}/";

if (process.env.ELEVENTY_ENV !== "production") return postPermalink;
else return data.draft ? false : postPermalink;
}
}
};

Being able to change the permaĀ­link usĀ­ing comĀ­puted propĀ­erĀ­ties is a speĀ­cial use-case. All other eleventy propĀ­erĀ­ties canĀ­not be overĀ­ridĀ­den like this, alĀ­though you can still set front matĀ­ter for any of your own propĀ­erĀ­ties freely.

The data variĀ­able is passed on by eleventy and inĀ­cludes the front-matĀ­ter data for us to use, so we can use data.draft to check the draft staĀ­tus of each colĀ­lecĀ­tion item, in this case, a blog post.


And there you have it. šŸ¤©

You can use this for any other colĀ­lecĀ­tion just as easĀ­ily. If youā€™d like to conĀ­trol all items built by eleventy, use a Global Data File.

Zach reĀ­leased the 0.11.0 verĀ­sion a couĀ­ple of days ago. Go ahead, upĀ­date, and use comĀ­puted data if you want to! šŸ‘


Update (2020-05-16): You could acĀ­tuĀ­ally just reĀ­turn the permaĀ­link from the front-matĀ­ter itĀ­self! This alĀ­lows you to use a global data ļ¬le withĀ­out reĀ­peatĀ­ing your permaĀ­link strucĀ­ture from your temĀ­plates. It would be like so:

// _posts.11tydata.js
module.exports = {
eleventyComputed: {
permalink: data => {
if (process.env.ELEVENTY_ENV !== "production") return data.permalink;
else return data.draft ? false : data.permalink;
}
}
};

I have imĀ­pleĀ­mented the same in my Smix Eleventy Starter.