This blog was previously powered by Tighten’s Jigsaw project. Even though it’s no longer used, if you’re thinking about starting your own blog, I can still highly recommend it.
Since Jigsaw generates a static website, I chose to host it with GitHub Pages as a "user site" as they allow for top-level domains. GitHub Pages only serve static sites, but as Jigsaw is a dynamic system we need to generate the site. I was able to automate this process with GitHub Actions. It took some trial and error (read: a lot of wip commits) but I was finally able to make it work and wanted to share this setup as I think it’s pretty sweet.
I’ll break this down into two sections, the first, using Jigsaw and GitHub Pages and the second, publishing with GitHub Actions.
Jigsaw & GitHub Pages
Jigsaw provides instructions on how to use GitHub Pages, but it’s written for project sites and not user sites. If you’re not sure why this is a problem, it’s because user sites require that the site contents are in the
master branch, whereas repository sites default to
gh-pages - though that can be changed.
To get this working, I setup Jigsaw under a
source branch which contains all of the code, assets and post content. I then push the contents of the
build_production directory to the
master branch, which GitHub happily serves up for you to read.
It’s a small change, but it may not immediately be obvious, so it’s worth clarifying!
Jigsaw & GitHub Actions
Jigsaw is really, really good but I’m lazy and don’t want to manually be building my website, committing and publishing it after each post.
Admittedly, it took me a lot of time to figure these steps out, but now I’m able to write a new post and have GitHub automatically build and publish it for me!
I created a new workflow under
.github/workflows/build-publish.yml with the following:
name: Build & Publish on: push: branches: - source schedule: - cron: "0 2 * * 1-5" jobs: build-site: runs-on: ubuntu-latest steps: - uses: actions/[email protected] - name: Install Composer Dependencies run: composer install --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist - name: Install NPM Dependencies run: npm install - name: Build Site run: npm run production - name: Create CNAME File run: echo "james.brooks.page" >> build_production/CNAME - name: Stage Files run: git add -f build_production - name: Commit files run: | git config --local user.email "[email protected]" git config --local user.name "GitHub Actions" git commit -m "Build for deploy" - name: Publish run: | git subtree split --prefix build_production -b master git push -f origin master:master git branch -D master
It may look complicated, but we can break it down.
- We tell GitHub to only run the workflow on pushes to the
sourcebranch. I also opted to automatically run the workflow at 2PM Monday - Friday, just in case 🤷🏻♂️
- Next we’re installing the Composer and NPM dependencies.
- Once the dependencies have been installed, we build the site using the production environment configuration.
- Optional! I’m using a CNAME on GitHub Pages so that I can use my own domain. I create a new file and fill it with the domain name I want to use.
- I forcefully stage the
build_productiondirectory, this is because Jigsaw defaults to ignoring
build_*directories from Git and I don’t want to change this and accidentally publish it into the
- Next we configure Git’s email and name, I chose to use GitHub Actions as the author so that I know it’s an automatic commit. We then commit the contents with a pre-defined commit message.
- Finally, we’re going to publish the site by pushing the changes from within the GitHub Action itself! This is a bit complicated if you’re not confident with Git, but let’s try to keep it simple. We create a subtree of the
build_productiondirectory and pushing it into a temporary
masterbranch. Now we can force push the branch to GitHub and clean up by deleting the
And that’s it, I’m now able to write new blog posts without my laptop (using just the GitHub website) and have them immediately published for me.
Let me know @jbrooksuk if you’re using this technique or have any suggestions on how to improve it.
- Because we’re force-pushing to
masterfrom a branch which contains only one commit, all history is lost for the published website. This is a trade-off that I’m happy with because the real history is in the