Personal academic site built with Astro, Tailwind CSS, and TypeScript. AGENTS.md defines the minimal visual style, protected page choices, CV synchronization, and publishing rules.
Use Node 22, at least 22.12.0 for the declared Astro version, and pnpm 10. The Node major is recorded in .nvmrc; package versions are in package.json and pnpm-lock.yaml. From this repository root:
pnpm install --frozen-lockfile
pnpm devUse the localhost URL and port printed by Astro. A local preview does not publish the site.
| Command | Effect |
|---|---|
pnpm dev |
Start the development server |
pnpm check |
Run Astro checks and Biome checks without applying fixes |
pnpm build |
Generate portfolio thumbnails, copy compiled CV PDFs, build Astro, then index dist/ with Pagefind |
pnpm preview |
Preview the existing production build |
pnpm lint |
Apply Biome fixes; this changes files |
pnpm format |
Apply Prettier formatting; this changes files |
pnpm optimize:portfolio |
Regenerate portfolio thumbnails |
For site implementation changes, run the applicable checks and inspect affected pages. Before an authorized publication, both pnpm check and pnpm build must pass. For instruction and README changes alone, check affected links and git diff --check; no preview server or production build is needed.
This is an Astro 7 personal academic website using:
- TailwindCSS v4 (via
@tailwindcss/viteplugin, not the Astro integration) - TypeScript with path alias
@/→src/ - Biome for linting/formatting (tabs, 100 char line width); Prettier for
.astrofiles
All global site metadata and navigation lives in src/site.config.ts:
siteConfig— author, URL, title, description, locale, date formatmenuLinks— drives header and footer navigation linksexpressiveCodeOptions— syntax highlighting themes (Dracula dark / GitHub light)
Defined in src/content.config.ts. Three collections:
post— blog posts atsrc/content/post/**/*.{md,mdx}. Required frontmatter:title(max 60 chars),description,publishDate. Optional:tags,draft,coverImage,ogImage,updatedDate,pinned.note— short notes atsrc/content/note/**/*.{md,mdx}.publishDatemust be ISO 8601 with timezone offset.tag— optional tag metadata atsrc/content/tag/**/*.{md,mdx}(keyed by tag slug).
Draft posts (draft: true) are excluded in production but visible in dev.
| Route | Page |
|---|---|
/ |
About (index.astro) |
/cv/ |
CV |
/research/ |
Research |
/resources/skills/ |
Skill collections |
/resources/skills/computational-modeling-skills/ |
Computational Modeling Skills catalog |
/posts/ |
Blog listing |
/notes/ |
Notes listing |
/tags/ |
Tag index |
/photography/ |
Photography gallery |
/og-image/[slug].png |
Server-rendered OG images (Satori) |
/rss.xml, /notes/rss.xml |
RSS feeds |
- src/layouts/Base.astro — root shell with
<html>,<head>(viaBaseHead), Header, and Footer.ThemeProviderloads the theme script in the head. - src/layouts/Reading.astro — shared single-column layout for blog posts, guides, and resource listings, with breadcrumb navigation. Citations use native footnotes with return links; the literature guide keeps image credits in its endnotes.
- src/layouts/BlogPost.astro — wraps
Reading.astrowith the blog masthead and webmentions.
src/styles/global.css, public/fonts/cmu.css, and public/styles/site.css define the shared typography and theme rules with CMU Sans Serif, a clear size hierarchy (24–30px page titles and Research section headings, 20–24px h2, 18px h3, 16px body text, 14px navigation and metadata), and a 3-color font palette (headings: #ffffff dark / #000000 light; body text: #d4d4d8 dark / #3f3f46 light; links: #e11d48 rose/crimson in both dark and light). public/styles/theme.js defaults to dark mode, remembers the choice under the local-storage key theme, and supports ?theme=light and ?theme=dark.
src/data/pages/resources.ts lists skill collections. The Computational Modeling Skills subpage uses src/data/pages/computational-modeling-skills.ts, with descriptions checked against the collection's GitHub README and skill instructions. Its logo in public/images/skills/computational-modeling-logo.svg is the repository's original assets/logo.svg. Update the catalog and logo from that source when the collection changes.
The MCPs page displays the Cellpose and Fiji posters listed in src/data/pages/resources.ts. Original PNG previews and PDFs are served from public/posters/; their sources are poster/cellpose_mcp_poster.{png,pdf} in cellpose_mcp and poster/fiji_mcp_poster.{png,pdf} in Fiji_imageJ_mcp. Keep these exports intact when updating them. Each preview links to the full-size image, with a PDF link below it.
Photos go in public/portfolio/. The prebuild step (scripts/optimize-portfolio.js) generates WebP thumbnails into public/portfolio-thumbs/ using sharp. The gallery page reads the filesystem at build time and uses Fancybox (@fancyapps/ui) for the lightbox.
Add a description of each photo to src/data/pages/photography.ts; these descriptions supply accessible image text and lightbox captions. Do not use camera filenames as descriptions.
Located in src/plugins/:
remark-reading-time— adds reading time to frontmatterremark-admonitions—:::note,:::tip,:::caution,:::warning,:::importantdirectivesremark-github-card— GitHub repo card embeds via directives
src/pages/og-image/[...slug].png.ts generates social preview images at build time using Satori + satori-html. Fonts are loaded via a custom Vite plugin (rawFonts) that inlines .ttf/.woff as base64.
Pagefind runs post-build (pagefind --site dist) to create the static search index. The Search.astro component loads the Pagefind UI client-side.
Configured via env vars in .env (copy from .example.env):
WEBMENTION_API_KEY= # server-only secret
WEBMENTION_URL= # public client var
WEBMENTION_PINGBACK= # optional
The maintained sources are resume/cv.tex and resume/resume.tex. The academic CV is the content authority; the condensed résumé follows its relevant content.
The build copies existing resume/cv.pdf and resume/resume.pdf into public/; it does not compile LaTeX. The /cv/ page exposes these two PDFs without duplicating their content in the webpage. Follow the document and page rules in AGENTS.md.
GitHub Pages uses GitHub Actions as its publishing source. CI checks Astro and the build; the deployment workflow publishes pushes to main. Commit or push only work authorized for publication, never force-push, and verify the resulting site after an authorized deployment. A request for local documentation or Git checkpoints does not require publication.