You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CLAUDE.md
+14-3Lines changed: 14 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -49,7 +49,11 @@ All blog, portfolio, and research entries are MDX files on disk — there's no C
49
49
-`Mermaid` — renders ` ```mermaid ` blocks; mermaid + stylis are transpiled and pre-bundled (see `transpilePackages` and `experimental.optimizePackageImports` in `next.config.js`).
50
50
-`ContentImage` — explicit component for ImageKit-hosted images. The default `img` MDX mapping was intentionally removed so external images / SVGs in MDX don't break; use `<ContentImage>` (or a raw `<img>`) explicitly.
6.**Research-specific components** live in `src/components/content/research/`: `HeadingResearch` (status chip, title, structured authors + affiliations, venue, action-button row, hr), `ResearchTeaser` (full-bleed figure + caption, lives outside `prose` so it can breathe), `ResearchAbstract` (purple-accented `not-prose` card), `ResearchBibTeX` (anchored at `#bibtex`, copy-to-clipboard, mirrors `Pre.tsx` chrome), `ResearchItem` + `ResearchSections` (listing card + section grouping). The detail page composition is in `src/app/research/[slug]/page.tsx`.
52
+
6.**Research-specific components** live in `src/components/content/research/`:
53
+
-**Detail-page**: `HeadingResearch` (status chip, title, structured authors + affiliations, venue, action-button row, hr — author/affiliation `<sup>` markers are conditional + carry `title` tooltips, see Conventions), `ResearchTeaser` (full-bleed figure + caption, lives outside `prose` so it can breathe), `ResearchAbstract` (purple-accented `not-prose` card), `ResearchBibTeX` (anchored at `#bibtex`, copy-to-clipboard, mirrors `Pre.tsx` chrome).
54
+
-**Listing-page**: `ResearchOverview` (intro paragraph), `ResearchNews` (date-column timeline; entries live in the `NEWS` array inside the file), `ResearchAreas` (colored chip row), `ResearchItem` + `ResearchSections` (listing card + section grouping). `ComingSoonImage` is a pastel-gradient placeholder used in place of the listing thumbnail when an entry has `comingSoon: true`.
55
+
-**Shared**: `SectionHeading` is the bordered `text-lg md:text-xl font-bold text-black dark:text-white` h2 used by every section on the listing page (Overview / News / Research Areas / Sections groupers). Use it for any new sections to keep the rhythm consistent.
56
+
- The detail page composition is in `src/app/research/[slug]/page.tsx`. The listing page is in `src/app/research/page.tsx` — both pass `pt-6 md:pt-10` to `AppLayoutPage` to give the first section breathing room from the sticky header.
53
57
7.**SEO** is generated per-page in `src/app/blog/[slug]/page.tsx` and the portfolio / research equivalents: `generateMetadata` builds Next.js Metadata (OG, Twitter, canonical, `modifiedTime`), and the page itself injects a single `@graph` JSON-LD block:
Net result: `bg-primary` (shadcn) and `bg-primary-500` (legacy) render the same color; both surfaces remain valid during the transition. When adding new code, prefer the semantic tokens. Don't write `dark:` overrides for shadcn classes — `--background` etc. switch automatically via `.dark`.
88
92
89
-
Fonts: `--font-sans` resolves to `var(--font-inter)` (Next/font Google) with the local `@font-face` Inter as a fallback. The legacy `font-primary` utility still maps to Inter via `tailwind.config.js`.
93
+
Fonts: `--font-sans` resolves to `'Google Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'`. Google Sans is loaded via Google Fonts CSS (`<link>` in `layout.tsx` head, with `preconnect` to `fonts.gstatic.com` — `font-src` in `next.config.js` CSP must include it). Local Inter `@font-face` stays in `globals.css` as a deeper fallback so the page never FOUCs. `tailwind.config.js``fontFamily.primary` mirrors the same stack so the legacy `font-primary` utility picks up Google Sans too.
90
94
91
95
## Two Build Modes
92
96
@@ -123,7 +127,14 @@ ISR endpoint at `GET /api/revalidate?secret=<SECRET>&slug=/blog/<slug>`. Secret
123
127
- Commits go through `commitizen` with `cz-conventional-changelog` — run `yarn commit` for the prompt. `lint-staged` runs Prettier on staged `js/jsx/ts/tsx/mdx/md/css` files.
124
128
- Frontmatter `published` for blog and research is `MM/DD/YYYY` (portfolio uses `date`). `featured: true` surfaces an entry on the home page. Optional `updated: "MM/DD/YYYY"` overrides `published` as the freshness signal — it flows into `dateModified` (BlogPosting / ScholarlyArticle JSON-LD), `<meta property="article:modified_time">`, and the sitemap `lastmod`. Set it whenever you make a substantive content edit; leave it off for typo fixes.
125
129
- Authoring convention: open every blog post with a 60–120 word TL;DR paragraph immediately under the H1. LLM crawlers (ChatGPT, Perplexity, AI Overviews) draw ~44% of their citations from the first 30% of an article, so front-loading the answer compounds visibility.
126
-
-**Research authoring**: use the YAML folded scalar (`abstract: >-`) — block scalar (`|`) preserves newlines and the abstract renders with broken lines. Authors use a structured array; `affiliations` indices are 1-based and reference the entry's `affiliations` array. `section` drives listing-page grouping (`top-tier` / `conferences` / `journals` / `workshops` / `others`). `new: true` renders a NEW badge inline with the title on the listing card. Authors matching `SITE_AUTHOR.name` are auto-bolded across `HeadingResearch` and `ResearchItem`.
130
+
-**Research authoring**: use the YAML folded scalar (`abstract: >-`) — block scalar (`|`) preserves newlines and the abstract renders with broken lines. Authors use a structured array; `affiliations` indices are 1-based and reference the entry's `affiliations` array. `section` drives listing-page grouping (`top-tier` / `conferences` / `journals` / `workshops` / `others`). `new: true` renders a NEW badge inline with the title on the listing card. `comingSoon: true` swaps the listing thumbnail for the `ComingSoonImage` pastel placeholder (no thumbnail/teaser required). Authors matching `SITE_AUTHOR.name` are auto-bolded across `HeadingResearch` and `ResearchItem`.
131
+
-**Author / affiliation superscripts** in `HeadingResearch` are conditional. Each marker only renders when it actually disambiguates something:
132
+
-`*` (corresponding author) — `corresponding: true` on the author. Shows when **2+ authors** AND at least one is corresponding.
133
+
-`†` (equal contribution) — `equalContribution: true` on the author. Shows when **2+ authors** AND at least 2 are flagged. Renders on every flagged author.
134
+
-`‡` (principal investigator) — `principalInvestigator: true` on the author. Shows when **2+ authors** AND at least one is PI.
135
+
-`¹ ² ³` (affiliation indices) — derived from `affiliations: [...]` on each author. Shows when **2+ affiliations** exist on the entry.
136
+
137
+
Marker order on each author follows academic convention: `*†‡` then numeric indices. The affiliation legend below the author line drops its leading `<sup>` under the same `showAffSup` rule. Single-author / single-affiliation entries collapse to clean text — no orphan markers. Each `<sup>` has `cursor-help` + a native `title` tooltip (affiliation index sups resolve to the full affiliation name; symbol sups resolve to their caption text). A combined caption line appears below the affiliation row when any symbol marker is shown — e.g. `*Corresponding author · †Equal contribution · ‡Principal investigator` — joined by ` · `.
Copy file name to clipboardExpand all lines: README.md
+39-6Lines changed: 39 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -70,6 +70,14 @@ Use it as your portfolio. Fork it as a template. Read the source as a reference
70
70
-**Topic archive pages** auto-generated from frontmatter `topics`.
71
71
-**RSS** at `/rss.xml` (summaries) and `/rss-full.xml` (full content) with `<link rel="alternate">` discovery in `<head>`.
72
72
73
+
### Design system
74
+
75
+
-**shadcn/ui** (radix-nova style) as the single primitive layer. Components live under `src/components/ui/` and are managed by the shadcn CLI (`npx shadcn@latest add <name>`); rerun with `--diff` to merge upstream updates without losing local edits.
76
+
-**Theme bridge** in `src/styles/globals.css``@theme inline` — shadcn semantic tokens (`--primary`, `--background`, `--foreground`, `--muted`, `--border`, `--ring`) map onto the legacy blue-primary / neutral-theme palette in OKLCH so legacy classes (`bg-primary-500`, `text-theme-700`) and shadcn classes (`bg-primary`, `text-foreground`) render identically across light/dark.
-**Typography** — Google Sans loaded from Google Fonts with a system-font fallback chain (`system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, …`). Local Inter `@font-face` is kept as a deeper fallback so the page never FOUCs.
80
+
73
81
### Performance
74
82
75
83
-**Core Web Vitals attribution** for CLS, LCP, **INP**, FCP, TTFB via Vercel Speed Insights.
@@ -80,13 +88,15 @@ Use it as your portfolio. Fork it as a template. Read the source as a reference
80
88
81
89
### Tooling
82
90
83
-
-**TypeScript** strict-mode, `@/*` path aliases.
91
+
-**TypeScript** strict-mode, `@/*` path alias.
84
92
-**ESLint flat config** (`eslint.config.mjs`, replacing the deprecated `next lint`).
-**Vitest** suite (48 tests, ~1.7s) covering schema generators, sorters, content readers. Vite resolves `@/*` paths via the native `resolve.tsconfigPaths: true` (no plugin).
86
96
-**JSON-LD validator** (`yarn validate:json-ld`) walks the build output and verifies every `<script type="application/ld+json">` block.
87
97
-**Alt-text auditor** (`yarn audit:alt-text`) flags weak `alt` attributes in MDX.
88
98
-**GitHub Actions CI**: type-check + lint + test + build + JSON-LD validation on every push/PR.
89
-
-**Yarn 4** via Corepack, with a `vercel.json``installCommand` so deploy hosts honour the lockfile.
99
+
-**Yarn 4** via Corepack, with a `vercel.json``installCommand`(`corepack enable && corepack prepare yarn@4.14.1 --activate && yarn install --immutable`) so deploy hosts actually run Yarn 4 and honour the lockfile.
90
100
91
101
---
92
102
@@ -97,9 +107,12 @@ Use it as your portfolio. Fork it as a template. Read the source as a reference
new: true # renders a "NEW" badge inline with the title on the listing card
354
+
comingSoon: true # OPTIONAL: renders a "Coming soon!" pastel placeholder in place of the listing thumbnail (for conditionally accepted / pre-publication entries that don't have a teaser yet)
The detail page renders the structured fields in the hero (status chip from `venue.status`, authors with affiliation superscripts, venue line, action-button row driven by `links` and `bibtex`). Authors matching `SITE_AUTHOR.name` are bolded. The `bibtex` field renders as a copy-to-clipboard code block anchored at `#bibtex`.
359
379
380
+
**Author / affiliation superscripts are conditional** — each marker only renders when it actually disambiguates something:
381
+
382
+
| Flag on `Author`| Glyph | Caption | Renders when |
|`principalInvestigator: true`|`‡`| ‡Principal investigator | 2+ authors AND ≥1 PI |
387
+
|`affiliations: [n]`|`¹ ² ³`|_(legend below)_| 2+ affiliations on the entry |
388
+
389
+
Marker order on each author: `*†‡` then numeric affiliation indices (academic convention). Single-author / single-affiliation entries skip everything — no orphan markers. When markers do show, each `<sup>` carries a native `title` tooltip (affiliation index sups resolve to the full affiliation name; symbol sups resolve to their caption). A combined caption line — e.g. `*Corresponding author · †Equal contribution · ‡Principal investigator` — auto-renders below the affiliation row.
390
+
391
+
The research listing page (`/research`) renders an Overview paragraph, a date-column News timeline, and a colored chip row of Research Areas above the section-grouped listings. Section headings across the page (Overview / News / Research Areas / Top-Tier Venues / Conferences / Journals / Workshops / Others) share a single `<SectionHeading>` component (`text-lg md:text-xl`, `font-bold`, `text-black dark:text-white`, bordered bottom).
392
+
360
393
### Special MDX components
361
394
362
395
```mdx
@@ -420,7 +453,7 @@ y = \sigma(Wx + b)
420
453
421
454
### Vercel (recommended)
422
455
423
-
Zero-config — Vercel detects Next.js and uses the `installCommand` from `vercel.json` (`corepack enable && yarninstall --immutable`) so Yarn 4 is honoured. Set `NEXT_PUBLIC_SITE_URL` to your production domain in the Vercel project settings.
456
+
Zero-config — Vercel detects Next.js and uses the `installCommand` from `vercel.json` (`corepack enable && corepack prepare yarn@4.14.1 --activate && yarn install --immutable`) so Yarn 4 actually runs (the explicit `corepack prepare` step is required because `corepack enable` alone doesn't reliably switch the active yarn binary on Vercel's image — without it, Vercel falls back to Yarn 1.22 and silently rewrites the lockfile). Set `NEXT_PUBLIC_SITE_URL` to your production domain in the Vercel project settings.
0 commit comments