Imported from C-L1gh7/My_blog (
AGENTS.md). Install upstream withnpx skills add C-L1gh7/My_blog. Copyright stays with the author.
AGENTS.md
This file provides guidance to Codex (Codex.ai/code) when working with code in this repository.
Project Overview
Personal blog (Chinese-language, lang="zh-CN") built with Astro 5, React 18, and Tailwind CSS 3. Features a retro/tape aesthetic with black borders, hard shadows, and yellow highlights. Deployed to GitHub Pages via withastro/action@v2.
Development Commands
npm run dev # Start dev server at localhost:4321 (alias: npm start)
npm run build # Build for production to ./dist/
npm run preview # Preview production build locally
No linting or test suites are configured — the project is content-driven with no application logic to test.
Architecture
Content Collections
Four collections defined in src/content/config.ts, all Zod-schema-validated markdown:
- posts —
title,date,tag(optional, defaults to'GENERAL'),excerpt(optional),image(optional) - notes —
title,date,file(optional),tags(optional string array) - studies —
title,course,date,image(optional) - projects —
title,description(optional),date,image(optional),technologies(required string array),codeUrl/docsUrl/videoUrl(all optional)
Content is queried via getCollection() from astro:content. Standard sort pattern across all pages:
items.sort((a, b) => new Date(b.data.date).valueOf() - new Date(a.data.date).valueOf())
Asset Strategy
All images are hosted on Cloudflare R2 CDN, not locally. Pattern: https://img.cl1gh7.top/PicGo/[filename]
- No image optimization or processing at build time
- Components use standard
<img>tags with CDN URLs as strings public/directory exists for local static files (CV PDF, favicon) but is not used for blog images
Component Architecture
React Components (in src/components/, require client:load directive):
Navbar.tsx— Fixed header with NASA-style color palette per nav link, scroll-animated rotating disc icon (framer-motion), mobile hamburger with fullscreen overlay and ESC-to-closePostCard.tsx— Article preview with spring-animated hover (framer-motion,LayoutGroup-compatible), image zoom + film gradient overlay, conditionalline-clamp-2excerptPostList.tsx— Thin wrapper that maps posts to PostCards inside aLayoutGroupPostHub.tsx— Full filtering/search UI: text search, tag filter buttons, newest/oldest sort, "Surprise Me" (random 3-pick mode)ProjectCard.tsx— Project showcase card with tech tags and conditional Code/Docs/Video action buttonsProjectHub.tsx— Filtering UI mirroring PostHub (search, tech filter, sort). Not currently used in pages —projects.astrorenders projects inline insteadProfileCard.tsx— Sticky sidebar with avatar, bio, social links (GitHub, Bilibili, Email). Accepts atimelineprop — a merged list of recent posts/projects/notes rendered as an animated vertical rail (color-coded by content type)Icons.tsx— SVG icon library (Disc, ArrowRight, Search, Filter, Sort, Shuffle, Github, Bilibili, Mail). No emoji icons
Astro Components:
BaseLayout.astro— Root HTML wrapper with Google Fonts (Inter + JetBrains Mono), KaTeX CDN CSS, SVGfeTurbulencenoise texture overlay at 3% opacity, custom scrollbar CSS,.content-containerutility classNoteCard.astro— Note display with optional file attachment downloadPDFViewer.astro— Iframe-based PDF viewer with download linkVideoPlayer.astro— Styled<video>player with black border + hard shadow. Available for use in MDX content (not currently imported in any page)
MDX Support
@astrojs/mdx is configured in astro.config.mjs. MDX files (.mdx) can be used in content collections alongside .md. Components like VideoPlayer.astro are available for embedding in MDX without explicit imports.
Styling System
Retro Aesthetic — Black borders (border-black), hard shadows (shadow-[4px_4px_0px_#000], shadow-[8px_8px_0px_#ccc]), yellow highlights (bg-yellow-200), uppercase font-mono labels, slight decorative rotations (-rotate-2)
Colors: Background #f0f0ed, foreground #1a1a1a, accent red #dc2626 (hover states), selection yellow #f2c94c
Typography: Inter (sans, body), JetBrains Mono (mono, labels/metadata/code). Custom Tailwind prose plugin config: black bold headings, red links on hover, inline code in red on light gray bg (backtick pseudo-elements removed), left-black-border blockquotes, centered images
Noise Texture: SVG feTurbulence filter (baseFrequency="0.65", numOctaves="3") rendered as fixed overlay at 3% opacity — core to the retro/analog aesthetic
Page Structure
All pages: Navbar (client:load) → .content-container (max-width 1100px, mx auto) → content
index.astro— 12-col grid: 4-col sticky sidebar (ProfileCard with merged timeline) + 8-col main (rendered project bodies, then PostList of latest 2). Mobile: inline profile below navbarposts/index.astro— PostHub with full filtering/searchposts/[...slug].astro— Individual post with smart back button (JS checksdocument.referrerfor same-origin →history.back(), otherwise →/posts/). Content in prose wrapper with optional header imagenotes.astro— 3-col grid of NoteCardsstudies/index.astro— Grouped by courseprojects.astro— Renders projects inline with rendered bodyContent(not via ProjectHub)about.astro— Static Chinese-language page with tech stack cardscv.astro— PDF viewer (expectspublic/cv.pdfor CDN URL)
Navigation
Order: HOME | POSTS | PROJECTS | NOTES | STUDIES | ABOUT | CV
Each link has a distinct NASA-inspired hover color defined in Navbar.tsx. Uses import.meta.env.BASE_URL for base path handling (currently /).
Math Support
LaTeX math via remark-math + rehype-katex. KaTeX CSS loaded from jsDelivr CDN in BaseLayout.astro.
Adding Content
New Blog Post
Create src/content/posts/your-post.md:
---
title: "Post Title"
date: "2024-01-01"
tag: "CATEGORY" # optional, defaults to 'GENERAL'
excerpt: "Brief summary"
image: "https://img.cl1gh7.top/PicGo/image.jpg" # optional
---
Markdown content here. LaTeX math $E = mc^2$ is supported.
New Project
Create src/content/projects/your-project.md:
---
title: "Project Name"
description: "Brief description"
date: "2024-01-01"
image: "https://..."
technologies: ["Python", "OpenCV"]
codeUrl: "https://github.com/..." # optional
docsUrl: "https://..." # optional
videoUrl: "https://bilibili.com/..." # optional
---
Detailed project description with markdown.
All three link fields are optional — buttons only render if URLs are provided.
Key Patterns
- No emoji as icons — Use SVG from
Icons.tsxinstead (thoughabout.astrohardcodes some emoji for decoration) - Framer Motion — Spring hover animations on cards,
LayoutGroupfor layout transitions between PostCards in PostList/PostHub - Content sorting — Collections sorted by date descending using the standard pattern shown above
- Base URL handling — All internal links use
${import.meta.env.BASE_URL}/pathpattern - Smart back navigation — Post detail page checks
document.referrerfor same-origin; useshistory.back()if so, otherwise navigates to/posts/ - timeline merging —
index.astromerges latest posts, projects, and notes into a single sorted timeline for ProfileCard
SEO 规范
所有页面必须设置 description meta 标签。 BaseLayout.astro 已支持 description prop,新建页面时使用:
<BaseLayout
title="页面标题"
description="页面描述"
>
- 列表页、关于页、CV 页等:在页面
.astro文件中硬编码 description - 文章详情页:description 取
post.data.excerpt,因此每篇文章的 frontmatter 中应填写excerpt字段 - 学习笔记详情页:description 使用
${study.data.course} 课程笔记 — ${study.data.title}
新建任何页面时,必须提醒用户提供 description。
站点地图配置
CRITICAL: 站点地图必须包含完整的 SEO 元数据才能被 Google 正常抓取。astro.config.mjs 中的 @astrojs/sitemap 配置已优化,包含:
lastmod— 最后修改时间(构建时间戳)changefreq— 更新频率(daily/weekly/monthly)priority— 页面优先级(0.0-1.0)
当前优先级策略(在 serialize 函数中定义):
- 首页:
1.0(每日更新) - 项目页:
0.9(每月更新) - 文章页:
0.8(每周更新) - 学习笔记页:
0.7(每月更新) - Notes 页:
0.6(每周更新) - 其他页面:
0.7(每周更新,默认值)
修改站点地图配置时:
- 保持
serialize函数中的 URL 模式匹配逻辑 - 根据内容类型调整
priority和changefreq - 修改后必须运行
npm run build重新生成站点地图 - 部署后在 Google Search Console 重新提交站点地图(或等待 24-48 小时自动抓取)
验证站点地图:
# 本地验证 XML 格式
xmllint --format dist/sitemap-0.xml | head -50
# 检查线上站点地图
curl -s https://cl1gh7.pages.dev/sitemap-index.xml | xmllint --format -