-
一定准备好一个包管理器, in case you dont have one
- windows: check out
scoop - ubuntu: you got
apt - archlinux: i use
yay, butparumay be better
- windows: check out
-
安装
node/npm + pnpm- 推荐直接运行仓库脚本,一次性补齐
node、npm和项目所需主版本的pnpm:
./scripts/install-pnpm.sh
- Windows PowerShell:
.\scripts\install-pnpm.ps1
- 如果系统里还没有
node/npm,脚本会先尝试通过系统包管理器自动安装 pnpm会优先通过corepack下载并启用- 如果你的环境没有可用的
corepack,会回退到npm install -g - 也可以手动指定版本,例如:
PNPM_VERSION=pnpm@10 ./scripts/install-pnpm.sh
- 推荐直接运行仓库脚本,一次性补齐
-
安装依赖
pnpm install
-
开造!
-
调试
pnpm dev
-
构建
pnpm build
-
本地预览构建结果
pnpm preview
-
可选格式化
pnpm prettier -w .
-
-
feel free to push,但至少先确认你改的页面能正常打开
-
component usage
-
import
在
.astro文件最上面的 frontmatter 里import其他组件,然后像 HTML 标签一样使用,例如引入 Card 之后写<Card />--- import Card from "@/components/Card.astro"; --- <Card title="Example">hello</Card>
-
props
组件参数和 React 那套意思差不多,父组件传,子组件在
Astro.props里取;适合传标题、链接、状态、class 之类结构信息--- src/components/Example.astro const { title } = Astro.props; --- <h2>{title}</h2>
--- src/contents/index.astro import Example from "@/components/Example.astro"; --- <Example title="YatCC AI" />
-
slot
slot 用来把一整段子内容塞进组件里,适合做壳子组件;如果一个组件主要负责“布局容器”而不是“具体文案”,优先考虑 slot
--- src/components/Shell.astro --- <section> <slot /> </section>
--- src/contents/index.astro import Shell from "@/components/Shell.astro"; --- <Shell> <h1>Hello</h1> <p>Some content</p> </Shell>
-
-
asset import
图片、svg 之类资源一般从 src/assets 或
public/引入;在 Astro 里可以像模块一样import img from "...png"再传给组件--- import logo from "@/assets/yatcc-icon.png"; --- <img src={logo.src} width={logo.width} height={logo.height} alt="YatCC" />
-
page content 尽量写在 src/contents 里,不要把具体文案塞进通用组件
简单说就是:
components负责“长什么样”,contents负责“写什么内容”;页面文案、卡片文字、section 标题这些都尽量放在contents--- src/components/Hero.astro const { title, subtitle } = Astro.props; --- <header> <h1>{title}</h1> <p>{subtitle}</p> </header>
--- src/contents/index.astro import Hero from "@/components/Hero.astro"; import { getLangFromUrl } from "@/i18n/utils"; const lang = getLangFromUrl(Astro.url); const t = <T,>(value: { zh: T; en: T }) => value[lang]; --- <Hero title="YatCC AI" subtitle={t({ zh: "中文介绍", en: "English introduction", })} />
-
-
全局布局 BaseLayout
每一个路由页的最外层一般都会经过它,负责默认排版、主题和全局结构
-
单页壳子 / 页面骨架
-
首页内容壳子,只负责整体结构和 slot,不负责具体文案
-
教学实践页内容壳子,只负责整体结构和 slot,不负责具体文案
-
-
页面片段组件
-
页面布局组件
-
固定高度页
-
吸附式页面布局
-
FeatureDisplayPage + FeatureDisplayPageFeature
功能展示页及其中的 feature 卡片
-
-
基础 UI
-
随主题明暗变化的黑/白按钮
-
主题色按钮
-
描边按钮
-
按钮组容器
-
卡片及卡片容器
-
小标签
-
-
导航 / 链接
-
YatCC 默认导航栏
-
主题 / 装饰 / 其他
-
llvm 龙样粒子效果,基于 three.js,一般做背景
-
原则
components尽量保持无具体内容耦合- 优先用
props、slot、shell/component 组合内容 - 如果一个组件里开始堆很多具体文案,通常应该拆去 src/contents
-
-
内容 src/contents
-
这里放“有具体页面内容”的 Astro 文件,而不是通用组件
-
文件名尽量和页面 slug 对应
- 首页: index.astro
- 教学实践: teaching-practice.astro
- 博客文章目录: blog/
-
页面文案 i18n 采用 inline 形式,靠近实际渲染位置,例如:
const t = <T,>(value: { zh: T; en: T }) => value[lang];
<h1>{t({ zh: "中文标题", en: "English Title" })}</h1>
-
不要再新建集中式 page-content dictionary,除非真的有明确复用需求
-
-
文章目录
- 所有博客文章都放在 src/contents/blog/
- 当前博客系统直接扫描这个目录下的
.md文件,不走 Astro content collection - 因此不要再新建
src/content/之类容易混淆的内容目录
-
一篇文章最少需要这些 frontmatter
--- title: "Demo/Test:首页时间线节点联调" summary: 用来测试首页 timeline 的显式 demo 文章,确认节点、跳转和时间排序都正常。 date: 2026-05-19 lang: zh category: Demo ---
字段说明:
title: 文章标题summary: 摘要,会展示在博客列表和部分首页上下文里date: 发布时间,决定排序lang: 语言,只能是zh或encategory: 可选,分类标签pinned: 可选,true时会优先排序draft: 可选,true时不会出现在页面里
-
路由约定
- 博客列表页:
/zh/blog/en/blog
- 博客详情页:
/zh/blog/<slug>/en/blog/<slug>
- 无语言前缀的
/blog会重定向到默认语言/zh/blog
- 博客列表页:
-
首页时间线
- 首页 timeline/news 区域会自动读取博客目录中的最新文章
- 宽屏下只显示当前布局能容纳的最新几篇
- 窄屏下切换为竖向时间线
- 新增文章后不需要手动改首页内容
-
新增文章 quick 'n dirty
-
在 src/contents/blog/ 新建一个 markdown 文件
-
写好 frontmatter 和正文
-
如果做双语内容,分别新建
*-zh.md和*-en.md -
运行:
pnpm build
或
pnpm dev
-
确认:
/zh/blog或/en/blog能看到文章- 首页 timeline 能看到对应节点
- 点击节点能跳到详情页
-
-
相关实现文件
- 博客读取逻辑: src/lib/blog.ts
- 首页时间线组件: src/components/HomeTimelineSection.astro
- 博客详情布局: src/layouts/BlogLayout.astro
- 博客列表页: src/pages/[lang]/blog/index.astro
- 博客详情页: src/pages/[lang]/blog/[slug].astro
-
路由 src/pages
-
无语言前缀路由入口 [[...slug].astro](<src/pages/[...slug].astro>)
负责把
/、/teaching-practice这类路径重定向到默认语言 -
带语言前缀路由入口 [[lang]/[...slug].astro](<src/pages/[lang]/[...slug].astro>)
负责把
/zh/...、/en/...分发到对应 contents 页面 -
目前内容页需要在这个文件里注册 slug,新增页面时记得一起改
-
现有中文文档页 src/pages/zh/about.md
-
博客页已拆到独立路由目录 src/pages/[lang]/blog/
- 博客文章不需要再在 [[lang]/[...slug].astro](<src/pages/[lang]/[...slug].astro>) 里手动注册
-
-
i18n src/i18n
-
其他
- 全局样式 src/styles
- 字体资源 src/fonts
- 静态资源 / 图片 src/assets
- 构建配置 astro.config.mjs
- 在 src/contents 新建一个同 slug 文件
- 在 [[lang]/[...slug].astro](<src/pages/[lang]/[...slug].astro>) 里注册这个 slug
- 如果希望无语言前缀也能访问,在 [[...slug].astro](<src/pages/[...slug].astro>) 里也加上这个 slug
- 内容写在
contents,结构拆到components
- 改动尽量小而准
- 命名尽量直接,不要为了“抽象”而抽象
- 如果你改了路由、contents 结构或 i18n 约定,请顺手更新这个文件