CLAUDE.md
CLAUDE.md
Working notes for Claude (or any AI assistant) on this repo. Keep this scannable — add to it when conventions or gotchas crystallize.
Repo overview
- Jekyll personal blog (“Wei’s Learning Notes”), deployed via GitHub Pages from the
mainbranch. - Theme:
minima, with local overrides in_layouts/,_includes/, andcss/override.css. - Generated originally from
chadbaldwin/simple-blog-bootstrap. - Live site: https://wwucla.github.io/
Sync before any change
The user also edits files directly via the GitHub web UI sometimes, so local main is often stale. Always start fresh work by pulling latest from origin:
git checkout main && git pull
Skip this and you’ll branch off old code and produce avoidable merge conflicts. Do this every session, every new branch — no exceptions.
PR workflow (preferred)
Always work on a feature branch and merge via gh — no clicking through the web UI for merges. The pattern that works reliably:
git checkout main && git pull # see above — never skip
git checkout -b <type>/<short-name> # feature/, fix/, demo/, chore/
# ... edits ...
git add <files>
git commit -m "<message>"
git push -u origin HEAD
gh pr create --fill --base main
gh pr merge --squash --delete-branch --auto
The --auto flag is the important one: it tells GitHub to merge the PR as soon as required checks pass, so we don’t need to foreground-watch with gh pr checks --watch (which has a race where it exits before the workflow has even registered).
“Allow auto-merge” is enabled in repo Settings → General. Leave it on.
After the auto-merge fires, sync local main:
git checkout main && git pull && git branch -d <branch-name>
Local dev (Jekyll)
GitHub Pages runs Ruby ~3.3 and a specific github-pages gem bundle. For a clean local match:
brew install ruby@3.1 # 3.1 is the sweet spot — newer Rubies (3.4+) break Liquid 4.0.3
echo 'export PATH="/opt/homebrew/opt/ruby@3.1/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
gem install --user-install bundler
bundle install
bundle exec jekyll serve --livereload # http://127.0.0.1:4000
To preview future-dated posts (e.g., the demo post): add --future to jekyll serve.
A Gemfile exists locally for dev but is gitignored — keep it that way.
Site customizations (already in place)
- Tag chips under each post title, linking to
/archive.html#tag-<slug>. Implemented in_layouts/post.html. Per-tag sections live inarchive.mdwith kramdown IAL anchors ({: id="tag-<slug>" }). - Reading time on each post: Liquid
content | number_of_words | divided_by: 200 | plus: 1. In_layouts/post.html. - Auto table of contents (
/js/toc.js): builds a nested TOC client-side from<h2>/<h3>headings in.post-content. Activation modes viadata-toc-modeon#post-toc:force—toc: truein front-matter — render whenever ≥1 heading exists.auto— default — render only when there are more than 3 headings.- To disable on a specific post:
toc: falsein front-matter.
- CI build check:
.github/workflows/jekyll-check.ymlrunsactions/jekyll-build-pages@v1on every PR targetingmain. Build-only; deploy still happens via Pages onmain.
Posting conventions
Every post in _posts/ should have:
---
layout: post
title: "Descriptive Title"
date: 2026-05-11
categories: [Optional, Category]
tags: [Tag1, Tag2] # used by tag chips + archive
description: One-sentence summary used by SEO.
---
Do not write hardcoded “Estimated reading time” lines or hand-rolled “Table of Contents” sections — both are auto-generated by the layout. Same for inline <a name="..."> anchor markers; kramdown auto-IDs headings.
Posts can opt out of the auto-TOC by setting toc: false. The Other tag is the default for posts that omit tags: (configured in _config.yml).
Gotchas / things to never do
- Do not enable
titles_from_headings.collections: truein_config.yml. Thejekyll-titles-from-headingsplugin (auto-loaded bygithub-pages) will then override the front-mattertitlewith the first heading text whenever a post starts with a heading. Front-matter title must stay authoritative. - Do not use bitdowntoc or other manual-TOC generators in posts. The auto-TOC from
/js/toc.jshandles it. - Do not pin
gem "jekyll"directly in aGemfile. Always go throughgem "github-pages", group: :jekyll_pluginsso versions match production Pages. - Do not push directly to
main. Always go through a PR (the auto-merge flow makes this near-zero overhead). - The
_posts/2038-03-08-blog-post-title-from-file-name.mdpost is a future-dated rendering demo. Don’t backdate it — that would publish it to the live site.
When asked to add a new feature/page
- Branch off
main. - Check
_layouts/and_includes/for existing partials before adding new ones — many extension points already exist (e.g., minima’scustom-head.htmlis honored). - Append site-wide CSS to
css/override.css(not a new stylesheet) so we keep one source of styling truth. - Run
jekyll build(orserve) locally if the change is non-trivial; the CI check catches breakage on PR anyway. - PR via the workflow above.
Useful one-liners
- See recent CI runs:
gh run list --limit 5 - Check PR status:
gh pr view <num> --json statusCheckRollup - Open the live site:
gh browse --no-browserthen paste the URL, or just visit https://wwucla.github.io/
Avoid touching
images/— only add new images, don’t reorganize.js/highlightjs/— vendored highlight.js. New languages require adding the matching module here AND a<script>tag in_includes/head.html.