| 层面 | 选型 | 说明 |
|---|---|---|
| 框架 | Next.js 14(App Router) | SSG 支持完善,next/image 性能优化内置 |
| 样式 | Tailwind CSS | 在 tailwind.config.js 中集中定义字号、间距等设计 token,无需 CSS Variables |
| 富文本 | MDX(next-mdx-remote) | 在 Markdown 中嵌入 React 组件,用户可直接在 GitHub 上编辑 |
| 图片处理 | Sharp(GitHub Action 中运行) | 自动压缩、WebP 转换、多尺寸生成 |
| 字体 | next/font(Google Fonts) | 零布局偏移,自动本地化 |
| 部署 | Vercel | 边缘 CDN,next/image 原生支持,免费 tier 足够个人学术网站 |
| CI/CD | GitHub Actions | 图片处理 + 自动部署触发 |
输出模式:output: 'export'(纯静态 HTML)。构建结果是一堆静态文件,部署在 Vercel 上,不需要服务器持续运行,也不需要数据库。
域名:Vercel 默认提供 project-name.vercel.app,后期可绑定自定义域名(如 cindykao.com),不影响任何技术实现,可随时决定。
/
├── app/ # Next.js App Router 页面
│ ├── layout.tsx # 根布局 — 字体、导航栏、元数据
│ ├── page.tsx # 根路由重定向 → /about
│ ├── globals.css # 全局 CSS(Tailwind 基础 + 自定义类)
│ ├── about/
│ ├── news/
│ │ └── all/ # /news/all — 完整新闻存档
│ ├── portfolio/
│ ├── projects/[id]/ # 动态项目详情页
│ ├── publications/
│ ├── team/
│ ├── courses/
│ └── opportunities/
│
├── components/
│ ├── layout/
│ │ └── Navbar.tsx # 固定顶部导航栏,含深色模式切换
│ ├── about/
│ │ ├── ResearchSection.tsx
│ │ ├── OurApproachSection.tsx
│ │ └── ContactSection.tsx
│ ├── news/
│ │ └── NewsGrid.tsx # /news 和 /news/all 共用的网格组件
│ ├── portfolio/
│ │ ├── PortfolioHero.tsx
│ │ ├── DirectionBanner.tsx
│ │ └── ProjectCard.tsx
│ ├── projects/
│ │ └── MediaGrid.tsx # 图片 + 视频两列网格
│ ├── publications/
│ │ └── PublicationCard.tsx
│ ├── team/
│ │ └── TeamSection.tsx
│ ├── courses/
│ │ └── CourseBlock.tsx
│ └── ui/
│ ├── InlineLink.tsx # 样式化链接 — 内部或外部
│ ├── Strong.tsx # 加粗 + 深色文字
│ ├── Corresponding.tsx # 通讯作者上标 *
│ └── Skeleton.tsx # 加载骨架屏
│
├── content/ # ← 用户可编辑文件
│ ├── site.ts # 网站标题、描述、favicon 说明
│ ├── about.tsx # 个人简介、研究方向、研究方法、联系方式
│ ├── news.tsx # 新闻条目数组
│ ├── portfolio.tsx # Hero、简介、研究方向 + 论文
│ ├── publications.tsx # 按年份分组的发表列表
│ ├── projectDetails.tsx # 项目详情页内容(按 slug 区分)
│ ├── team.tsx # 团队简介 + 成员分组
│ ├── courses.tsx # 课程列表
│ └── opportunities.tsx # 招募信息正文 + 要点列表
│
├── lib/
│ └── projectRoutes.ts # Slug 生成 + 项目查找工具函数
│
├── public/
│ ├── images/ # 静态图片(已加入 gitignore — 单独上传)
│ ├── papers/ # 自托管 PDF(已加入 gitignore — 单独上传)
│ │ └── .gitkeep
│ └── favicon.ico # 替换此文件可更改浏览器标签图标
│
└── docs/
├── en/ # 英文用户指南(每页一份)
└── zh/ # 中文用户指南(每页一份)
| URL | 文件 | 说明 |
|---|---|---|
| `/` | `app/page.tsx` | 重定向到 `/about` |
| `/about` | `app/about/page.tsx` | |
| `/news` | `app/news/page.tsx` | 显示前 8 条 |
| `/news/all` | `app/news/all/page.tsx` | 显示全部 |
| `/portfolio` | `app/portfolio/page.tsx` | |
| `/publications` | `app/publications/page.tsx` | |
| `/team` | `app/team/page.tsx` | |
| `/courses` | `app/courses/page.tsx` | |
| `/opportunities` | `app/opportunities/page.tsx` | |
| URL 模式 | 文件 | 生成方式 |
|---|---|---|
| `/projects/[id]` | `app/projects/[id]/page.tsx` | `generateStaticParams()` 读取 `content/about.tsx` 中所有项目标题并转换为 slug |
Slug 生成规则(lib/projectRoutes.ts):
标准化 → 转小写 → 将非字母数字字符替换为 - → 去除首尾 -。
示例:"Project Alpha" → project-alpha,"Soft Robot (2024)" → soft-robot-2024。
激活状态:导航栏在 /portfolio 和任意 /projects/* 路由下均将"Portfolio"标记为激活。