RealWorld 文档站实战:基于 Astro + Starlight 的文档项目结构、构建管线与命令体系
本文以 RealWorld 仓库中 docs/ 子项目自带的 README 为主线,完整讲解这个 Astro + Starlight 文档站的标准目录结构、每个目录的职责边界,以及从本地开发到生产构建的完整命令体系;并结合 astro.config.mjs、package.json 等真实配置,进一步剖析该文档站在官方 Starlight 模板之上做了哪些工程化定制(自定义 Vite 插件、Tailwind v4 主题、侧边栏组织方式)。读完后你将能够独立理解并在同类仓库中复用这套「内容路由 + 构建管线」的文档站架构。
项目定位:docs/ 是一个独立的 Astro + Starlight 子项目
RealWorld 是 The Pragmatic Programmer 社区发起的全栈 Medium 克隆示例应用(俗称 "The mother of all demo apps"),其核心交付物之一是面向各语言/框架实现者的规范文档。这些规范(实现指南、前后端规范、API 端点、错误处理等)并没有散落在仓库各处,而是统一收敛为 docs/ 目录下的一个独立文档站项目:
- 包名为
documentation(见 package.json 第 2 行),与主仓库的 Node/Django 等服务端实现解耦; - 基于 Astro 5.x 与
@astrojs/starlight0.37.x 构建(依赖声明见 package.json); - 内容以 Markdown/MDX 形式存放在
src/content/docs/下,由 Starlight 渲染成站点路由。
docs/README.md 本身源自 Starlight 官方 starter kit(文中提示 "Seasoned astronaut? Delete this file"),但在 RealWorld 仓库中被保留下来,作为说明该文档站结构与操作方式的入口文档。下文所有内容均围绕该 README 的两条主线展开:项目结构与命令体系,并补充仓库中实际存在的工程化细节。
目录结构:逐目录拆解 README 中的标准树
README 给出的标准结构如下(此处完整保留原文档的结构图,并逐条对照仓库实际内容):
.
├── public/
├── src/
│ ├── assets/
│ ├── content/
│ │ ├── docs/
│ │ └── config.ts
│ └── env.d.ts
├── astro.config.mjs
├── package.json
└── tsconfig.json
对照当前仓库,各目录的实际职责如下。
public/:原样拷贝的静态资源
README 指出:「Static assets, like favicons, can be placed in the public/ directory.」当前仓库中 docs/public/ 目录下只有 favicon.svg 一个文件。public/ 下的文件在构建时会原样进入 dist/ 根路径,不参与 Vite 的模块转换,适合存放 favicon 这类无需处理、按固定 URL 访问的资源。
src/content/docs/:内容即路由
README 的关键说明是:「Starlight looks for .md 或 .mdx files in the src/content/docs/ directory. Each file is exposed as a route based on its file name.」
在当前仓库中,这个目录承载了全部规范文档,组织为四个板块:
| 板块 | 路径(相对仓库根目录) | 内容 |
|---|---|---|
| 实现指南 | docs/src/content/docs/implementation-creation/ | introduction.md、features.md、expectations.md,定义 Conduit(Medium 克隆)应实现的完整功能面 |
| 前端规范 | docs/src/content/docs/specifications/frontend/ | templates.md、styles.md、routing.md、api.md、tests.md |
| 后端规范 | docs/src/content/docs/specifications/backend/ | endpoints.md、api-response-format.md、cors.md、error-handling.md、hurl.md、tests.md 等 |
| 社区 | docs/src/content/docs/community/ | authors.md、resources.md、special-thanks.md |
文件名即路由:例如 specifications/backend/endpoints.md 会暴露为站点上的 /specifications/backend/endpoints 页面。站点首页 index.mdx 使用了 Starlight 的 template: splash 模板,frontmatter 中声明了 hero 标语和 realworld-logo.png 头图。
src/content/config.ts:内容集合的 Schema 声明
Starlight 要求为内容目录注册一个 collection。当前仓库的 docs/src/content/config.ts 完整内容如下:
import { defineCollection } from 'astro:content';
import { docsSchema } from '@astrojs/starlight/schema';
export const collections = {
docs: defineCollection({ schema: docsSchema() }),
};
docsSchema() 由 Starlight 提供,用于校验每篇文档 frontmatter 中 title、description、template、hero 等字段,配合 TypeScript 可获得内容层的类型检查。
src/assets/:参与构建的图片资源
README 说明:「Images can be added to src/assets/ and embedded in Markdown with a relative link.」与 public/ 的区别在于:src/assets/ 下的资源会经过 Astro 构建管线(按需优化、URL 重写)。当前仓库的 docs/src/assets/img/ 存放了站点实际引用的图片,如 realworld-logo.png、realworld-dual-mode.png、codebaseshow-logo.png 等。内容文档中以相对路径引用,例如 index.mdx 中的:
image:
file: ../../assets/img/realworld-logo.png
src/env.d.ts、astro.config.mjs、tsconfig.json
-
docs/src/env.d.ts 仅两行,引入 Astro 生成的类型与客户端类型引用,是类型体系的入口:
/// <reference path="../.astro/types.d.ts" /> /// <reference types="astro/client" /> -
docs/tsconfig.json 继承
astro/tsconfigs/strict(严格模式),并开启jsx: react-jsx与jsxImportSource: react——这说明该文档站除了 MDX 之外还支持在内容中嵌入 React 组件(@astrojs/react、react、react-dom均声明在 package.json 的依赖中)。 -
docs/astro.config.mjs 是整个文档站的工程化核心,下一节展开。
命令体系:从 README 表格到真实 script 定义
README 给出的命令表(完整保留):
| Command | Action |
|---|---|
npm install |
Installs dependencies |
npm run dev |
Starts local dev server at localhost:4321 |
npm run build |
Build your production site to ./dist/ |
npm run preview |
Preview your build locally, before deploying |
npm run astro ... |
Run CLI commands like astro add, astro check |
npm run astro -- --help |
Get help using the Astro CLI |
对照 docs/package.json 中实际注册的 scripts,可以确认各命令的真实落点:
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro check && astro build",
"preview": "astro preview",
"astro": "astro"
}
由此得到三点比 README 更精确的补充事实:
npm run build并非单纯的构建,而是astro check && astro build的两阶段流水线——先执行@astrojs/check对全项目(包括内容层与 TS 配置)做类型检查,检查通过后才进入astro build输出静态站点到dist/。这意味着类型错误会直接阻断文档站的构建发布。start与dev等价,都是astro dev,本地开发服务器默认监听localhost:4321(Astro 的默认端口)。npm run astro ...是转义通道:script 名为astro且内容为astro,因此npm run astro check实际执行的是astro check,npm run astro -- --help执行astro --help。
另外一个实操细节:仓库在 docs/ 下提供的是 bun.lock 锁文件而非 package-lock.json,说明当前维护流程使用 bun 作为包管理器,bun install 即可复现锁定依赖;README 中的 npm install 作为通用写法仍然适用。
构建管线定制:README 之外的源码级工程细节
README 描述的是 Starlight 官方 starter 的基线;而 docs/ 在此之上叠加了多处定制,全部集中在 astro.config.mjs 与 src/tailwind.css。
自定义 Vite 插件 removeMdExtension
astro.config.mjs 定义了一个内联 Vite 插件:
function removeMdExtension() {
return {
name: 'remove-md-extension',
enforce: 'pre',
transform(code, id) {
if (id.endsWith('.md')) {
return code.replace(/\.md/g, '');
}
return code;
},
};
};
该插件在 pre 阶段运行(先于其他转换),对所有以 .md 结尾的模块做字符串级替换,把文档内部指向其他 Markdown 页面的 .md 后缀从 URL 中抹掉——效果是页面间互相链接时呈现 /specifications/backend/endpoints 而非 /specifications/backend/endpoints.md,与 Starlight「文件名即路由、URL 不带扩展名」的约定保持一致。插件挂载位置见 astro.config.mjs 的 vite.plugins: [tailwindcss(), removeMdExtension()]。
Tailwind CSS v4 主题与 Starlight 调色板覆盖
文档站通过 @tailwindcss/vite 插件接入 Tailwind v4,并使用 @astrojs/starlight-tailwind 桥接(ssr.noExternal 中对它的显式声明见 astro.config.mjs)。docs/src/tailwind.css 中做了两类定制:
@theme覆盖:重写accent色阶(#a700c3紫红主色)与整套gray色阶(从#f8f4fe到#1c1425的偏紫中性色),使深色/浅色模式下站点整体呈现品牌紫色调,而非 Starlight 默认配色;- Markdown 列表样式恢复:Starlight 会重置列表符号,tailwind.css 针对
.sl-markdown-content逐级恢复ul(disc/circle/square)与ol(decimal)的默认符号与缩进,保证规范文档中的列表可读性。
侧边栏:三大板块的导航组织
Starlight 的 sidebar 配置(astro.config.mjs)将站点组织为三个顶级分组,每个叶子项以 slug 指向内容路由:
- Implementation creation:
introduction/features/expectations; - Specifications:下挂 Frontend、Backend 两个子分组(各 5–7 个端点/规范页)以及 Mobile specifications;
- Community:
authors/resources/special-thanks。
值得注意的是 Backend 分组中列出的 Hurl 页面,与仓库 specs/api/hurl/ 下的 Hurl 测试集、以及 specs/api/run-api-tests-hurl.sh 形成文档与测试脚本的呼应——规范文档中的 Hurl 章节正是指导贡献者使用这套 API 测试资产。
快速上手清单
综合 README 与仓库实际配置,对 docs/ 文档站的完整操作路径为:
- 在
docs/目录下执行bun install(或npm install)安装依赖(锁定依赖见 bun.lock); npm run dev启动开发服务器,访问localhost:4321,编辑src/content/docs/下的 Markdown 即可获得路由级热更新;- 新增文档时,文件放入 docs/src/content/docs/ 对应子目录,并在 astro.config.mjs 的
sidebar中登记slug,否则页面存在但不出现在导航中; npm run build先跑astro check类型检查、再产出dist/静态站点;npm run preview在部署前本地预览构建产物。
小结
docs/README.md 作为 Starlight starter 的项目说明,定义了「内容目录 → 路由」「public/ 与 src/assets/ 的静态资源分工」以及五类标准命令这条基线;而当前仓库在此基础上,通过 astro check 前置的类型检查、removeMdExtension 插件的 URL 净化、Tailwind v4 品牌主题和三大板块侧边栏,把模板升级为一个可维护的规范文档站。理解这两层——starter 基线与项目定制——即可将该模式迁移到其他需要「Markdown 即规范、静态构建即发布」的开源项目文档体系中。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00