Skip to content

Deploy a Build Awesome site

Publish a Build Awesome (formerly Eleventy) site on your own domain, from your computer or from GitHub Actions. The package names and config file in the code below (@11ty/eleventy, eleventy.config.js) are the ones current releases use.

Build command npx @11ty/eleventy (in most projects, npm run build)
Output folder _site
Settings you need Your site URL; _redirects and _headers copied to the site root if you use them
Routing Build Awesome’s default permalinks (/about/ → about/index.html) work as they are

You need:

  • A Build Awesome site that builds on your computer.
  • An Evolving Edge account that can deploy workloads. See Getting Started.
  • A project in the portal, and its project ID (it starts with proj_).
  • A deploy token from the portal, under Workload → Deploy Tokens, with workload:write. Scope it to the project. See Deploy tokens.
  • The domain you want to serve the site on, for example www.example.com, and access to its DNS settings.
  • Node.js 22.12 or later, on Windows (x64), macOS, or Linux (x64 or arm64).

Build Awesome has no single “site URL” setting: each project keeps it wherever its feeds and templates read it. In the eleventy-base-blog starter it lives in two places, and the feed reads only the second:

_data/metadata.js
export default {
url: "https://www.example.com/",
// ...
};
// eleventy.config.js, in the feed plugin's options
metadata: {
base: "https://www.example.com/",
// ...
},

Build once and search _site/feed/feed.xml (or your sitemap) for the old URL, to make sure you’ve caught every place.

Don’t use --pathprefix: your site is served from the root of the domain.

Only the project that claimed a domain can deploy to it, so claim it before your first deploy. In the portal, or from the command line:

Terminal window
export EE_CDN_TOKEN=<your deploy token>
npx -p @evolving-edge/ee-cdn-cli ee-domain claim www.example.com --project proj_abc123 --wait

It prints a TXT record and a CNAME record to add at your DNS provider, then waits until the domain is active. See Custom domains for the portal steps, root domains and Cloudflare.

Terminal window
npm run build
npx @evolving-edge/ee-cdn-cli _site --domain www.example.com --project proj_abc123 --trailing-slash
  • --trailing-slash makes /about redirect to /about/, where Build Awesome put the page. Without it, a link that leaves the slash off is a 404.
  • ee-deploy finds _site by itself if you leave the folder out.
  • Each deploy replaces the whole site on that domain. Allow up to about 90 seconds for a new deploy to reach every node.

In your repository settings, add:

  • a secret EE_CDN_TOKEN holding your deploy token
  • variables EE_DOMAIN (for example www.example.com) and EE_CDN_PROJECT_ID

Then create .github/workflows/deploy.yml:

name: Deploy to Evolving Edge
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ee-deploy
cancel-in-progress: false
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- name: Cache fetched files and images
uses: actions/cache@v4
with:
path: ./.cache
key: ${{ runner.os }}-eleventy-fetch-cache
- run: npm ci
- run: npm run build
- name: Deploy
env:
EE_CDN_TOKEN: ${{ secrets.EE_CDN_TOKEN }}
EE_CDN_PROJECT_ID: ${{ vars.EE_CDN_PROJECT_ID }}
run: npx --yes @evolving-edge/ee-cdn-cli _site --domain ${{ vars.EE_DOMAIN }} --trailing-slash

The .cache step keeps the results of @11ty/eleventy-fetch and @11ty/eleventy-img between runs. Leave it out if you don’t use them.

Redirects. Add a _redirects file:

/old-post/ /blog/new-post/ 301
/notes/* /blog/:splat 301

It has to end up at the root of _site, and Build Awesome only copies files it’s told to:

  • eleventy-base-blog: put _redirects (and _headers) in public/. The starter already copies that folder to the site root.

  • Other projects: put the files at the project root and add a passthrough copy:

    eleventy.config.js
    eleventyConfig.addPassthroughCopy("_redirects");
    eleventyConfig.addPassthroughCopy("_headers");

Rules can be 301 or 302, and * and :splat wildcards work. Redirects apply to public (Level 0) sites.

404 page. Add a template with permalink: 404.html (see the 404 tip in Build Awesome’s docs). The base blog already has one. Evolving Edge serves it, with a 404 status, for any address that doesn’t exist. See Custom 404 pages.

Caching. HTML pages are checked on every request, so a new deploy shows as soon as it reaches the nodes. Other files are cached for an hour. @11ty/eleventy-img names its output by content hash. If you write images to a folder of their own (for example with urlPath: "/img/"), you can cache that folder for a year with a _headers file, copied the same way as _redirects:

/img/*
Cache-Control: public, max-age=31536000, immutable

Only do this for a folder where every file name carries a hash. See Caching hashed assets for a year.

  • Path prefixes. A site owns its whole domain, so --pathprefix isn’t used.
  • Serverless and Edge. Version 3 removed them. If an older site still depends on Netlify Functions, that part needs another home.
  • Deploy previews for each pull request. To preview, deploy to a second domain.
What you see Why What to do
/about is a 404 but /about/ works The trailing-slash redirect isn’t on Deploy with --trailing-slash
Redirects in _redirects don’t work The file wasn’t copied into _site Check that _site/_redirects exists; if not, move it to public/ (base blog) or add a passthrough copy
The feed still shows https://example.com/ The URL is set in one place but not the other Set it in both _data/metadata.js and the feed plugin’s metadata.base
A page built with permalink: /about.html isn’t found at /about The page is a flat file Deploy with --clean-urls, or use a folder permalink such as /about/
The deploy is refused for your domain The domain isn’t claimed for this project Claim it first
No deploy token EE_CDN_TOKEN isn’t set Export it, or add the repository secret
An authorisation error on upload The token is scoped to a project and no project was given Pass --project (or set EE_CDN_PROJECT_ID)

More in the command line troubleshooting.