CLAUDE.md — Curry09.github.io
Personal academic homepage built on the acad-homepage Jekyll template (minimal-mistakes based), deployed via GitHub Pages. The whole site is essentially one page: _pages/about.md.
🌏 This site is bilingual (English + 中文) — the #1 rule
The site has a 中 / EN language switch (floating button, top-right). It works entirely client-side: every visible string exists twice — an English copy and a Chinese copy — and CSS shows only one at a time based on a class on <html> (lang-en / lang-zh).
RULE: Any change to visible content MUST be made in BOTH languages. Never add, edit, or remove a piece of visible text in only one language. If you add a news item, a paper, an award, etc. in English, add the matching Chinese (and vice-versa). If you only have one language, ask the user for the other before committing — do not leave a half-translated page.
How the bilingual markup works
1. Inline text (paragraphs, list items, headings) — wrap each language in a span:
<span class="lang-en">English text here</span><span class="lang-zh">中文文本</span>
Keep the two spans adjacent with no space between them (a stray space shows up when switching). Markdown inside a span renders normally: **bold**, [link](url), *italic* all work.
2. Section headings — keep the shared emoji outside the spans, and pin an explicit ID so nav anchors never break:
# 🔥 <span class="lang-en">News</span><span class="lang-zh">最新动态</span> {#news}
The {#news} is required — _data/navigation.yml links to /#news, /#internships, /#publications, /#honors-and-awards, /#education. If you rename or add a section, keep the ID in sync with the nav file.
⚠️ The ID must start with a letter, not a hyphen. kramdown only consumes the
{#id}attribute when the ID begins with a letter; an ID like{#-news}is left in the rendered page as literal text (and the heading never gets the ID, so the nav anchor breaks). Use{#news}, never{#-news}.
3. Publications — paper titles and author lists stay English-only (academic convention). Only the bullet descriptions under each paper are bilingual (wrap each bullet’s text in the two spans). Badges, images, links, dates are shared (written once, no spans).
Where each translatable surface lives
| Surface | File | How |
|---|---|---|
| Page body (intro, news, internships, publication blurbs, honors, education) | _pages/about.md |
.lang-en / .lang-zh spans |
| Nav bar labels | _data/navigation.yml (title + title_zh) rendered by _includes/masthead.html |
one entry per language |
| Sidebar name / bio / location | _config.yml author block: name+name_zh, bio+bio_zh, location+location_zh |
rendered by _includes/author-profile.html |
| Sidebar blurb under avatar | _config.yml: sidebar_blurb + sidebar_blurb_zh |
description stays English (used for SEO) |
The switching machinery (rarely needs changing)
- CSS + pre-paint language script:
_includes/head/custom.html - Toggle button + click handler:
_includes/lang-toggle.html(included from_layouts/default.html) - Default language for first-time visitors: English. The choice is saved in
localStorageundersite-lang.
Local preview
bundle exec jekyll serve # then open http://localhost:4000
Click the 中 / EN button and confirm BOTH languages look right before committing.
Citation counts (Semantic Scholar)
Citation counts come from the Semantic Scholar Graph API, in two places:
- Per paper, at the end of each publication’s badge row — a shields.io
badge with the Semantic Scholar logo (
logo=semanticscholar,-fff?logoColor=000), matching the hand-written Paper/Code/Dataset badges. Built client-side from the fetched count. - A Total Citations badge in the badge row near the top of
about.md, beside Total GitHub Stars and styled to match it (coloured fill, white logo). This one is a shields.io endpoint badge readings2_data_shieldsio.jsonstraight off the data branch, so it needs no JS. It points atraw.githubusercontent.comlike the stars badge does — fine there because shields.io fetches it server-side, not the visitor’s browser.
shields.io treats
-and_as separators inside a/badge/path segment, sos2Badge()doubles them. An unescapedh-indexrenders a “404 badge not found” image, which is easy to miss.
Publications are ordered by citation count, descending — not
reverse-chronologically. about.md is kept in that order so the first paint is
already right, and s2SortPapers() re-sorts on load so the order stays correct
as counts drift. A paper Semantic Scholar has no data for sorts last rather than
tying with a genuine 0. The sort moves .paper-box nodes between placeholder
slots rather than re-appending them to the parent, which would drop them past
the Honors and Education sections.
| Piece | Where |
|---|---|
| Crawler (one API call, retries on 429) | semantic_scholar_crawler/main.py |
Daily job, force-pushes to the semantic-scholar-stats branch |
.github/workflows/semantic_scholar_crawler.yaml |
| Page-side fetch + DOM fill | _includes/fetch_semantic_scholar_stats.html (loaded via _includes/scripts.html) |
| Markers in the page | _pages/about.md — one <span class='show_s2_citations' data='<arxiv-id>'> per paper; also the sort key and the id the badge links by |
Adding a paper: put the usual arxiv.org/abs/<id> Paper badge on the badge
line and append <span class='show_s2_citations' data='<id>'></span>, and drop
the block in at its place in the citation ordering. Nothing
else to configure — the crawler scrapes the arXiv ids out of the Publications
section of about.md, so a paper that isn’t on the Semantic Scholar author
profile (co-author disambiguation slips happen) still gets looked up directly.
Notes:
- The author id lives in the workflow (
SEMANTIC_SCHOLAR_AUTHOR_ID, currently2399060433); override it with a repo variable of the same name. An optionalSEMANTIC_SCHOLAR_API_KEYsecret raises the rate limit but isn’t needed. - Every paper shows its own count, 0 included. If the branch is missing or the
fetch fails the page just renders without citations — no broken text, no
dangling
|. - Numbers lag reality: the job runs daily at 08:30 UTC and jsDelivr caches a branch path for up to ~12h. Run the workflow manually from the Actions tab to refresh sooner.
- The data is read through jsDelivr unless
citation_stats_use_cdnin_config.ymlis set tofalse; raw.githubusercontent.com is unreachable from mainland China, so the CDN is the default rather than the opt-in. - Semantic Scholar is the only citation source. The upstream template’s
Google Scholar pipeline (
google_scholar_crawler, its workflow, and_includes/fetch_google_scholar_stats.html) was removed deliberately — don’t reintroduce it.docs/README-zh.mdis upstream template documentation and still describes it. The Google Scholar profile links inabout.mdand the sidebar are unrelated and stay. - Run the crawler locally with:
cd semantic_scholar_crawler && SEMANTIC_SCHOLAR_AUTHOR_ID=2399060433 python main.py