跳到正文
Elaine Blog
返回

博客生成细则

文档编写

本文说明如何在 Elaine Blog 中创建和管理文章。按照这些规则,你可以控制文章的访问地址、发布时间、目录结构、图片和发布状态。

目录

创建文章

src/content/posts/ 中创建 .md.mdx 文件。正式文章的文件名不能以 _ 开头,否则 Astro 不会加载它。

以下示例创建一篇 Markdown 文章:

src/content/posts/my-first-post.md

文章至少需要包含标题、发布时间、分类和摘要:

---
title: 我的第一篇博客
pubDatetime: 2026-08-27T10:00:00+08:00
category: docs
description: 介绍这篇博客的主要内容。
---

## 前言

从这里开始编写正文。

构建完成后,这篇文章的访问地址为:

/posts/my-first-post/
Warning

不要使用 _my-first-post.md 作为正式文章文件名。当前内容加载规则会忽略所有以 _ 开头的 Markdown 和 MDX 文件。

选择 Markdown 或 MDX

普通文章使用 .md。需要导入 Astro 组件或编写 JSX 表达式时,使用 .mdx

格式适用场景是否支持导入组件
.md标题、列表、表格、图片和代码块等普通文章
.mdx自定义组件、交互内容和复杂布局

下面的 MDX 示例导入了项目组件:

---
title: MDX 示例
pubDatetime: 2026-08-27T10:00:00+08:00
category: docs
description: 展示如何在文章中使用 Astro 组件。
---

import ResponsiveTable from "@/components/ResponsiveTable.astro";

<ResponsiveTable variant="striped-minimal">

| 名称  | 说明         |
| ----- | ------------ |
| Astro | 静态网站框架 |

</ResponsiveTable>

组织文章目录

你可以将文章直接放在 posts 下,也可以使用多级子目录。普通目录名会成为文章 URL 的一部分。

文件位置访问地址是否加载
posts/hello.md/posts/hello/
posts/java/spring.md/posts/java/spring/
posts/_java/spring.md/posts/spring/
posts/java/_legacy/spring.md/posts/java/spring/
posts/_demo/_hello.md

_ 开头的目录只会从 URL 中移除目录名,不会自动隐藏目录里的文章。只有文章文件名以 _ 开头时,内容加载器才会忽略该文件。

当前项目将原始示例文章保存在:

src/content/posts/_demo/

该目录中的文章文件全部以 _ 开头,因此不会出现在首页、文章列表、标签、RSS 或文章详情页中。

Tip

如果目录只用于整理文件,不希望目录名出现在 URL 中,请给目录名添加 _ 前缀。如果希望隐藏文章,请同时给文章文件名添加 _ 前缀。

不同文件不能生成相同的 URL。例如,以下两个文件都会尝试生成 /posts/hello/

posts/_java/hello.md
posts/_astro/hello.md

创建文章前,请检查文件名和 slug,避免 URL 冲突。

配置 Frontmatter

Frontmatter 位于文章顶部的两组 --- 之间,用来定义文章元数据。

必填字段

字段类型说明
title字符串文章标题
pubDatetime日期ISO 8601 格式的发布时间
category字符串文章所属的分类 ID,通常填写叶子分类
description字符串用于文章列表、搜索和 SEO 的摘要

可选字段

字段类型默认值或作用
slug字符串覆盖文件名生成的 URL
author字符串默认使用站点作者 Elaine
modDatetime日期文章最后修改时间
featured布尔值是否显示在首页精选文章区域
draft布尔值设置为 true 时不发布文章
tags字符串数组默认使用 others 标签
ogImage图片或 URL社交平台分享预览图
canonicalURLURL文章在其他网站的原始地址
hideEditPost布尔值是否隐藏文章编辑入口
timezone字符串覆盖站点默认时区

推荐使用以下完整模板:

---
title: 文章标题
slug: article-slug
author: Elaine
pubDatetime: 2026-08-27T10:00:00+08:00
modDatetime:
featured: false
draft: false
category: docs
tags:
  - Astro
  - 博客
description: 用一句话说明文章解决的问题或介绍的内容。
---

## 前言

在这里编写正文。

设置稳定的 URL

如果文件名可能变化,设置 slug 保持访问地址稳定:

slug: astro-blog-guide

对应的访问地址为:

/posts/astro-blog-guide/

文章发布后尽量不要修改 slug。修改后,旧链接将无法访问,除非额外配置重定向。

使用多级分类

分类统一配置在 src/data/categories.ts。每个分类使用稳定的英文 ID,并通过 parent 指向父分类;不设置 parent 的分类是一级分类。

export const categoryIds = ["knowledge", "docs", "astro"] as const;

export const categories = {
  knowledge: {
    name: "知识库",
    description: "系统整理和持续维护的知识内容。",
  },
  docs: {
    name: "文档编写",
    description: "Markdown、MDX 与内容发布指南。",
    parent: "knowledge",
  },
  astro: {
    name: "Astro",
    description: "Astro 开发与博客建设实践。",
    parent: "docs",
  },
};

以上配置形成“知识库 → 文档编写 → Astro”三级结构。文章只需填写它直接所属的分类 ID:

category: astro

分类页面会自动生成完整路径:

/categories/knowledge/
/categories/knowledge/docs/
/categories/knowledge/docs/astro/

分类页面采用逐级导航:一级分类页只显示直属二级分类,二级分类仍有子分类时继续显示直属三级分类;只有没有子分类的分类页才显示文章。父分类卡片上的文章数量会统计整个分支。

同一个分类不能同时拥有直属文章和子分类。例如 docs 已经包含 astro 子分类后,文章就不能再使用 category: docs,必须放入 astro 或另一个叶子分类。构建程序会检查这一规则并报告冲突文章。

文章可以直接属于一级、二级或三级分类,前提是该分类没有子分类。分类 ID 必须全局唯一;移动分类时只需修改 parent,文章中的 category 不需要改动。

管理文章状态和排序

使用 draftpubDatetimemodDatetime 控制文章是否发布以及文章的排列顺序。

保存草稿

如果文章还不能发布,将 draft 设置为 true

draft: true

草稿不会生成文章详情页,也不会出现在首页、列表、标签或 RSS 中。

设置定时发布

pubDatetime 设置为未来时间,可以创建定时文章:

pubDatetime: 2026-09-01T09:00:00+08:00

开发环境会显示所有非草稿文章,便于预览。生产构建只包含已经到达发布时间的文章,并应用项目配置的发布时间容差。

控制排序

文章列表默认使用 date-desc,按时间倒序排列:

  1. 如果存在 modDatetime,使用最后修改时间排序。
  2. 如果没有 modDatetime,使用发布时间排序。
  3. 时间越新的文章越靠前。

连续教程或系列文章可以在分类配置中使用 filename-asc

"llm-basic": {
  name: "LLM 基础",
  description: "理解大语言模型原理、API 形态和生产工程基础。",
  parent: "agent-runtime",
  postSort: "filename-asc",
}

filename-asc 会读取文件名开头的数字,并在分类分页前按数字从小到大排序:

01-token与tokenizer.md
02-transformer与attention.md
03-上下文窗口与长上下文.md

数字后可以使用 -_.。没有数字前缀的文件会排在编号文章之后。文件名编号只控制分类文章列表,不改变首页、归档和全站文章列表的时间排序。

设置 featured: true 后,文章还会显示在首页精选文章区域。

添加图片

你可以使用远程图片,也可以将图片放在文章附近并使用相对路径引用。

使用远程图片

![Elaine Blog 示例图片](https://example.com/example.png)

使用本地图片

使用以下目录结构保存文章和图片:

src/content/posts/tutorial/
├── astro-guide.md
└── assets/
    └── astro-cover.png

astro-guide.md 中使用相对路径:

![Astro 教程封面](./assets/astro-cover.png)

也可以将图片设置为文章分享图:

ogImage: ./assets/astro-cover.png

每张图片都应包含有意义的替代文本。不要使用“图片”或“截图”等无法描述内容的文字。

添加图表

新的正式文章优先使用 D2,部署时会自动生成深浅色 SVG。Mermaid 适合临时草图和少量必须在 Markdown 内维护的简单图。

图表类型推荐工具原因
临时草图、文内示例Mermaid代码块可直接渲染
时序图、状态图D2部署时生成 SVG,展示更稳定
多阶段流程、系统架构D2支持网格和 ELK 布局
需要精确位置的图SVG可以完全控制位置和比例

使用 Mermaid

在 Markdown 或 MDX 中添加 mermaid 代码块:

```mermaid
sequenceDiagram
    participant App as 应用
    participant Model as 模型
    App->>Model: 提交请求
    Model-->>App: 返回结果
```

文章页面只在检测到 Mermaid 代码块时加载渲染库。图表支持深浅色主题和全屏缩放预览。

使用 D2

D2 源文件和生成的 SVG 使用相同的相对路径:

src/diagrams/agent-runtime/llm-basic/token-processing.d2
public/diagrams/agent-runtime/llm-basic/token-processing.svg
public/diagrams/agent-runtime/llm-basic/token-processing-dark.svg

创建或修改 .d2 文件后,可以在本机预先生成图表:

pnpm diagrams:build

本机预览命令需要安装 d2。macOS 可以使用 Homebrew 安装:

brew install d2

在文章中引用生成的 SVG:

![从输入准备到增量解码的 Token 处理流程](/diagrams/agent-runtime/llm-basic/token-processing.svg)

只修改 src/diagrams/ 中的源文件,不要手动修改 public/diagrams/ 中的 SVG。生成命令会同时输出浅色版 .svg 和深色版 -dark.svg,博客会根据当前主题自动切换。pnpm run build 会比较源文件哈希与两个 SVG 中的标记。

运行 ../elaine-cicd/dev/build-elaine-blog.sh 时,Docker 会安装固定版本的 D2,先执行 pnpm diagrams:build,再构建 Astro。因此部署不依赖本机的 D2,也不会使用过期的 SVG。D2 不直接解析 Mermaid 语法;需要迁移时,先将 Mermaid 图改写为 .d2 源文件。

检查并发布文章

在项目目录中执行以下步骤:

  1. 启动开发服务器并预览文章:

    pnpm run dev
  2. 检查文章标题、摘要、时间、标签、图片和链接。

  3. 运行生产构建:

    pnpm run build
  4. 确认构建结果中没有内容校验错误。

  5. 使用本地部署脚本重新构建并启动 Docker 容器:

    cd ../elaine-cicd/dev
    ./build-elaine-blog.sh

如果需要修改本地端口,在运行部署脚本时传入 ELAINE_BLOG_PORT

ELAINE_BLOG_PORT=9000 ./build-elaine-blog.sh

下一步


分享这篇文章:

下一篇
MDX 详细使用指南