Eleventy + Markdown + CoffeeScript = ❤
Tags: eleventy, markdown, coffeescript, jamstack
Published: 2020-10-16 15:12:34

---
title: Eleventy + Markdown + CoffeeScript = ❤
date: 2020-10-16 14:12:00 UTC
tags: [eleventy, markdown, coffeescript, jamstack]
canonical_url: https://www.denizaksimsek.com/2020/coffeescript-frontmatter/
published: true
---

I’ve started using CoffeeScript instead of YAML for frontmatter, and it works like a dream. [Endorsed by Zach Leatherman](endorsed).

[endorsed]: https://twitter.com/zachleat/status/1340057504567488513

## Markdown with Frontmatter

As far as I know, Jekyll is the origin of using a YAML block at the top of a Markdown file for metadata. It’s not hard to imagine why this became popular — associating prose with data is a common use case, and though they have their issues, both Markdown and YAML look pretty<sup><a href="#fn1" id="fnref1">[1]</a></sup>.

## Eleventy Frontmatter

Eleventy uses frontmatter blocks (delimited by `---`) for all kinds of files. Markdown posts, HTML partials and Nunjucks/EJS/Liquid/… templates can all have them. The data in the frontmatter can then be used in templates. In the following, `title` is not a reserved name:

```
---
title: 'A Blog Post'
---

# {title}

Lorem ipsum dolor sit amet...
```

We could have used `name`, `heading` or `kdsad983erj33`.

* * *

Eleventy’s [“Computed Data”](https://www.11ty.dev/docs/data-computed/) feature relies on functions in the frontmatter. As YAML doesn’t have functions, you are expected to use JS (well, you can use template strings I guess…):

```
---js
{
  title: "My page title",
  eleventyComputed: {
    currentDate: () =>
      new Date().toLocaleString() 
  }
}
---
<!doctype html>
<html>
<!-- … -->
<body>
  <h1>{{title}}</h1>
  <p>Published on {{currentDate}}</p>
  <!-- … -->
```

Computed data is cool. Among other things, it allows me to move logic away from my templates and express it in an actual programming language. However JS frontmatter is not very pretty, and I don’t want to convert my whole frontmatter just for one function.

If only there was a language that had the expressive power of JS, and the visually clean data notation of YAML…

## CoffeeScript All The Time!

CoffeeScript is actually mentioned in the GitHub repo for `gray-matter`, the library Eleventy uese to parse frontmatter. Compared to YAML, it’s not much more verbose:

<table><tr><td><pre><code class="language-md">
---
title: Street sign in İstanbul
date: 2020-10-10T19:27:39+03:00
tags:
- place
- design
uPhoto: /assets/photos/IMG20201007085906-02.jpeg
türkçe: /2020/istanbul-sokak-tabelasi/
---

&lt;!-- YAML -->
</code></pre>
<td><pre><code class="language-md">
---
title: 'Street sign in İstanbul'
date: '2020-10-10T19:27:39+03:00'
tags: ['place', 'design']
uPhoto: '/assets/photos/IMG20201007085906-02.jpeg'
türkçe: '/2020/istanbul-sokak-tabelasi/'
---

&lt;!-- CoffeeScript -->
</table>

The CoffeeScript code above is actually fully YAML-compatible! This keeps my templates portable. And with computed data:

```
---
layout: 'layout'
eleventyComputed:
  syndicationLinks: (data) ->
    DEV: data.devToSyndication[data.page.url]
---

<article class="h-entry">
<!-- ... -->
{%for silo, link in syndicationLinks%}
  <a class="u-syndication" href="{{link}}">{{silo}}</a>
  {%if not loop.last%} | {%endif%}
{%endfor%}
```


I think that computed frontmatter gives a nice balance of logic-less<sup><a href="#fn2" id="fnref2">[2]</a></sup> and logic-full templates.

* * *

<section>
<ol>
<li id="fn1">
<p>“It looks pretty” is often what people really mean when they call something “human-readable”. <a href="#fnref1">↩︎</a></p>
</li>
<li id="fn2">
<p>Logicless templates: For people who will never need to make an HTML monthly calendar! <a href="#fnref2">↩︎</a></p>
</li>
</ol>
</section>