A blog is mostly text, so you don't want a database or a running app behind it — you want plain HTML that a web server can hand out instantly. Eleventy (11ty) is a static-site generator: you write posts in Markdown, run one command, and it produces a folder of finished HTML pages. This guide builds that blog, then covers the part most tutorials skip: where the build runs, and how the output gets onto Falix.
| At a glance | |
|---|---|
| You're building | A Markdown blog compiled to static HTML by Eleventy |
| You need | Node to run the build; the static-site setup to serve the output |
| Plan | Any plan |
| Time | About forty minutes |
New to static hosting? Read Host a static website first — it's where the finished pages end up.
What you're building
| Piece | File |
|---|---|
| Build config | .eleventy.js — input/output folders, a date filter |
| Layout | src/_includes/base.njk — the HTML wrapper every page shares |
| Home page | src/index.njk — lists your posts |
| Posts | src/posts/*.md — one Markdown file per post |
| Output | _site/ — the finished static site Eleventy generates |
The files
package.json — Eleventy as a dev dependency, plus a build script:
{
"name": "blog-eleventy",
"version": "1.0.0",
"private": true,
"scripts": {
"build": "eleventy"
},
"devDependencies": {
"@11ty/eleventy": "^3.0.0"
}
}
.eleventy.js — the configuration:
module.exports = function (eleventyConfig) {
// Copy the stylesheet straight through to the output folder.
eleventyConfig.addPassthroughCopy("src/style.css");
// A tiny date filter so templates can print "2026-07-01".
eleventyConfig.addFilter("date", (d) => new Date(d).toISOString().slice(0, 10));
return {
dir: { input: "src", includes: "_includes", output: "_site" },
markdownTemplateEngine: "njk",
htmlTemplateEngine: "njk",
};
};
src/_includes/base.njk — the shared page wrapper:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ title }}</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<header><a href="/">My Blog</a></header>
<main>{{ content | safe }}</main>
</body>
</html>
src/posts/posts.json — directory data that gives every post the layout and a shared tag (so they form a collection):
{
"layout": "base.njk",
"tags": "post"
}
src/index.njk — the home page, listing posts newest-first:
---
layout: base.njk
title: My Blog
---
<h1>My Blog</h1>
<ul>
{% for post in collections.post | reverse %}
<li>
<a href="{{ post.url }}">{{ post.data.title }}</a>
<small>{{ post.date | date }}</small>
</li>
{% endfor %}
</ul>
src/posts/hello-world.md — a post is just Markdown with a title and date:
---
title: Hello, world
date: 2026-07-01
---
# Hello, world
This is my first post, written in **Markdown**. Eleventy turns this file into
`/posts/hello-world/index.html` when it builds.
Add a src/style.css for looks, and drop in more .md files to add posts.
Build it
Eleventy runs on Node, so build it where Node lives — your own computer, or a Node server (more on that below). In the project folder:
npm install
npx @11ty/eleventy
You'll see it write the pages:
[11ty] Writing ./_site/index.html from ./src/index.njk
[11ty] Writing ./_site/posts/hello-world/index.html from ./src/posts/hello-world.md
[11ty] Copied 1 Wrote 3 files in 0.05 seconds (v3.1.6)
The _site/ folder now holds a complete static site — a home page that lists your posts, one HTML page per post, and your CSS copied across. That folder is everything you deploy.
🎯 Good to know: Everything in
_site/is plain HTML — no Node, no Eleventy, nothing running. Whatever serves it just needs to hand out files, which is exactly what the static-site setup does.
Get it onto Falix
Here's the honest part: Eleventy is a build tool (needs Node) and the static-site setup is a web server (nginx, no Node). They're two different jobs, so you have a choice about where the build happens.
Path A — build locally, upload the output (recommended)
- Run
npx @11ty/eleventyon your computer. - Deploy the static-site setup to a server.
- Upload the contents of
_site/into that server'spublic/folder — drag them in the File Manager, or push over SFTP. - Open your server's address. The blog is live.
This is the simplest and most reliable option: nginx serves finished files, there's no build to break on the server, and nothing of yours has to keep running.
Path B — build on a server with Git
Let Falix rebuild on every push, using Git deploy with a build step:
-
Connect your repo on the Git page and add a post-deploy command
npx @11ty/eleventy(see Build steps). -
The catch: the command runs where your server's application can run it. Eleventy needs Node, which the PHP Web Server (static-site) image doesn't have — so to build on the server you run it on a Node.js application and serve
_site/yourself with a tiny static server:const express = require('express'); const app = express(); app.use(express.static('_site')); const PORT = process.env.SERVER_PORT || 8080; app.listen(PORT, '0.0.0.0', () => console.log(`Listening on port ${PORT}`));Point the Main file at this
index.js, addexpresstopackage.json, and set the build script to run on deploy. Now agit pushrebuilds and serves in one step — at the cost of running a Node process instead of nginx.
| Path A: build locally | Path B: build on server | |
|---|---|---|
| Runs on | static-site (nginx) | Node.js application |
| Server needs Node | no | yes |
| Rebuild on push | manual re-upload | automatic via Git |
| Best for | simplest, most reliable | frequent posts, hands-off |
💡 Tip: Most blogs post rarely, so Path A is usually the right call — build when you write, upload once. Reach for Path B when you're pushing often and want it automated.
Make it yours
- A real theme. Flesh out
base.njkandstyle.css; Eleventy stays out of your way. - Tags and an archive. Eleventy builds collections from tags — add tag pages that list matching posts.
- An RSS feed. Generate
feed.xmlfrom your posts collection so readers can subscribe. - Drafts. Give a post
draft: trueand filter it out of the collection until it's ready.
Everything past the Falix layer is standard Eleventy — the official docs at 11ty.dev cover layouts, collections, data, and plugins in full.
Troubleshooting
eleventy: not found— you didn'tnpm installfirst, or you're not in the project folder. Install, then usenpx @11ty/eleventy.- Home page is blank / no posts listed — the posts aren't in the
postcollection. Checksrc/posts/posts.jsonsets"tags": "post"and your posts are insrc/posts/. - A post shows raw Markdown — it's missing the layout. The
posts.jsonabove assignsbase.njkto everything in the folder; make sure the file is there. - Deployed but 404 on the home page — after uploading, the web root must contain
index.htmldirectly (upload the contents of_site/, not the_sitefolder itself). See Host a static website.