| Production | https://kaichen.dev |
| Source | https://github.com/kaiiiichen/kaichen.dev |
- Requirements
- Quick start
- npm scripts
- Technology stack
- Repository layout
- Routes and features
- API routes
- Environment variables
- External integrations
- Local development tips
- Testing
- CI, Dependabot, auto-merge
- Git hooks
- Deployment
- Forking
- Documentation map
- License
kaichen.dev is Kai Chen’s personal website — a small, intentional corner of the internet. It is not a generic portfolio template or a link-in-bio page.
The core idea is simple: show a person as they actually are — who they are, what they care about, what they are doing right now, and how to reach them — in one place that feels warm and readable.
To do that, the site mixes several kinds of content:
| Kind | Purpose | Examples on this site |
|---|---|---|
| Narrative | Background and intent that change slowly | About; project write-ups |
| Live signals | Small windows into the present | Spotify now playing; Berkeley weather and local clock; GitHub pins and contribution calendar |
| Curated lists | Taste and attention, hand-picked | Misc |
Visually, the site uses an editorial / magazine layout: cream-toned cards (.mag-card), Nunito for nav and card chrome, Geist Sans for body text, light mode by default with full dark-mode support. The goal is reading comfort and personality — a hub you can revisit, not a feature dashboard.
This repository implements that idea with Next.js 16 (App Router), React 19, TypeScript, Tailwind CSS 4, deployed on Vercel. Dynamic data comes from Spotify, GitHub GraphQL, Open-Meteo, and optional Supabase listening history. Optional observability: Sentry, Vercel Analytics, Speed Insights.
There is no middleware.ts / proxy.ts — all routes are public and rendered directly by the App Router.
| Route / link | Role |
|---|---|
/ |
First impression — identity, social links, Listening, Location, Projects |
/about |
Deeper self — education, Focus, experience, volunteering |
/projects |
Course Projects, Personal Projects, GitHub Activity |
/misc |
Watching, Remembrance, Things I Love |
Open Graph: each in-app route has an opengraph-image handler ([app/lib/og.tsx](app/lib/og.tsx)). SEO: sitemap.ts, robots.ts, and JSON-LD Person on the home page.
| Token | Hex | Use |
|---|---|---|
| Cream background | #F7F3EE |
Page atmosphere (--background) |
| Accent | #C4894F |
Links, hovers, editorial emphasis (--accent) |
| Dark accent | #D9A870 |
Accent in .dark mode |
Implementation layer: stack, repo layout, API routes, env vars, CI, and fork notes.
| Tool | Version / notes |
|---|---|
| Node.js | 20.x (matches CI) |
| npm | 9+; use npm ci for reproducible installs |
git clone https://github.com/kaiiiichen/kaichen.dev.git
cd kaichen.dev
npm install
cp .env.example .env.local
# Edit .env.local — see Environment variables below
npm run devOpen http://localhost:3000. dev and build use Next.js Turbopack.
You do not need every env key to run locally; missing keys typically degrade or hide features rather than crash the build.
| Script | Command | Purpose |
|---|---|---|
dev |
next dev |
Local development (Turbopack) |
build |
next build |
Production bundle |
start |
next start |
Serve last build output |
lint |
eslint |
ESLint ([eslint.config.mjs](eslint.config.mjs)) |
typecheck |
tsc --noEmit |
TypeScript check |
test |
vitest run |
Unit tests (CI) |
test:watch |
vitest |
Vitest watch mode |
postinstall |
git config core.hooksPath .githooks … |
Git hooks — see Git hooks |
Before opening a PR, mirror CI:
npm run lint && npm run typecheck && npm run test && npm run build| Layer | Choices |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack), React 19, TypeScript 5 |
| Styling | Tailwind CSS 4, magazine cards in [app/globals.css](app/globals.css) (.mag-card, .mag-label) |
| Fonts | Geist Sans / Mono on body; Nunito for nav + cards; JetBrains Mono where needed |
| Data | Optional Supabase (listening_history / listening_stats) for Spotify route |
| Monitoring | Optional Sentry; Vercel Analytics + Speed Insights |
| Testing | Vitest — see [lib/*.test.ts](lib/) |
Pinned versions: [package.json](package.json).
kaichen.dev/
├── app/
│ ├── layout.tsx # Root layout, metadata, theme, Nav, SiteFooter, Analytics
│ ├── page.tsx # Home (identity, Spotify, weather, nested Projects)
│ ├── globals.css # Theme tokens, .mag-card, .mag-card-inset, .nav-link, animations
│ ├── opengraph-image.tsx # OG for /
│ ├── about/ # Bio, education, focus, experience + OG
│ ├── projects/
│ │ ├── page.tsx # Course + Personal project cards, GitHub heatmap
│ │ └── oxford-dul-2025/ # Oxford summer coursework portfolio (landing + [slug])
│ ├── misc/ # Watching, Remembrance, Things I Love + OG
│ ├── api/
│ │ ├── spotify/now-playing/
│ │ ├── spotify/last-month-top/
│ │ ├── github/contributions/
│ │ └── weather/
│ ├── components/
│ │ ├── oxford-dul/ # Portfolio cards, project sections, projects-split
│ │ ├── nav.tsx # Bold labels; pill-shaped active underline
│ │ └── … # listening-card, weather-card, pinned-project-link, …
│ ├── hooks/use-now-playing.ts
│ ├── lib/
│ │ ├── oxford-dul-projects.ts # Oxford portfolio metadata + 6 projects
│ │ ├── course-projects.ts # Course Projects entries (Oxford + Notion notes)
│ │ ├── og.tsx
│ │ └── github-pinned.ts
│ ├── sitemap.ts
│ └── robots.ts
├── lib/ # Server helpers + Vitest tests
│ └── …
├── public/
│ ├── avatar.jpg
│ └── portfolio/oxford-dul-2025/ # Exported training PNGs (see portfolio/ README)
├── portfolio/oxford-dul-2025/README.md # Portfolio asset + compliance notes
├── next.config.ts
├── instrumentation*.ts
├── sentry.*.config.ts
├── .env.example
├── AGENTS.md / CLAUDE.md / CONTRIBUTING.md / SECURITY.md
└── .github/workflows/ # ci.yml, auto-merge.yml
| Route | What it does |
|---|---|
/ |
Identity; social links; Listening + Location cards; Projects outer card with nested Course Projects and Personal Projects (GitHub pins, list rows with hover ↗) |
/about |
Personality, education (incl. Oxford → portfolio link), Focus, experience, volunteering |
/projects |
Course Projects cards; Personal Projects grid; GitHub contribution calendar |
/projects/oxford-dul-2025 |
Oxford Deep Unsupervised Learning landing — overview, learning path, 6 project cards, academic record |
/projects/oxford-dul-2025/{slug} |
Per-project detail — Problem, Dataset, Approach, Training, My Work, Evaluation, Results, Takeaway |
/misc |
Watching (dated news links), Remembrance, Things I Love (nested category inset cards) |
Nav: bold Kai T. Chen + About · Projects · Misc; active route uses accent text + pill-shaped underline (app/globals.css .nav-link). Site footer on every page: © 2026 Kai Thomas Chen. All rights reserved.
All handlers under app/api/.
| Method & path | Behavior | Caching / env |
|---|---|---|
GET /api/spotify/now-playing |
Spotify currently-playing + recently-played; optional Supabase listening_* writes while playing; in-memory lastKnownTrack fallback |
Cache-Control: public, s-maxage=10, stale-while-revalidate=5; SPOTIFY_*; optional SUPABASE_* |
GET /api/spotify/last-month-top |
Previous calendar month top 5 tracks from Supabase listening_history (recorded_at, paginated) |
revalidate = 600; optional SUPABASE_* |
GET /api/github/contributions |
GraphQL contribution calendar (12 months) → { weeks, totalContributions } |
revalidate = 300; GITHUB_TOKEN |
GET /api/weather |
Open-Meteo current conditions for Berkeley, CA ([weather-open-meteo.ts](lib/weather-open-meteo.ts)) |
revalidate = 600; no API key |
Pinned repo stars / archived badges: server-side GraphQL in [github-pinned.ts](app/lib/github-pinned.ts) (revalidate = 120) — no separate stars API route.
Copy [.env.example](.env.example) to .env.local. Never commit secrets.
| Variable | Role |
|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Supabase project URL (Spotify listening history) |
SUPABASE_SERVICE_ROLE_KEY |
Server-only — listening_history / listening_stats |
SPOTIFY_CLIENT_ID / SPOTIFY_CLIENT_SECRET / SPOTIFY_REFRESH_TOKEN |
Spotify app + refresh token (user-read-currently-playing, user-read-recently-played) |
GITHUB_TOKEN |
GitHub API — contributions + pinned repos |
GITHUB_LOGIN |
Optional username (default kaiiiichen) |
NEXT_PUBLIC_SENTRY_DSN / SENTRY_DSN |
Optional error reporting |
SENTRY_AUTH_TOKEN, SENTRY_ORG, SENTRY_PROJECT |
Build-time source maps (Vercel) |
CI builds without real Supabase keys — clients are lazy-init; see [.github/workflows/ci.yml](.github/workflows/ci.yml).
vercel env pull .env.vercel.check # gitignored — do not commit| Service | Use |
|---|---|
| Spotify Web API | Now playing + recently played |
| GitHub GraphQL | Contribution calendar + pinned repos (stars, archived) |
| Open-Meteo | Berkeley weather (no key) |
| Supabase | Optional listening history persistence |
| Symptom | Check |
|---|---|
| GitHub widgets empty | GITHUB_TOKEN valid; rate limits |
| Listening history not persisted across deploys | SUPABASE_* set; tables exist |
| Sentry noisy locally | Unset DSN or lower sample rate in instrumentation-client.ts |
Vitest unit tests in lib/*.test.ts — weather parsing and Spotify helpers.
npm run test
npm run test:watchNo Playwright/E2E in this repo; manual browser checks for layout polish.
- CI (
[.github/workflows/ci.yml](.github/workflows/ci.yml)): push/PR tomain→npm ci→ lint → typecheck → test → build (Node 20). - Dependabot (
[.github/dependabot.yml](.github/dependabot.yml)): weekly npm + github-actions; grouped updates; major bumps for core tooling ignored (manual). - Auto-merge (
[.github/workflows/auto-merge.yml](.github/workflows/auto-merge.yml)): Dependabot patch/minor PRs → squash merge when checks pass.
npm install sets core.hooksPath → [.githooks/prepare-commit-msg](.githooks/prepare-commit-msg) appends Co-authored-by: Claude <noreply@anthropic.com>. See [AGENTS.md](AGENTS.md).
- Connect repo to Vercel.
- Set env vars (
GITHUB_TOKEN,SPOTIFY_*, optionalSUPABASE_*, optional Sentry). - Push to
main→ production; PRs → previews.
vercel --prod # after vercel link| Area | Where to edit |
|---|---|
| Copy, social URLs | app/page.tsx, app/about/page.tsx |
| Course Projects | [app/lib/course-projects.ts](app/lib/course-projects.ts) — Oxford entry + external links (e.g. Notion) |
| Oxford portfolio | [app/lib/oxford-dul-projects.ts](app/lib/oxford-dul-projects.ts), app/projects/oxford-dul-2025/, app/components/oxford-dul/ |
| Portfolio PNG assets | public/portfolio/oxford-dul-2025/{slug}/ — see [portfolio/oxford-dul-2025/README.md](portfolio/oxford-dul-2025/README.md) |
| Spotify OAuth | Spotify Developer Dashboard → SPOTIFY_* in [lib/spotify-access-token.ts](lib/spotify-access-token.ts) |
| GitHub login / pins | GITHUB_LOGIN, [app/lib/github-pinned.ts](app/lib/github-pinned.ts), contributions route |
| Supabase schema | [lib/listening-supabase.ts](lib/listening-supabase.ts), now-playing route |
| Weather location | [app/api/weather/route.ts](app/api/weather/route.ts) |
| Misc lists | [app/misc/page.tsx](app/misc/page.tsx) |
| Theme / fonts / nav | app/layout.tsx, app/globals.css, app/components/nav.tsx, theme-provider.tsx |
Keep GPL-3.0 compliance if you redistribute — see [LICENSE](LICENSE).
| File | Contents |
|---|---|
| README.md | This file — idea + reference |
[portfolio/oxford-dul-2025/README.md](portfolio/oxford-dul-2025/README.md) |
Oxford portfolio assets, routes, export checklist |
[CONTRIBUTING.md](CONTRIBUTING.md) |
Human contributor guide |
[AGENTS.md](AGENTS.md) |
AI agent git workflow |
[CLAUDE.md](CLAUDE.md) |
Short stack summary |
[SECURITY.md](SECURITY.md) |
Responsible disclosure |
[.env.example](.env.example) |
Env var names |
GNU General Public License v3.0 — see [LICENSE](LICENSE). Report vulnerabilities via [SECURITY.md](SECURITY.md).
- 环境要求
- 快速开始
- npm 命令
- 技术栈
- 目录结构
- 路由与功能
- API 路由
- 环境变量
- 外部集成
- 常见问题
- 测试
- CI 与 Dependabot
- Git hooks
- 部署
- Fork 指南
- 文档索引
- 许可证
kaichen.dev 是 Kai Chen 的个人网站 —— 互联网上很小、但有意图的一块自留地。它不是通用作品集模板,也不是 link-in-bio 聚合页。
核心想法很简单:把一个真实的人展示出来 —— 是谁、在意什么、此刻在做什么、如何联系 —— 集中在一个温暖、好读的站点里。
为此,站点混合几类内容:
| 类型 | 作用 | 在本站的具体体现 |
|---|---|---|
| 叙述 | 变化较慢的背景与方向 | About;项目说明 |
| 实时信号 | 照进「此刻」的小窗口 | Spotify 正在播放;Berkeley 天气与时钟;GitHub 置顶与贡献日历 |
| 策展列表 | 品味与注意力,人工挑选 | Misc |
视觉上采用杂志 / editorial 排版:奶油色卡片(.mag-card)、Nunito 用于导航与卡片 chrome、Geist Sans 用于正文、默认浅色并完整支持暗色。目标是阅读舒适与个性 —— 可回访的枢纽,而非功能控制台。
技术实现:Next.js 16(App Router)、React 19、TypeScript、Tailwind CSS 4,部署于 Vercel。动态数据来自 Spotify、GitHub GraphQL、Open-Meteo、可选 Supabase 听歌记录。可选观测:Sentry、Vercel Analytics、Speed Insights。
本仓库没有 middleware.ts / proxy.ts,所有路由公开,由 App Router 直接渲染。
| 路由 / 链接 | 作用 |
|---|---|
/ |
第一印象 —— 身份、社交链接、Listening、Location、Projects |
/about |
更深的自我 —— 教育、Focus、经历、志愿 |
/projects |
Course Projects、Personal Projects、GitHub Activity |
/misc |
Watching、Remembrance、Things I Love |
Open Graph: 各站内路由均有 opengraph-image([app/lib/og.tsx](app/lib/og.tsx))。SEO: sitemap.ts、robots.ts,首页嵌入 JSON-LD Person。
| 序号 | 色值 | 用途 |
|---|---|---|
| 01 | #F7F3EE |
页面背景(--background) |
| 02 | #C4894F |
强调色(--accent) |
| 03 | #D9A870 |
暗色模式强调色 |
以下为实现层:技术栈、目录、API、环境变量、CI 与 fork 说明。
| 工具 | 版本 / 说明 |
|---|---|
| Node.js | 20.x(与 CI 一致) |
| npm | 9+;可复现安装请用 npm ci |
git clone https://github.com/kaiiiichen/kaichen.dev.git
cd kaichen.dev
npm install
cp .env.example .env.local
# 编辑 .env.local —— 见下方「环境变量」
npm run dev打开 http://localhost:3000。dev 与 build 使用 Next.js Turbopack。
未配置全部密钥通常只会降级或隐藏相关功能,而不会阻止本地启动与构建。
| 命令 | 实际执行 | 用途 |
|---|---|---|
dev |
next dev |
本地开发(Turbopack) |
build |
next build |
生产构建 |
start |
next start |
运行上次 build 产物 |
lint |
eslint |
ESLint([eslint.config.mjs](eslint.config.mjs)) |
typecheck |
tsc --noEmit |
TypeScript 检查 |
test |
vitest run |
单元测试(CI 使用) |
test:watch |
vitest |
监听模式 |
postinstall |
git config core.hooksPath .githooks … |
Git hooks —— 见 Git hooks |
提 PR 前请与 CI 保持一致:
npm run lint && npm run typecheck && npm run test && npm run build| 层级 | 选型 |
|---|---|
| 框架 | Next.js 16(App Router、Turbopack)、React 19、TypeScript 5 |
| 样式 | Tailwind CSS 4,杂志卡片见 [app/globals.css](app/globals.css)(.mag-card、.mag-label) |
| 字体 | body 用 Geist Sans / Mono;导航与卡片用 Nunito;代码处用 JetBrains Mono |
| 数据 | 可选 Supabase(listening_history / listening_stats),供 Spotify 路由使用 |
| 监控 | 可选 Sentry;Vercel Analytics + Speed Insights |
| 测试 | Vitest —— 见 [lib/*.test.ts](lib/) |
版本锁定见 [package.json](package.json)。
kaichen.dev/
├── app/
│ ├── layout.tsx # 根布局、metadata、主题、Nav、SiteFooter、Analytics
│ ├── page.tsx # 首页(身份、Spotify、天气、嵌套 Projects)
│ ├── globals.css # 主题 token、.mag-card、.mag-card-inset、.nav-link、动画
│ ├── opengraph-image.tsx # 首页 OG
│ ├── about/ # 简介、教育、Focus、经历 + OG
│ ├── projects/
│ │ ├── page.tsx # Course + Personal 项目卡片、GitHub 热力图
│ │ └── oxford-dul-2025/ # 牛津暑校作品集(落地页 + [slug] 详情)
│ ├── misc/ # Watching、Remembrance、Things I Love + OG
│ ├── api/
│ │ ├── spotify/now-playing/
│ │ ├── spotify/last-month-top/
│ │ ├── github/contributions/
│ │ └── weather/
│ ├── components/
│ │ ├── oxford-dul/ # 作品集卡片、详情区块、projects-split
│ │ ├── nav.tsx # 粗体标签;圆角 active 下划线
│ │ └── …
│ ├── hooks/use-now-playing.ts
│ ├── lib/
│ │ ├── oxford-dul-projects.ts # 牛津作品集元数据 + 6 个项目
│ │ ├── course-projects.ts # Course Projects 条目(牛津 + Notion 笔记)
│ │ ├── og.tsx
│ │ └── github-pinned.ts
│ ├── sitemap.ts
│ └── robots.ts
├── lib/ # 服务端 helper + Vitest 测试
│ └── …
├── public/
│ ├── avatar.jpg
│ └── portfolio/oxford-dul-2025/ # 导出的训练 PNG(见 portfolio/ README)
├── portfolio/oxford-dul-2025/README.md
├── next.config.ts
├── …
└── .github/workflows/
| 路由 | 功能 |
|---|---|
/ |
身份;社交链接;Listening / Location;嵌套 Projects(Course + Personal 列表行,hover ↗) |
/about |
性格、教育(含牛津作品集链接)、Focus、经历、志愿 |
/projects |
Course Projects 卡片;Personal Projects 网格;GitHub 贡献日历 |
/projects/oxford-dul-2025 |
牛津 Deep Unsupervised Learning 落地页 |
/projects/oxford-dul-2025/{slug} |
单项目详情(Problem / Dataset / Training / Evaluation / Results 等) |
/misc |
Watching、Remembrance、嵌套 Things I Love |
导航: 粗体 Kai T. Chen + About · Projects · Misc;当前页为 accent 文字 + 圆角下划线(.nav-link)。页脚:© 2026 Kai Thomas Chen. All rights reserved.
所有 handler 位于 app/api/。
| 方法与路径 | 行为 | 缓存 / 环境变量 |
|---|---|---|
GET /api/spotify/now-playing |
Spotify 当前播放 + 最近播放;播放中可选写入 Supabase listening_*;内存 lastKnownTrack 兜底 |
Cache-Control: public, s-maxage=10, stale-while-revalidate=5;SPOTIFY_*;可选 SUPABASE_* |
GET /api/spotify/last-month-top |
上自然月 Top 5(Supabase listening_history,按 recorded_at 筛选并分页) |
revalidate = 600;可选 SUPABASE_* |
GET /api/github/contributions |
GraphQL 贡献日历(12 个月)→ { weeks, totalContributions } |
revalidate = 300;GITHUB_TOKEN |
GET /api/weather |
Open-Meteo 伯克利当前天气([weather-open-meteo.ts](lib/weather-open-meteo.ts)) |
revalidate = 600;无需 API key |
置顶仓库的 star / archived 徽章:服务端 GraphQL([github-pinned.ts](app/lib/github-pinned.ts),revalidate = 120),无单独 stars API。
复制 [.env.example](.env.example) 为 .env.local。切勿提交密钥。
| 变量 | 作用 |
|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Supabase 项目 URL(Spotify 听歌记录) |
SUPABASE_SERVICE_ROLE_KEY |
仅服务端 —— listening_history / listening_stats |
SPOTIFY_CLIENT_ID / SPOTIFY_CLIENT_SECRET / SPOTIFY_REFRESH_TOKEN |
Spotify 应用 + refresh token(user-read-currently-playing、user-read-recently-played) |
GITHUB_TOKEN |
GitHub API —— 贡献日历 + 置顶仓库 |
GITHUB_LOGIN |
可选用户名(默认 kaiiiichen) |
NEXT_PUBLIC_SENTRY_DSN / SENTRY_DSN |
可选错误上报 |
SENTRY_AUTH_TOKEN, SENTRY_ORG, SENTRY_PROJECT |
构建期 source map(Vercel) |
CI 无需真实 Supabase 密钥即可构建 —— client 懒加载;见 [.github/workflows/ci.yml](.github/workflows/ci.yml)。
vercel env pull .env.vercel.check # 已 gitignore,勿提交| 服务 | 用途 |
|---|---|
| Spotify Web API | 正在播放 + 最近播放 |
| GitHub GraphQL | 贡献日历 + 置顶仓库(star、archived) |
| Open-Meteo | 伯克利天气(无需 key) |
| Supabase | 可选听歌记录持久化 |
| 现象 | 排查 |
|---|---|
| GitHub 组件为空 | GITHUB_TOKEN 是否有效;是否触发 rate limit |
| 听歌记录部署后不持久 | 是否配置 SUPABASE_*;表结构是否正确 |
| 本地 Sentry 过吵 | 不设置 DSN,或在 instrumentation-client.ts 降低采样率 |
Vitest 单元测试位于 lib/*.test.ts —— 天气解析、Spotify helper。
npm run test
npm run test:watch本仓库暂无 Playwright/E2E;布局与视觉建议手动浏览器检查。
- CI(
[.github/workflows/ci.yml](.github/workflows/ci.yml)):推送到main或 PR →npm ci→ lint → typecheck → test → build(Node 20)。 - Dependabot(
[.github/dependabot.yml](.github/dependabot.yml)):每周 npm + github-actions;分组更新;核心工具 major 升级忽略(手动处理)。 - Auto-merge(
[.github/workflows/auto-merge.yml](.github/workflows/auto-merge.yml)):Dependabot patch/minor PR 在检查通过后 squash 合并。
npm install 会设置 core.hooksPath → [.githooks/prepare-commit-msg](.githooks/prepare-commit-msg) 追加 Co-authored-by: Claude <noreply@anthropic.com>。详见 [AGENTS.md](AGENTS.md)。
- 将仓库连接到 Vercel。
- 配置环境变量(
GITHUB_TOKEN、SPOTIFY_*、可选SUPABASE_*、可选 Sentry)。 - 推送到
main部署生产;PR 生成预览。
vercel --prod # 需先 vercel link| 区域 | 修改位置 |
|---|---|
| 文案、社交链接 | app/page.tsx、app/about/page.tsx |
| Course Projects | [app/lib/course-projects.ts](app/lib/course-projects.ts) |
| 牛津作品集 | [app/lib/oxford-dul-projects.ts](app/lib/oxford-dul-projects.ts)、app/projects/oxford-dul-2025/、app/components/oxford-dul/ |
| 作品集 PNG 资源 | public/portfolio/oxford-dul-2025/{slug}/ —— 见 [portfolio/oxford-dul-2025/README.md](portfolio/oxford-dul-2025/README.md) |
| Spotify OAuth | Spotify Developer Dashboard → SPOTIFY_*,见 [lib/spotify-access-token.ts](lib/spotify-access-token.ts) |
| GitHub 用户 / 置顶 | GITHUB_LOGIN、[app/lib/github-pinned.ts](app/lib/github-pinned.ts)、contributions 路由 |
| Supabase 表结构 | [lib/listening-supabase.ts](lib/listening-supabase.ts)、now-playing 路由 |
| 天气坐标 | [app/api/weather/route.ts](app/api/weather/route.ts) |
| Misc 列表 | [app/misc/page.tsx](app/misc/page.tsx) |
| 主题 / 字体 / 导航 | app/layout.tsx、app/globals.css、app/components/nav.tsx、theme-provider.tsx |
二次分发请遵守 GPL-3.0 —— 见 [LICENSE](LICENSE)。
| 文件 | 内容 |
|---|---|
| README.md | 本文件 —— 理念 + 技术参考 |
[portfolio/oxford-dul-2025/README.md](portfolio/oxford-dul-2025/README.md) |
牛津作品集资源、路由、导出清单 |
[CONTRIBUTING.md](CONTRIBUTING.md) |
人工贡献指南 |
[AGENTS.md](AGENTS.md) |
AI agent Git 流程 |
[CLAUDE.md](CLAUDE.md) |
Claude Code 简要说明 |
[SECURITY.md](SECURITY.md) |
安全披露 |
[.env.example](.env.example) |
环境变量名 |
GNU General Public License v3.0 —— 见 [LICENSE](LICENSE)。漏洞报告见 [SECURITY.md](SECURITY.md)。