Publishing an Eleventy Site on GitHub Pages #
I wanted a simple-to-maintain, totally customizable web site that made content updating easy, so I chose Eleventy. I've enjoyed using the framework, but I also really wanted to host it on GitHub Pages, since I already pay GitHub. But, while GitHub Pages has out-of-the-box support for other frameworks, not Eleventy. Here's how I got my Eleventy site to automatically publish to GitHub Pages every time I make a push to
What's an Eleventy? #
How to Publish Your 11ty Site on GitHub Pages #
There are two ways to do this:
- Directly publish your output to Pages, leveraging work already done to support GitHub's default Jekyll pages
- Use your own action
I tried 1 first, and then ended up with 2.
Option One: Publish Directly With GitHub Pages #
If you read a lot of blogs on how to do exactly this, they'll advise you to:
- Select the "Classic Pages Experience"
- Use PeaceIris's GitHub Pages Action to do the packaging and publishing
This is really appealing, and it's where I started too. In particular, it's appealing because that Action has a ton of tests, and who wants to write their own Action with that many tests for a simple publish?
This worked great for me, until it didn't, when I discovered that the robust Action code, designed to handle tons of edge cases, couldn't handle mine. Some troubleshooting showed me how I could fix the issue, but I realized that relying on someone else's code so much had left me with a site I'd have a hard time supporting over the long term... which is kind of the opposite of the point of using an SSG and GitHub Pages. Like many a nerd before me, I just wanted to understand exactly what was going on.
Option Two: Roll Your Own Action #
I didn't know a lot about GitHub Actions going into this, but it turns out the page publishing workflow is pretty simple, and pretty well-documented by GitHub.
So I made my own, and it was pretty simple.
The top does two things:
# Must have `on: workflow_dispatch` to enable manual run from Actions tab
Initially, I set the Action to run when there's a push to
main. I also have
workflow_dispatch, because, without that, there's no button to manually run the action.
This sets up permissions for the Action and the token it will get.
# Allow one concurrent deployment
It's not clear to me that this is relevant to my needs, but, certainly if one were running a complex Action, this would be needed. I used it because I did go wild with
git pushes once and overran my hourly rate limit for GitHub Actions.
Now I run the first step of the process, the step that builds the pages.
- name: Setup pages
- name: Checkout repo
- name: Setup Node $NaN
This starts the set-up for building the site. I'm running 3 Actions that are pre-built by GitHub:
- Configure Pages — This can do a lot more than I'm using it for, but the basic config is all that's needed here
- Setup Node
Having completed this setup, I can actually run Node commands:
- name: Install dependencies
run: npm install
- name: Build
run: npm run build
build is an action that I set up in my
package.json, use whatever command you use to create your site.
Here, the site is built; but I need to ensure it's ready for GitHub's Pages Servers.
- name: Fix permissions
chmod -c -R +rX "_site" | while read line; do
echo "::warning title=Invalid file permissions automatically fixed::$line"
- name: Upload artifact
The permissions fix is something I can probably get rid of, but some documentation called it out as potentially needed.
Upload Artifact step
tars up an archive of the created site in the format Pages servers require.
Now we flow into the second step, deploying the site. This is much simpler than the build.
- name: Deploy to GitHub pages
Having built the site, I tell the
deploy action to actually put it on there, and provide the output as a configuration argument for the Pages environment.
And that's it! A site of my own! Now to make it good...
And I know if I hosted the site on S3 somehow I'd make it cost me $150/month. ↩︎
Or, you know, occasionally building them and then caching them very aggressively ↩︎
It's just 10 builds per hour ↩︎
My package.json basically has the build do some cleanup and setup actions, as well as build only non-