dug (company logo) Good looks like this.

Maintenance runbook

Practical, copy-pasteable steps for keeping the site running and adding content. For why things are structured the way they are, see architecture.md and case-studies.md.


Run it locally

bundle install                       # first time, or after a Gemfile change
bundle exec jekyll serve --drafts    # serves at http://localhost:4000

If bundle install complains, you probably changed Ruby versions. The Gemfile pins github-pages (which in turn pins the Jekyll version GitHub actually uses) plus webrick (needed on Ruby 3+).


Deploy

There is no manual deploy and no GitHub Actions workflow.

  1. Commit your changes.
  2. git push origin main.
  3. GitHub Pages rebuilds automatically. Live within ~1–2 minutes at goodlookslikethis.com (the custom domain is set by the CNAME file).

If a build fails, GitHub emails the commit author. Builds fail most often because of: a YAML front-matter typo, or a Jekyll plugin that GitHub Pages doesn’t allow (only the plugins in _config.ymljekyll-feed, jekyll-paginate — are on the allowlist).

Tip: main is production. There’s no staging. Preview locally before pushing.


Common tasks

Add a blog post

Create _posts/YYYY-MM-DD-your-slug.md:

---
layout: 2023/post
title: Title here
subtitle: One-liner
intro: >
  Intro paragraph, shown prominently on the post and in listings.
tags: [tag-one, tag-two]
categories: [category]
hero_image: /i/your-image.jpg
hero_image_alt: Plain-language description of the image
date: YYYY-MM-DD
---

Body content in markdown.

Add a case study

  1. Pick the collection that fits the work (see the table in Collections).
  2. Create a markdown file in that folder. The filename controls ordering — see Reorder cases.
  3. Use the 2023/case layout:
---
layout: 2023/case
title: Project name
subtitle: One-liner
intro: >
  Short summary.
challenge: What the problem was.
approach: How you tackled it.
result: What happened (ideally with a number or two).
hero_image: /i/cases/project-slug/hero.jpg
hero_image_alt: Plain-language description
tags: [service-design, leadership]
---

Full case study content.

Reorder cases in a section

Cases in a section are listed alphabetically by filename (there is no sort config). Control the order by prefixing filenames with letters:

_cases_sdingov/a-environmental-regulator.md   ← shown first
_cases_sdingov/b-hmrc-PTA.md
_cases_sdingov/c-funding-agency.md
...

To move a case, rename it. To insert one between b- and c-, either renumber or use bb-. Unprefixed files sort after… well, alphabetically by their real name, so mixing prefixed and unprefixed files in one folder gets unpredictable — prefix them all if order matters.

Hide a case (without deleting it)

Add exception to its tags:

tags:
  - service-design
  - exception      # ← removes it from the section's index listing

Add images

Publish a draft

Move the file from _drafts/ into _posts/ and rename it to YYYY-MM-DD-slug.md. Check/refresh its front matter — many drafts are old stubs with legacy field names (see architecture.md).

Add a whole new case section

This is the one multi-step task — a section is a Jekyll collection, so several files must agree. To add, say, a “research” section at /cases/research/:

  1. Register the collection in _config.yml under collections::
    cases_research:
      output: true
      permalink: /cases/research/:name
    
  2. Create the folder _cases_research/.
  3. Add an index page _cases_research/index.html (copy an existing one, e.g. _cases_practitioner/index.html) and set:
    parent: "cases_research"   # tells the listing loop which collection to iterate
    theme: "research"          # key into _data/constants.yml for the title/subtitle
    bodyclass: "cases"
    
  4. Add the nav/labels in _data/constants.yml (this is what drives the section nav and the /cases/ category index — see the gotcha in case-studies.md):
    research:
      title: "Research"
      slug: "research"
      subtitle: "…"
    
  5. Restart jekyll serve (config + data changes need a restart) and check the section lists, the nav button appears, and /cases/ shows the new category.

Collections

Folder URL Use for
_cases/ /cases/ Base collection. Its index.html lists the categories, not cases.
_cases_leadership/ /cases/leadership/ Design leadership, people management
_cases_sdingov/ /cases/sdingov/ Service design in government
_cases_strategy/ /cases/strategy/ Strategy, direction-setting
_cases_business/ /cases/business/ Commercial / business-facing work
_cases_practitioner/ /cases/practitioner/ Senior IC, hands-on craft
_cases_remote/ /cases/remote/ Remote teams and distributed work

Not collected (won’t build, by design): _cases-WIP/, _cases_Zolder/ (archive), _posts-older-to-process/, _posts-author-archive-old/. To bring any of these live, treat it like content to add — move files into a real collection/_posts, refresh front matter.


Troubleshooting

Symptom Likely cause / fix
New case doesn’t appear in its section Tagged exception? In a folder that’s actually in _config.yml? Restart serve if you touched config.
New case in wrong position Ordering is by filename — rename with a letter prefix.
A whole section is missing from the nav The nav reads _data/constants.yml, which only lists some sections. Add an entry there. See case-studies.md.
Image 404s Path must be absolute from site root, e.g. /i/..., and the file must be committed.
Config/data change not showing locally Restart the server — Jekyll doesn’t reload _config.yml or _data/.
Build passes locally but fails on GitHub Usually a non-allowlisted plugin or a YAML front-matter error. Check the email from GitHub.
Old post renders weirdly It probably uses legacy front-matter keys or a root layout — see architecture.md.
GitHub build fails but local serve is fine GitHub force-enables jekyll-optional-front-matter, which renders every loose .md — including README.md and CLAUDE.md — through Liquid. A literal Liquid tag or output expression (the curly-brace / percent syntax) in those files fails the build, even though local serve copies them raw and never catches it. Avoid Liquid syntax in prose, or wrap code samples in raw/endraw tags. See architecture.md › Local build ≠ GitHub build.