CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Commit conventions
Do not add a Co-Authored-By: Claude ... trailer (or any AI attribution) to commit messages.
What this is
A single-page academic personal homepage built on the acad-homepage Jekyll template (a fork of it). It is hosted on GitHub Pages and served at https://cao-wuhui.github.io. upstream points at RayeRen/acad-homepage.github.io for pulling template improvements; when merging from upstream, take framework/template changes only and ignore the upstream author’s personal content.
Local development
bash run_server.sh # = bundle exec jekyll liveserve; serves http://127.0.0.1:4000 with livereload
bundle install # install Ruby gem dependencies (first-time setup, requires Ruby + GCC + Make)
There are no tests, linters, or a build step to run manually — Jekyll regenerates the site and GitHub Pages builds/deploys automatically on push to main. _config.yml is not hot-reloaded; restart the server after editing it.
Where content lives
Nearly all page content is in one file: _pages/about.md. It has permalink: /, so it is the homepage. Every visible section (About Me, Publications, Educations, Experiences, Teaching, Honors & Awards, CVEs, Reports, Visiting Record) is a top-level # heading in this single Markdown file, which mixes Markdown and raw HTML freely. To edit the site’s content, edit this file.
The nav ↔ heading anchor contract (important)
The top navigation bar is defined in _data/navigation.yml. Each link’s url is an anchor into the single-page body (e.g. /#-publications). These anchors are auto-generated by kramdown (auto_ids: true) from the # headings in about.md, using this rule: lowercase, spaces → -, and non-alphanumerics (including emoji and &) stripped.
# 📝 Publications→ id-publications→ nav url/#-publications(leading-because the emoji is stripped but its trailing space becomes a dash)# 🏅 Honors & Awards→ id-honors--awards
Consequence: if you rename or reorder a section heading in about.md, you must update the matching url in navigation.yml, or that nav link breaks. The “About Me” section is the exception — it has no visible heading; its anchor is a manual <span class='anchor' id='about-me'></span> in the body, and the nav points at /#about-me.
The domain prefix for nav links
masthead.html renders nav links as ``, and domain is set in _config.yml (https://cao-wuhui.github.io). This absolute prefix makes anchor links like /#-publications jump back to the homepage even when viewed from a sub-page. If nav links break after a fork/rename, check that domain in _config.yml matches the actual live GitHub Pages URL (the username-derived USERNAME.github.io, not whatever is in CNAME).
Google Scholar citation counts (automated)
Citation stats are fetched by a scheduled GitHub Action, not committed to main:
- .github/workflows/google_scholar_crawler.yaml runs google_scholar_crawler/main.py daily (08:00 UTC) and on each page build.
- It reads the
GOOGLE_SCHOLAR_IDrepo secret, then force-pushes the resultinggs_data.jsonto a separategoogle-scholar-statsbranch (this force-push is by design and lives only on that data branch — never force-pushmain). - The site reads that JSON at runtime via _includes/fetch_google_scholar_stats.html;
google_scholar_stats_use_cdn: truein_config.ymlcontrols whether it’s loaded via jsDelivr CDN or raw GitHub. Per-paper counts use<span class='show_paper_citations' data='SCHOLAR_ID:PAPER_ID'></span>inabout.md.
Layout / theme structure
Standard Jekyll minimal-mistakes-derived layout: _layouts/default.html is the only layout, composed from partials in _includes/ (masthead.html nav, sidebar.html + author-profile.html for the left profile card driven by the author: block in _config.yml, head/, scripts.html, seo.html, analytics.html). Styles are SCSS in _sass/ compiled from assets/. Static assets: images/ (avatar referenced by author.avatar), files/ (linked PDFs/slides). docs/ and google_scholar_crawler/ are excluded from the Jekyll build via _config.yml.