A lightweight, server-side rendering prototype that turns Handlebars-flavoured Markdown into fully styled web pages using the Holiday Extras brand system.
Live demo: hx-markdown-rendering.herokuapp.com
Holiday Extras has a Stories-based content platform where content is authored in Handlebars Markdown — plain Markdown files enriched with Handlebars template syntax for dynamic data injection. This project is a rendering engine that takes those files and outputs fully styled, production-quality HTML.
The core idea is a clean separation of concerns:
| Layer | Technology | Responsibility |
|---|---|---|
| Content | Markdown (.md) |
What to say — authored by content teams |
| Data | JSON (.json) |
Structured product/page data |
| Presentation | EJS templates | How to render it |
| Design | CSS (HX tokens) | Brand colours, typography, spacing |
Because the content lives in plain Markdown, it is human-readable, AI-readable, and version-controllable. An AI agent can read the same .md files that power the UI — no special export or transformation needed.
-
Content portability — the same Markdown source can be rendered into web pages today, and adapted for email, native apps, or print later without changing how content is authored.
-
AI compatibility — LLMs can read and reason about Markdown natively. Keeping content in
.mdfiles means AI tools (Claude, Copilot, etc.) can understand, summarise, and generate content in the same format the platform already uses. -
Speed of iteration — adding a new page or screen is a new
.mdfile and a JSON data file. No new routes, no new components, no deployment pipeline changes beyond a git push. -
Brand consistency — all rendering goes through a single CSS file built on the official HX design tokens, so every output is on-brand by default.
content/hotels.md ← frontmatter: template, data source, title
content/data/hotels.json ← product data (or live from API)
views/layout.ejs ← EJS template
views/partials/ ← reusable EJS partials
public/styles.css ← HX design tokens → CSS custom properties
server.js ← Node HTTP server, renders on request
renderer.js ← parses frontmatter, merges data, renders EJS
api.js ← fetches live data from HAPI, maps to template shape
A request to /hotels:
server.jsfetches live hotel data from the HAPI API viaapi.jsrenderer.jsreadscontent/hotels.md, parses the frontmatter, and merges the data- EJS renders
views/layout.ejswith the product data - Fully-formed HTML is returned — no client-side rendering, no JavaScript required
| Page | Route | Description |
|---|---|---|
| Index | / |
This index — links to all examples |
| Hotel product list | /hotels |
Live product cards from the HAPI hotels API |
| Booking extras | /extras |
Extras selection screen with checkboxes |
npm install
npm run dev # starts with --watch for auto-reloadThen open http://localhost:3000.
- More page templates: search results, booking confirmation, upsell screens
- Parameterised API queries so the hotel list reflects real search context
- Email rendering mode — same Markdown, different EJS template outputs inline-CSS HTML
- Investigate using Markdown as the AI agent's primary interface for reading and writing content
- Content authoring guide for the team