Tutorials
Nunjucks tutorial
Server-rendered macros for Eleventy, Express, or any Node templating pipeline — the GOV.UK-style approach, with Lily's catalog and class hooks.
What you'll build
A small server-rendered contact form — labelled input, submit button, zero JavaScript payload — first bare, then styled, in about 10 minutes.
Before you start
You need git, Node 22 or later, and pnpm 10 or later. Any Nunjucks pipeline works — Eleventy, Express, or plain Nunjucks.
Step 1 — Get the code
git clone https://github.com/LilyDesignSystem/lily-design-system-nunjucks-headless
cd lily-design-system-nunjucks-headless
pnpm install
pnpm test # vitest rendering every macro Each component is a directory in components/ with a macro.njk, its test, and its docs — for example components/button/macro.njk. Point your Nunjucks loader at components/ (in Eleventy, add it to the includes path) and
import what you need.
Step 2 — Your first component
{% from "components/button/macro.njk" import button %}
{{ button({ text: "Save", type: "submit" }) }} Renders <button class="button" type="submit">Save</button>.
Macros take a single params object: text (escaped) or html (raw), type, label for an aria-label, and a class hook appender.
Step 3 — Compose a small form
{% from "components/form/macro.njk" import form %}
{% from "components/label/macro.njk" import label %}
{% from "components/text-input/macro.njk" import textInput %}
{% from "components/button/macro.njk" import button %}
<form class="form" method="post">
<div class="field">
{{ label({ for: "name", text: "Full name" }) }}
{{ textInput({ id: "name", name: "name", required: true }) }}
</div>
{{ button({ text: "Save", type: "submit" }) }}
</form> Because everything renders on the server, the browser receives pure semantic HTML with the class hooks — a JavaScript payload of zero bytes.
Check your work: load the page and the form looks plain — exactly as intended: styling is still ahead. Press Tab: focus moves through every control, the label is announced, and submit works. The behaviour is done; the look is yours, and it's next.
Step 4 — Style it
Style the hooks — .button, .text-input, .label, .field — in your stylesheet, or link a
ready-made theme in your base layout:
<link rel="stylesheet" href="/themes/united-kingdom-government-digital-service.css" /> Step 5 — See it all working
The Nunjucks + Eleventy example app builds the full catalog as a static site with per-component demo pages:
git clone https://github.com/LilyDesignSystem/lily-design-system-nunjucks-eleventy-examples
cd lily-design-system-nunjucks-eleventy-examples
pnpm install && pnpm run dev Next steps
- Theming — including the Eleventy cookie pattern for flash-free SSR theme switching.
- Preference helpers — language and text size.
- Component catalog — props, ARIA, and keyboard per component.
Questions along the way? The help page is full of answers — and if a step could be clearer, tell us and we'll gladly improve the tutorial.