Return to Home

Step 4. Templating with WebC

So, you have a sort of website that's working which goes to show you how little you actually need of a lot of the cruft of various software. It's not much of one though, it is just some disparate pieces of HTML. You probably want to add the rest of an HTML document around it, attach styles, JS, maybe even one of those annoying corpo JS frameworks like React or one of the good ones like Svelte.

There are some great choices for templating in 11ty and I personally was a longtime user of Nunjucks. However, I only use two types of templates nowadays in 11ty, Markdown and WebC. Markdown is great for writing and reading by humans or machines and is ideal for translating onto the web. WebC is a first class vanilla component framework that once you try, you'll never want to use any other option.

From here on out, I'll only be using WebC for templating. I have added a recommended extension for VSCode to help with WebC syntax highlighting and snippets at this commit. Let's create that master template we talked about earlier by creating a special file known as a layout. Layouts in 11ty are stored in a special folder named /_includes. Create a file named root.webc in that folder. To use this layout, we need to hook up the first party WebC plugin and assign this new layout to any template we want to use it.

We install the plugin with Bun using bun i -D @11ty/eleventy-plugin-webc and then add it to the 11ty config with the line:

import pluginWebc from "@11ty/eleventy-plugin-webc";

...

eleventyConfig.addPlugin(pluginWebc);

Let's try out the layout by going back to our index.md and adding the Front Matter:

---
layout: root.webc
title: Home
---

Now type anything into the root.webc file. Let's boot up the dev server and see what happens. Oh, we see the text we typed in the layout but nothing from the template. That's because we need to add a slot for the content in the layout. We'll be running through some WebC features as we go but understand that WebC is just HTML.

Into the root.webc file, add the following:

<template @raw="content" webc:nokeep></template>

Now in the browser if the dev server is still running, you should see the content from the index.md file. We've taken the template element and called the @raw directive with the special "content" argument that will render child templates. <template> elements are a great element to use for this purpose as they won't render anything into the DOM themselves, and the webc:nokeep attribute tells 11ty to not keep the template element in the final output, only the child content.

Let's add the rest of the simple HTML body indo root.webc:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
  <template @raw="content" webc:nokeep></template>
</body>
</html>

Now you can see that /_site/index.html file has a full HTML document structure around it. You should add this layout to Front Matter of any other templates for now. While I'm in here I'll move title into the Front Matter as well.

For some of these pages, we might want full control over every last bit of HTML displayed. For these blog articles, I think I would rather have a default template with standard items like titles and metadata. So let's create another layout to use for these blog articles.

Create a file named blog.webc in the /_includes folder with the following content:

---
layout: root.webc
---

<article> <h1 @text="title"></h1>

<template @raw="content" webc:nokeep></template>

<footer> Tags: <blog-tag webc:for="tag of tags" @text="tag" /> </footer> </article>

Wow! Simple but cool, yeah? What's the \<blog-tag\> element? I don't recommend using spans or divs so it's a custom element I made up. This syntax is nice but WebC has a lot more substance than just nice syntax. In the next step we'll look at WebC components.

Before we leave let's clean refactor one thing. If you recall in the data article, we could use directory data files. Let's do that here, creating /blog/blog.json with:

{
    "tags": ["blog"],
    "layout": "blog.webc"
}

Now the blog layout will be assigned to all these files and we can delete the Front Matter entry. If inside of an article we have a Front Matter entry like:

---
title: A Lunch
tags: [lunch]
---

then the article will have the tags "blog and "lunch."

Return to Home