Skip to content

Deploying Eleventy on Hop3

This guide deploys with the build-on-server strategy — Hop3 runs the generator on each deploy. For the concepts and the alternative (build your site at the source and deploy the assets), see the Static Sites overview.

This guide walks you through deploying an Eleventy (11ty) static site on Hop3. Eleventy is a simpler static site generator with zero-config by default.

Prerequisites

Before you begin, ensure you have:

  1. A Hop3 server - Follow the Installation Guide
  2. The Hop3 CLI - Installed on your local machine
  3. Node.js 18+ - Install from nodejs.org
  4. Git - For version control and deployment

Verify your local setup:

node -v

Step 1: Create a New Eleventy Site

mkdir hop3-tuto-eleventy && cd hop3-tuto-eleventy && npm init -y
package.json

Install Eleventy:

npm install @11ty/eleventy
added

Step 2: Create Site Structure

Create the source directory:

mkdir -p src/_includes src/_data src/posts

Create the base layout:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ title }} | My Site</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 2rem;
            line-height: 1.6;
        }
        header {
            border-bottom: 1px solid #eee;
            padding-bottom: 1rem;
            margin-bottom: 2rem;
        }
        nav a {
            margin-right: 1rem;
        }
        .hero {
            background: linear-gradient(135deg, #222 0%, #444 100%);
            color: white;
            padding: 3rem;
            border-radius: 8px;
            text-align: center;
            margin-bottom: 2rem;
        }
        .hero h1 { font-size: 2.5rem; margin-bottom: 0.5rem; }
    </style>
</head>
<body>
    <header>
        <nav>
            <a href="/">Home</a>
            <a href="/about/">About</a>
            <a href="/posts/">Blog</a>
        </nav>
    </header>
    <main>
        {{ content | safe }}
    </main>
    <footer>
        <p>&copy; {{ site.year }} My Eleventy Site on Hop3</p>
    </footer>
</body>
</html>

Create site data:

{
  "name": "My Eleventy Site",
  "description": "An Eleventy site deployed on Hop3",
  "year": "2024"
}

Step 3: Create Content

Create the home page:

---
layout: base.njk
title: Home
---

<div class="hero">
    <h1>Hello from Hop3!</h1>
    <p>Your Eleventy site is running.</p>
</div>

<h2>Welcome</h2>
<p>This is an Eleventy static site deployed on Hop3.</p>

<h2>Recent Posts</h2>
<ul>
{%- for post in collections.posts | reverse | limit(5) %}
    <li><a href="{{ post.url }}">{{ post.data.title }}</a></li>
{%- endfor %}
</ul>

Create the about page:

---
layout: base.njk
title: About
permalink: /about/
---

## About This Site

This Eleventy site demonstrates static site deployment on Hop3.

### Features

- **Simple** - Zero-config by default
- **Flexible** - Multiple template languages
- **Fast** - Minimal JavaScript, maximum performance

Create a blog post:

---
layout: base.njk
title: Hello World
date: 2024-01-01
tags: posts
---

Welcome to our Eleventy site on Hop3!

## Getting Started

Eleventy supports multiple template languages:

- Markdown
- Nunjucks
- Liquid
- JavaScript

Create content in the `src/` directory and Eleventy will build your site.

Create a posts listing page:

---
layout: base.njk
title: Blog
permalink: /posts/
---

<h1>Blog Posts</h1>

<ul>
{%- for post in collections.posts | reverse %}
    <li>
        <a href="{{ post.url }}">{{ post.data.title }}</a>
        <small>({{ post.date | date }})</small>
    </li>
{%- endfor %}
</ul>

Step 4: Configure Eleventy

module.exports = function(eleventyConfig) {
  // Copy static assets
  eleventyConfig.addPassthroughCopy("src/assets");

  // Add date filter
  eleventyConfig.addFilter("date", (date, format) => {
    return new Date(date).toISOString().split('T')[0];
  });

  // Add limit filter
  eleventyConfig.addFilter("limit", (arr, limit) => arr.slice(0, limit));

  return {
    dir: {
      input: "src",
      output: "_site",
      includes: "_includes",
      data: "_data"
    },
    markdownTemplateEngine: "njk"
  };
};

Update package.json:

{
  "name": "hop3-tuto-eleventy",
  "version": "1.0.0",
  "scripts": {
    "build": "eleventy",
    "start": "eleventy --serve",
    "serve": "npx serve _site"
  },
  "dependencies": {
    "@11ty/eleventy": "^2.0.0"
  }
}

Step 5: Build and Test

Build the site:

npm run build
Wrote

Verify the build:

ls -la _site/
index.html

Test the build:

grep -o "Hello from Hop3" _site/index.html || cat _site/index.html | head -50
Hello from Hop3

Step 6: Create Deployment Configuration

prebuild: npm install && npm run build
web: npx serve _site -l $PORT
[metadata]
id = "hop3-tuto-eleventy"
version = "1.0.0"
title = "My Eleventy Site"

[build]
before-build = ["npm install", "npm run build"]
packages = ["nodejs", "npm"]

[run]
start = "npx serve _site -l $PORT"

[port]
web = 3000

[healthcheck]
path = "/"
timeout = 30
interval = 60

Deploy to Hop3

The following steps require a Hop3 server.

Initialize (First Time Only)

hop3 init --ssh root@your-server.example.com

Initialize the Git Repository

Hop3 deploys the committed contents of a Git repository. Ignore node_modules (it's rebuilt on the server, and its symlinks can't be archived) and commit:

printf 'node_modules/\n_site/\n.env\n' > .gitignore
git init && git add -A && git commit -m "Initial Eleventy site"

Deploy

Deploy the application (first deployment creates the app):

hop3 deploy hop3-tuto-eleventy
deployed successfully

Set Hostname

Configure the hostname for nginx proxy:

hop3 config set --app hop3-tuto-eleventy HOST_NAME=hop3-tuto-eleventy.$HOP3_TEST_DOMAIN

Wait for Process Stop

Wait for the previous deployment to fully stop:

sleep 5

Apply Configuration

Redeploy to apply the hostname configuration:

hop3 deploy hop3-tuto-eleventy
deployed successfully

Verify Deployment

hop3 app status --app hop3-tuto-eleventy
hop3-tuto-eleventy
curl -s http://hop3-tuto-eleventy.$HOP3_TEST_DOMAIN/
Hello from Hop3

Managing Your Application

# Restart the application
hop3 app restart --app hop3-tuto-eleventy

# View logs
hop3 app logs --app hop3-tuto-eleventy

# View/set environment variables
hop3 config show --app hop3-tuto-eleventy
hop3 config set --app hop3-tuto-eleventy NEW_VAR=value

# Scale workers
hop3 ps scale --app hop3-tuto-eleventy web=2

Advanced Configuration

Custom Filters

// eleventy.config.js
eleventyConfig.addFilter("readableDate", (date) => {
  return new Date(date).toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  });
});

Collections

eleventyConfig.addCollection("featured", (collectionApi) => {
  return collectionApi.getFilteredByTag("featured").reverse();
});

Image Optimization

npm install @11ty/eleventy-img
const Image = require("@11ty/eleventy-img");

eleventyConfig.addShortcode("image", async function(src, alt) {
  let metadata = await Image(src, {
    widths: [300, 600],
    formats: ["webp", "jpeg"]
  });
  return Image.generateHTML(metadata, { alt });
});

RSS Feed

npm install @11ty/eleventy-plugin-rss
const pluginRss = require("@11ty/eleventy-plugin-rss");
eleventyConfig.addPlugin(pluginRss);

Troubleshooting

Build Errors

Check for template syntax errors in Nunjucks files.

Missing Pages

Ensure frontmatter is valid YAML.

CSS Not Loading

Add passthrough copy for assets.

Example hop3.toml

[metadata]
id = "hop3-tuto-eleventy"
version = "1.0.0"
title = "My Eleventy Site"

[build]
before-build = ["npm install", "npm run build"]
packages = ["nodejs", "npm"]

[run]
start = "npx serve _site -l $PORT -s"

[port]
web = 3000

[healthcheck]
path = "/"