本博客代码修改指南
代码修改指南
Mingrui Blog 常见改代码需求指南
目录
- 先理解项目怎么运行
- 最常改的文件速查表
- 新增、修改、删除博客文章
- 修改首页
- 修改关于页
- 修改顶部导航栏和全站布局
- 修改博客列表页
- 修改文章详情页
- 修改归档页
- 修改标签页
- 修改全站样式
- 修改文章正文样式
- 添加图片、头像和静态资源
- 添加文章封面图
- 添加文章阅读时间
- 添加上一篇 / 下一篇文章
- 添加 RSS
- 添加 sitemap
- 增强 SEO
- 添加搜索功能
- 文章变多后添加分页
- 修改 favicon
- 修改域名和部署配置
- 同步 README
- 清理模板遗留文件
- 日常开发流程
- 发布前检查清单
- 常见问题排查
- 建议的后续开发顺序
1. 先理解项目怎么运行
Mingrui Blog 是一个 Astro 静态博客项目。
你可以这样理解它:
Markdown / MDX 文章
↓
Astro Content Collections 读取文章
↓
src/pages/ 里的页面生成首页、博客列表、文章详情、归档和标签页
↓
src/layouts/BaseLayout.astro 统一包住页面
↓
src/styles/global.css 控制全站样式
↓
npm run build 生成 dist/ 静态网站
平时开发主要做三件事:
npm run dev
用于本地开发预览。
npm run build
用于正式构建,检查项目是否能成功生成静态网站。
npm run preview
用于本地预览生产构建结果。
2. 最常改的文件速查表
| 需求 | 主要修改位置 |
|---|---|
| 新增文章 | src/content/blog/ |
| 修改文章内容 | src/content/blog/某篇文章.md |
| 修改首页 | src/pages/index.astro |
| 修改关于页 | src/pages/about.astro |
| 修改博客列表页 | src/pages/blog/index.astro |
| 修改文章详情页 | src/pages/blog/[slug].astro |
| 修改归档页 | src/pages/archive.astro |
| 修改标签总览页 | src/pages/tags/index.astro |
| 修改标签详情页 | src/pages/tags/[tag].astro |
| 修改顶部导航栏 | src/layouts/BaseLayout.astro |
| 修改全站 HTML head、meta、favicon | src/layouts/BaseLayout.astro |
| 修改全站样式 | src/styles/global.css |
| 修改文章字段规则 | src/content.config.ts |
| 修改路径拼接逻辑 | src/utils/basePath.ts |
| 添加图片、favicon 等静态资源 | public/ |
| 修改域名 | astro.config.mjs |
| 修改 npm 命令或依赖 | package.json |
| 修改项目说明 | README.md |
| 配置 GitHub Actions 部署 | .github/workflows/ |
3. 新增、修改、删除博客文章
3.1 新增一篇文章
文章放在:
src/content/blog/
例如新建:
src/content/blog/my-first-real-post.md
基本模板:
---
title: "我的第一篇正式文章"
description: "这是一篇关于我开始写个人博客的记录。"
pubDate: 2026-05-06
updatedDate: 2026-05-06
tags: ["Blog", "Astro", "学习"]
draft: false
---
这里开始写正文。
## 为什么我要写博客
正文内容……
## 后续计划
正文内容……
3.2 frontmatter 字段说明
文章顶部的这段叫 frontmatter:
---
title: "文章标题"
description: "文章摘要"
pubDate: 2026-05-06
updatedDate: 2026-05-06
tags: ["Astro", "Blog"]
draft: false
---
每个字段的作用:
| 字段 | 是否必填 | 作用 |
|---|---|---|
title | 是 | 文章标题 |
description | 是 | 文章摘要,也会用于列表页和 meta description |
pubDate | 是 | 发布日期,用于排序和归档 |
updatedDate | 否 | 更新日期 |
tags | 否 | 标签数组,用于标签统计和标签页 |
draft | 否 | 是否草稿,默认通常为 false |
3.3 文章 URL 是怎么来的
文章文件名会影响 URL。
例如:
src/content/blog/hello-blog.md
会生成:
/blog/hello-blog/
再比如:
src/content/blog/learning-astro.md
会生成:
/blog/learning-astro/
建议文件名使用英文、小写、短横线:
good:
learning-astro.md
my-first-project.md
how-i-built-my-blog.md
not recommended:
我的文章.md
My First Blog.md
test 1.md
3.4 写草稿
如果文章还没写完,不想公开,设置:
draft: true
例如:
---
title: "还没写完的文章"
description: "这篇文章还在草稿阶段。"
pubDate: 2026-05-06
tags: ["Draft"]
draft: true
---
草稿文章不会出现在:
- 首页最近文章
- 博客列表页
- 文章详情页
- 归档页
- 标签总览页
- 标签详情页
发布时再改成:
draft: false
3.5 修改文章
直接打开对应 Markdown 文件修改即可。
例如:
src/content/blog/hello-blog.md
修改标题:
title: "新的文章标题"
修改正文:
## 新的小标题
新的正文内容。
3.6 删除文章
直接删除对应 .md 或 .mdx 文件。
例如删除:
src/content/blog/hello-blog.md
删除后重新运行:
npm run dev
或:
npm run build
检查是否还有错误。
3.7 修改文章标签
例如原来是:
tags: ["Astro", "Blog"]
想加一个“前端”:
tags: ["Astro", "Blog", "前端"]
标签会自动出现在:
/tags/
对应标签详情页会自动生成:
/tags/Astro/
/tags/Blog/
/tags/前端/
3.8 修改发布日期
例如:
pubDate: 2026-05-06
发布日期会影响:
- 首页最近文章排序
- 博客列表排序
- 归档页年份分组
- 标签页文章排序
如果文章只是更新内容,不建议改 pubDate,可以改:
updatedDate: 2026-05-10
4. 修改首页
首页文件:
src/pages/index.astro
首页路径:
/
当前首页通常负责:
- 展示博客名称
- 展示个人简介
- 展示进入博客、关于页的按钮
- 展示最近文章
- 展示“我会写什么”
- 展示关于页入口
4.1 修改首页标题和简介
在 src/pages/index.astro 中找类似内容:
<h1>Mingrui Blog</h1>
<p>记录学习、项目实践、工具使用心得和生活思考。</p>
可以改成:
<h1>Mingrui 的个人博客</h1>
<p>这里记录我的学习笔记、项目实践、技术踩坑和生活思考。</p>
4.2 修改首页按钮
可能会看到类似:
<a href={withBase('/blog/')}>阅读博客</a>
<a href={withBase('/about/')}>关于我</a>
你可以修改按钮文字:
<a href={withBase('/blog/')}>开始阅读</a>
<a href={withBase('/about/')}>了解我</a>
也可以增加一个 GitHub 按钮:
<a href="https://github.com/你的用户名" target="_blank" rel="noreferrer">
GitHub
</a>
4.3 修改首页最近文章数量
找类似代码:
const recentPosts = posts.slice(0, 3);
如果想展示最近 5 篇:
const recentPosts = posts.slice(0, 5);
4.4 修改首页“我会写什么”
找类似结构:
<section>
<h2>我会写什么</h2>
<ul>
<li>学习</li>
<li>项目实践</li>
<li>工具使用</li>
<li>生活思考</li>
</ul>
</section>
可以改成:
<section>
<h2>我会写什么</h2>
<ul>
<li>前端学习笔记</li>
<li>个人项目复盘</li>
<li>AI 工具使用心得</li>
<li>生活和成长记录</li>
</ul>
</section>
4.5 首页没有文章时显示什么
博客刚开始可能文章很少,首页通常会有空状态。
例如:
{recentPosts.length === 0 && (
<p>暂时还没有文章。</p>
)}
你可以改成:
{recentPosts.length === 0 && (
<p>文章正在准备中,欢迎稍后再来看看。</p>
)}
5. 修改关于页
关于页文件:
src/pages/about.astro
访问路径:
/about/
5.1 修改个人介绍
找类似内容:
<h1>关于我</h1>
<p>我是 Mingrui。</p>
改成你自己的介绍:
<h1>关于我</h1>
<p>
你好,我是 Mingrui。我正在学习前端开发、个人知识管理和 AI 工具使用。
这个博客用来记录我的学习过程、项目实践和一些生活思考。
</p>
5.2 修改“我现在关注什么”
例如:
<h2>我现在关注什么</h2>
<ul>
<li>Astro 和静态站点搭建</li>
<li>前端基础</li>
<li>AI 工具辅助学习</li>
</ul>
你可以根据自己的真实情况改。
5.3 修改联系方式
如果现在是占位链接:
<a href="#">Email</a>
<a href="#">GitHub</a>
<a href="#">LinkedIn</a>
发布前建议不要保留 #。
你可以改成真实链接:
<a href="mailto:your-email@example.com">Email</a>
<a href="https://github.com/your-name" target="_blank" rel="noreferrer">GitHub</a>
<a href="https://www.linkedin.com/in/your-name/" target="_blank" rel="noreferrer">LinkedIn</a>
如果暂时不想公开联系方式,可以先删除:
<section>
<h2>联系方式</h2>
<p>暂时不公开联系方式。</p>
</section>
5.4 加头像
先把头像放到:
public/images/avatar.png
然后在 about.astro 里添加:
<img src={withBase('/images/avatar.png')} alt="Mingrui 的头像" class="avatar" />
再到 src/styles/global.css 添加样式:
.avatar {
width: 120px;
height: 120px;
border-radius: 999px;
object-fit: cover;
}
6. 修改顶部导航栏和全站布局
核心布局文件:
src/layouts/BaseLayout.astro
它负责:
- 引入全局样式
- 设置 HTML head
- 设置网页 title
- 设置 description
- 设置 favicon
- 设置 Open Graph
- 输出顶部 header
- 输出导航栏
- 用
<slot />放具体页面内容
6.1 修改网站名
找类似内容:
<a href={withBase('/')}>Mingrui Blog</a>
改成:
<a href={withBase('/')}>Mingrui 的博客</a>
6.2 添加导航项
原来可能是:
<nav>
<a href={withBase('/')}>首页</a>
<a href={withBase('/blog/')}>博客</a>
<a href={withBase('/archive/')}>归档</a>
<a href={withBase('/about/')}>关于</a>
</nav>
如果想加“标签”:
<nav>
<a href={withBase('/')}>首页</a>
<a href={withBase('/blog/')}>博客</a>
<a href={withBase('/archive/')}>归档</a>
<a href={withBase('/tags/')}>标签</a>
<a href={withBase('/about/')}>关于</a>
</nav>
6.3 修改网页默认标题格式
页面一般会传入:
<BaseLayout title="首页标题" description="页面描述">
BaseLayout.astro 中可能有:
<title>{title}</title>
如果你想统一加站点名:
<title>{title ? `${title} | Mingrui Blog` : 'Mingrui Blog'}</title>
注意:如果文章详情页已经传了 "文章标题 - Mingrui Blog",就不要重复加两次。你需要统一全站标题规则。
6.4 修改全站 description
在 BaseLayout.astro 里找:
<meta name="description" content={description} />
每个页面传入的 description 会显示在这里。
如果某些页面没有传,可以设置默认值:
const {
title = 'Mingrui Blog',
description = 'Mingrui 的个人博客,记录学习、项目实践、工具使用心得和生活思考。',
} = Astro.props;
6.5 修改 favicon 引用
可能会看到:
<link rel="icon" href={withBase('/favicon.svg')} />
如果你换成 PNG:
<link rel="icon" type="image/png" href={withBase('/favicon.png')} />
对应文件要放到:
public/favicon.png
7. 修改博客列表页
文件:
src/pages/blog/index.astro
访问路径:
/blog/
7.1 修改列表页标题
找:
<h1>博客</h1>
可以改成:
<h1>全部文章</h1>
7.2 修改文章卡片展示内容
文章列表一般会循环:
{posts.map((post) => (
<article class="post-item">
<h2>
<a href={withBase(`/blog/${post.id}/`)}>{post.data.title}</a>
</h2>
<p>{post.data.description}</p>
</article>
))}
你可以增加日期:
<time datetime={post.data.pubDate.toISOString()}>
{post.data.pubDate.toLocaleDateString('zh-CN')}
</time>
可以增加标签:
<div class="tags">
{post.data.tags.map((tag) => (
<a href={withBase(`/tags/${tag}/`)} class="tag">{tag}</a>
))}
</div>
7.3 修改排序方式
通常会看到:
posts.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
这是从新到旧。
如果想从旧到新:
posts.sort((a, b) => a.data.pubDate.valueOf() - b.data.pubDate.valueOf());
7.4 隐藏草稿逻辑
通常会有:
const posts = (await getCollection('blog')).filter((post) => !post.data.draft);
这表示过滤掉草稿。
不要随便删掉这段,否则 draft: true 的文章也可能被公开。
8. 修改文章详情页
文件:
src/pages/blog/[slug].astro
访问路径类似:
/blog/hello-blog/
8.1 修改文章标题区域
你可能会看到:
<h1>{post.data.title}</h1>
<p>{post.data.description}</p>
可以改成:
<header class="post-header">
<h1>{post.data.title}</h1>
<p class="post-description">{post.data.description}</p>
</header>
然后到 global.css 添加样式:
.post-header {
margin-bottom: 2rem;
}
.post-description {
color: #666;
font-size: 1.1rem;
}
8.2 修改日期显示
可能有:
<time>{post.data.pubDate.toLocaleDateString('zh-CN')}</time>
你可以显示更完整:
<p>
发布于:
<time datetime={post.data.pubDate.toISOString()}>
{post.data.pubDate.toLocaleDateString('zh-CN')}
</time>
</p>
显示更新时间:
{post.data.updatedDate && (
<p>
更新于:
<time datetime={post.data.updatedDate.toISOString()}>
{post.data.updatedDate.toLocaleDateString('zh-CN')}
</time>
</p>
)}
8.3 修改正文区域
文章正文一般来自:
<Content />
或者类似:
<div class="content">
<Content />
</div>
.content 的样式通常在:
src/styles/global.css
如果你想修改正文的段落、标题、代码块、引用样式,主要改 .content 相关 CSS。
8.4 添加返回按钮
例如:
<a href={withBase('/blog/')}>← 返回博客列表</a>
可以改成:
<nav class="post-nav">
<a href={withBase('/blog/')}>← 查看全部文章</a>
</nav>
9. 修改归档页
文件:
src/pages/archive.astro
访问路径:
/archive/
9.1 修改归档页标题
<h1>归档</h1>
可以改成:
<h1>文章归档</h1>
9.2 当前按年份分组
归档页一般会按照 pubDate 的年份分组。
例如:
2026
05-06 文章 A
05-05 文章 B
9.3 如果想按月份分组
可以把分组 key 从年份改成年月。
原本可能类似:
const year = post.data.pubDate.getFullYear();
改成:
const year = post.data.pubDate.getFullYear();
const month = String(post.data.pubDate.getMonth() + 1).padStart(2, '0');
const key = `${year}-${month}`;
这样可以分成:
2026-05
2026-04
2026-03
9.4 修改归档项显示内容
原来可能只显示:
<a href={withBase(`/blog/${post.id}/`)}>{post.data.title}</a>
可以加摘要:
<p>{post.data.description}</p>
也可以加标签:
<div class="tags">
{post.data.tags.map((tag) => (
<a href={withBase(`/tags/${tag}/`)} class="tag">{tag}</a>
))}
</div>
10. 修改标签页
标签相关文件:
src/pages/tags/index.astro
src/pages/tags/[tag].astro
10.1 标签总览页
文件:
src/pages/tags/index.astro
访问路径:
/tags/
它负责统计所有标签,并显示每个标签下有几篇文章。
10.2 修改标签排序
当前通常是:
- 文章数量多的排前面
- 数量相同按中文排序
如果你想按标签名称排序:
tags.sort((a, b) => a.name.localeCompare(b.name, 'zh-CN'));
如果想按数量排序:
tags.sort((a, b) => b.count - a.count);
10.3 标签详情页
文件:
src/pages/tags/[tag].astro
访问路径:
/tags/Astro/
它展示某个标签下的全部文章。
10.4 修改标签页文章卡片
和博客列表页类似,可以在循环里修改:
{posts.map((post) => (
<article class="post-item">
<h2>
<a href={withBase(`/blog/${post.id}/`)}>{post.data.title}</a>
</h2>
<p>{post.data.description}</p>
</article>
))}
11. 修改全站样式
文件:
src/styles/global.css
这是美化博客最常用的文件。
11.1 修改全站字体
可能会看到:
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
你可以改成:
body {
font-family:
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
"PingFang SC",
"Microsoft YaHei",
sans-serif;
}
11.2 修改背景色
原来:
body {
background: #fafafa;
}
改成更温和的背景:
body {
background: #f7f7f5;
}
11.3 修改正文颜色
body {
color: #222;
}
可以改成:
body {
color: #1f2933;
}
11.4 修改页面最大宽度
可能有:
main {
max-width: 760px;
}
如果想变宽:
main {
max-width: 860px;
}
如果想文章阅读更窄:
main {
max-width: 720px;
}
11.5 修改顶部 header 宽度
可能有:
.site-header {
max-width: 860px;
}
可以改成:
.site-header {
max-width: 960px;
}
11.6 修改文章卡片
可能有:
.post-item {
background: #fff;
border: 1px solid #e5e5e5;
border-radius: 8px;
padding: 1rem;
}
可以改成更柔和:
.post-item {
background: #fff;
border: 1px solid #e8e8e8;
border-radius: 12px;
padding: 1.25rem;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.04);
}
11.7 修改链接颜色
a {
color: #2563eb;
}
可以改成:
a {
color: #0f766e;
}
11.8 修改标签样式
可能有:
.tag {
border-radius: 999px;
padding: 0.2rem 0.6rem;
}
可以改成:
.tag {
display: inline-flex;
align-items: center;
border-radius: 999px;
padding: 0.25rem 0.7rem;
background: #f1f5f9;
color: #475569;
font-size: 0.85rem;
text-decoration: none;
}
11.9 修改移动端样式
通常在 CSS 底部会有:
@media (max-width: 640px) {
...
}
你可以在里面改手机端布局。
例如:
@media (max-width: 640px) {
main {
padding: 1rem;
}
.site-header {
flex-direction: column;
align-items: flex-start;
}
}
12. 修改文章正文样式
文章正文通常包在:
<div class="content">
...
</div>
所以重点改:
src/styles/global.css
里面的 .content 相关样式。
12.1 修改段落行高
.content p {
line-height: 1.8;
}
如果觉得太松:
.content p {
line-height: 1.7;
}
12.2 修改标题间距
.content h2 {
margin-top: 2rem;
margin-bottom: 1rem;
}
12.3 修改引用样式
.content blockquote {
border-left: 4px solid #ddd;
padding-left: 1rem;
color: #666;
}
可以改成:
.content blockquote {
border-left: 4px solid #94a3b8;
padding: 0.75rem 1rem;
background: #f8fafc;
color: #475569;
}
12.4 修改代码块样式
行内代码:
.content code {
background: #f1f5f9;
padding: 0.15rem 0.35rem;
border-radius: 4px;
}
代码块:
.content pre {
overflow-x: auto;
padding: 1rem;
border-radius: 8px;
background: #0f172a;
}
12.5 修改图片样式
.content img {
max-width: 100%;
border-radius: 8px;
display: block;
margin: 1.5rem auto;
}
13. 添加图片、头像和静态资源
13.1 推荐放到 public/images/
新建目录:
public/images/
放图片:
public/images/avatar.png
public/images/post-cover.jpg
public/images/project-demo.png
13.2 在页面中引用
如果不用 withBase():
<img src="/images/avatar.png" alt="头像" />
如果使用 withBase():
<img src={withBase('/images/avatar.png')} alt="头像" />
为了兼容未来 base 路径,建议使用 withBase()。
13.3 在 Markdown 文章中引用图片
例如图片放在:
public/images/astro-note.png
Markdown 中写:

如果未来部署到子路径,这种写法可能需要额外处理。当前自定义域名根路径下通常没问题。
13.4 图片命名建议
推荐:
avatar.png
astro-blog-cover.jpg
project-demo-01.png
不推荐:
图片1.png
我的 截图.png
Screen Shot 2026-05-06 at 10.00.png
建议使用英文、小写、短横线。
14. 添加文章封面图
这是一个常见进阶功能。
需要改三个地方:
- 文章 frontmatter
src/content.config.ts- 页面展示位置
14.1 修改文章 frontmatter
例如:
---
title: "我开始学习 Astro"
description: "记录我学习 Astro 的过程。"
pubDate: 2026-05-06
tags: ["Astro", "学习"]
cover: "/images/covers/astro-learning.jpg"
draft: false
---
14.2 修改 content schema
打开:
src/content.config.ts
找到 blog schema,加入:
cover: z.string().optional(),
大概像这样:
const blog = defineCollection({
loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' }),
schema: z.object({
title: z.string(),
description: z.string(),
pubDate: z.coerce.date(),
updatedDate: z.coerce.date().optional(),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
cover: z.string().optional(),
}),
});
14.3 在文章列表页显示封面
修改:
src/pages/blog/index.astro
在文章卡片里加:
{post.data.cover && (
<img class="post-cover" src={withBase(post.data.cover)} alt={post.data.title} />
)}
14.4 在文章详情页显示封面
修改:
src/pages/blog/[slug].astro
在标题下方或正文上方加入:
{post.data.cover && (
<img class="post-cover-large" src={withBase(post.data.cover)} alt={post.data.title} />
)}
14.5 添加样式
修改:
src/styles/global.css
加入:
.post-cover {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
border-radius: 10px;
margin-bottom: 1rem;
}
.post-cover-large {
width: 100%;
max-height: 420px;
object-fit: cover;
border-radius: 12px;
margin: 2rem 0;
}
15. 添加文章阅读时间
阅读时间可以简单按字数估算。
15.1 新建工具函数
新建:
src/utils/readingTime.ts
写入:
export function getReadingTime(text: string) {
const wordsPerMinute = 300;
const textLength = text.trim().length;
const minutes = Math.max(1, Math.ceil(textLength / wordsPerMinute));
return `${minutes} 分钟阅读`;
}
中文文章可以按字符数粗略估算。
15.2 在文章详情页使用
打开:
src/pages/blog/[slug].astro
需要拿到文章正文原始内容时,具体实现取决于当前 Astro 内容对象是否暴露 body。
如果可以访问 post.body,可以写:
---
import { getReadingTime } from '../../utils/readingTime';
const readingTime = getReadingTime(post.body ?? '');
---
<p>{readingTime}</p>
如果当前对象没有 body,可以先只在列表中不做阅读时间,或者以后使用 rehype / remark 插件实现。
15.3 更简单的方式
先手动写字段:
---
title: "文章标题"
description: "文章摘要"
pubDate: 2026-05-06
tags: ["Blog"]
readingTime: "5 分钟阅读"
draft: false
---
然后在 src/content.config.ts 加:
readingTime: z.string().optional(),
页面中显示:
{post.data.readingTime && <span>{post.data.readingTime}</span>}
这种方式最简单,但需要每篇文章手动写。
16. 添加上一篇 / 下一篇文章
修改:
src/pages/blog/[slug].astro
16.1 思路
在文章详情页中:
- 获取所有非草稿文章
- 按发布时间排序
- 找到当前文章的位置
- 得到上一篇和下一篇
- 在页面底部显示链接
16.2 示例代码思路
在 frontmatter 脚本区域中:
const allPosts = (await getCollection('blog'))
.filter((item) => !item.data.draft)
.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
const currentIndex = allPosts.findIndex((item) => item.id === post.id);
const previousPost = allPosts[currentIndex + 1];
const nextPost = allPosts[currentIndex - 1];
页面底部:
<nav class="post-pagination">
{previousPost && (
<a href={withBase(`/blog/${previousPost.id}/`)}>
← {previousPost.data.title}
</a>
)}
{nextPost && (
<a href={withBase(`/blog/${nextPost.id}/`)}>
{nextPost.data.title} →
</a>
)}
</nav>
样式:
.post-pagination {
display: flex;
justify-content: space-between;
gap: 1rem;
margin-top: 3rem;
padding-top: 1.5rem;
border-top: 1px solid #e5e7eb;
}
17. 添加 RSS
RSS 可以让别人通过阅读器订阅你的博客。
17.1 安装依赖
npm install @astrojs/rss
17.2 新建 RSS 页面
新建:
src/pages/rss.xml.js
写入示例:
import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';
export async function GET(context) {
const posts = (await getCollection('blog'))
.filter((post) => !post.data.draft)
.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
return rss({
title: 'Mingrui Blog',
description: 'Mingrui 的个人博客',
site: context.site,
items: posts.map((post) => ({
title: post.data.title,
description: post.data.description,
pubDate: post.data.pubDate,
link: `/blog/${post.id}/`,
})),
});
}
17.3 在导航或 head 里添加 RSS 链接
在 BaseLayout.astro 的 <head> 中加入:
<link rel="alternate" type="application/rss+xml" title="Mingrui Blog RSS" href={withBase('/rss.xml')} />
也可以在 footer 或 about 页面添加:
<a href={withBase('/rss.xml')}>RSS</a>
18. 添加 sitemap
sitemap 有助于搜索引擎发现页面。
18.1 安装依赖
npm install @astrojs/sitemap
18.2 修改 astro.config.mjs
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://potatotom.top',
integrations: [sitemap()],
});
18.3 检查构建
npm run build
构建后应该会生成 sitemap 相关文件。
19. 增强 SEO
当前项目已经有基础 description 和 Open Graph。后续可以继续增强。
主要修改:
src/layouts/BaseLayout.astro
src/pages/blog/[slug].astro
astro.config.mjs
19.1 添加 canonical URL
在 BaseLayout.astro 中增加 props:
interface Props {
title: string;
description: string;
canonical?: string;
}
然后:
{canonical && <link rel="canonical" href={canonical} />}
页面调用时传入:
<BaseLayout
title="页面标题"
description="页面描述"
canonical={new URL(Astro.url.pathname, Astro.site).toString()}
>
19.2 文章页使用 article 类型
在 BaseLayout.astro 中可以增加:
<meta property="og:type" content={ogType ?? 'website'} />
props:
ogType?: string;
文章详情页传:
<BaseLayout
title={`${post.data.title} - Mingrui Blog`}
description={post.data.description}
ogType="article"
>
19.3 添加文章发布时间 meta
文章详情页可以在 <head> 里提供更多信息。
一种做法是让 BaseLayout 支持额外 slot:
<head>
...
<slot name="head" />
</head>
文章页中:
<Fragment slot="head">
<meta property="article:published_time" content={post.data.pubDate.toISOString()} />
{post.data.updatedDate && (
<meta property="article:modified_time" content={post.data.updatedDate.toISOString()} />
)}
</Fragment>
19.4 添加 Open Graph 图片
如果实现了 cover 字段,可以在 BaseLayout 中支持:
image?: string;
然后:
{image && <meta property="og:image" content={image} />}
文章页传:
image={post.data.cover ? new URL(post.data.cover, Astro.site).toString() : undefined}
20. 添加搜索功能
搜索功能可以先做简单版本。
20.1 简单方案:前端搜索
适合文章数量不多的个人博客。
思路:
- 构建一个 JSON 文件,包含所有文章标题、描述、标签和链接
- 前端页面读取 JSON
- 用输入框过滤
20.2 新建搜索数据接口
新建:
src/pages/search.json.js
示例:
import { getCollection } from 'astro:content';
export async function GET() {
const posts = (await getCollection('blog'))
.filter((post) => !post.data.draft)
.map((post) => ({
title: post.data.title,
description: post.data.description,
tags: post.data.tags,
url: `/blog/${post.id}/`,
}));
return new Response(JSON.stringify(posts), {
headers: {
'Content-Type': 'application/json',
},
});
}
20.3 新建搜索页面
新建:
src/pages/search.astro
可以先做一个简单页面:
---
import BaseLayout from '../layouts/BaseLayout.astro';
import { withBase } from '../utils/basePath';
---
<BaseLayout title="搜索 - Mingrui Blog" description="搜索 Mingrui Blog 的文章">
<h1>搜索</h1>
<input id="search-input" type="search" placeholder="输入关键词搜索文章" />
<ul id="search-results"></ul>
<script>
const input = document.querySelector('#search-input');
const results = document.querySelector('#search-results');
async function loadPosts() {
const response = await fetch('/search.json');
return response.json();
}
const posts = await loadPosts();
input?.addEventListener('input', () => {
const keyword = input.value.toLowerCase().trim();
const matched = posts.filter((post) => {
return (
post.title.toLowerCase().includes(keyword) ||
post.description.toLowerCase().includes(keyword) ||
post.tags.join(' ').toLowerCase().includes(keyword)
);
});
results.innerHTML = matched
.map((post) => `<li><a href="${post.url}">${post.title}</a></li>`)
.join('');
});
</script>
</BaseLayout>
注意:如果未来有 base 子路径,fetch('/search.json') 也需要调整。
20.4 导航栏增加搜索入口
修改:
src/layouts/BaseLayout.astro
加入:
<a href={withBase('/search/')}>搜索</a>
21. 文章变多后添加分页
现在文章少,不需要分页。
如果文章超过 30 篇,可以考虑分页。
21.1 博客列表分页
Astro 支持 paginate。
可以把:
src/pages/blog/index.astro
改成:
src/pages/blog/[page].astro
示例思路:
---
import { getCollection } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro';
import { withBase } from '../../utils/basePath';
export async function getStaticPaths({ paginate }) {
const posts = (await getCollection('blog'))
.filter((post) => !post.data.draft)
.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
return paginate(posts, { pageSize: 10 });
}
const { page } = Astro.props;
---
<BaseLayout title="博客 - Mingrui Blog" description="Mingrui Blog 的全部文章">
<h1>博客</h1>
{page.data.map((post) => (
<article class="post-item">
<h2>
<a href={withBase(`/blog/${post.id}/`)}>{post.data.title}</a>
</h2>
<p>{post.data.description}</p>
</article>
))}
<nav>
{page.url.prev && <a href={page.url.prev}>上一页</a>}
{page.url.next && <a href={page.url.next}>下一页</a>}
</nav>
</BaseLayout>
21.2 注意事项
分页会影响 URL 结构。
例如:
/blog/1/
/blog/2/
你需要考虑是否保留 /blog/ 作为第一页。
初期不建议急着做分页,等文章数量真的变多再做。
22. 修改 favicon
当前 favicon 在:
public/favicon.svg
public/favicon.ico
22.1 替换 favicon.svg
准备一个新的 SVG 文件,命名为:
favicon.svg
覆盖:
public/favicon.svg
22.2 替换 favicon.ico
如果你也有 .ico 文件,覆盖:
public/favicon.ico
22.3 检查 BaseLayout
打开:
src/layouts/BaseLayout.astro
确认里面引用了:
<link rel="icon" href={withBase('/favicon.svg')} />
如果你改成 PNG:
<link rel="icon" type="image/png" href={withBase('/favicon.png')} />
对应放到:
public/favicon.png
23. 修改域名和部署配置
配置文件:
astro.config.mjs
23.1 自定义域名
当前类似:
export default defineConfig({
site: 'https://potatotom.top',
});
如果换域名:
export default defineConfig({
site: 'https://new-domain.com',
});
23.2 如果部署到 GitHub Pages 子路径
例如:
https://username.github.io/Mingrui_Blog/
可能需要:
export default defineConfig({
site: 'https://username.github.io',
base: '/Mingrui_Blog/',
});
这时 withBase() 的价值就会体现出来。
23.3 GitHub Actions 部署
当前 .github/workflows/ 为空。
如果要自动部署,需要添加:
.github/workflows/deploy.yml
具体内容取决于你部署到哪里:
- GitHub Pages
- Cloudflare Pages
- Vercel
- Netlify
- 自己的服务器
不同平台配置不同,不建议在还没确定部署平台前乱写 workflow。
24. 同步 README
当前 README 应该和真实项目状态保持一致。
建议 README 至少包含:
# Mingrui Blog
Mingrui 的个人博客,使用 Astro 构建。
## 技术栈
- Astro
- Markdown / MDX
- TypeScript
- CSS
## 本地开发
```bash
npm install
npm run dev
构建
npm run build
预览构建结果
npm run preview
目录说明
src/content/blog/:博客文章src/pages/:页面路由src/layouts/:布局src/styles/global.css:全局样式public/:静态资源
写文章
在 src/content/blog/ 中新增 Markdown 文件:
---
title: "文章标题"
description: "文章摘要"
pubDate: 2026-05-06
tags: ["Blog"]
draft: false
---
正文内容。
注意:如果当前还没有 GitHub Actions,就不要写“已经配置自动部署”。
---
# 25. 清理模板遗留文件
当前可能有模板遗留资源:
```text
src/assets/astro.svg
src/assets/background.svg
如果项目里没有使用,可以删除。
25.1 删除前先搜索
在 VS Code 中全局搜索:
astro.svg
background.svg
如果没有任何引用,可以删除。
25.2 删除后检查构建
npm run build
如果构建成功,说明没有问题。
26. 日常开发流程
26.1 开始开发
npm install
npm run dev
如果已经安装过依赖,以后只需要:
npm run dev
26.2 修改代码
常见修改:
写文章 → src/content/blog/
改首页 → src/pages/index.astro
改关于页 → src/pages/about.astro
改样式 → src/styles/global.css
改导航 → src/layouts/BaseLayout.astro
26.3 本地检查
浏览器打开本地开发地址,检查:
- 首页是否正常
- 博客列表是否正常
- 文章详情页是否正常
- 标签页是否正常
- 归档页是否正常
- 移动端是否正常
26.4 构建检查
发布前一定运行:
npm run build
如果失败,先修复错误再发布。
26.5 预览生产构建
npm run preview
这比 npm run dev 更接近真实发布效果。
27. 发布前检查清单
发布前建议检查:
内容检查
- 没有草稿文章误设为
draft: false - 没有公司 confidential 信息
- 没有客户数据
- 没有内部代码
- 没有会议记录
- 没有截图泄露隐私
- 没有 token、API key、密码
- 文章标题没有错别字
- 文章日期正确
- 标签合理
页面检查
- 首页正常
- 博客列表正常
- 文章详情页正常
- 归档页正常
- 标签页正常
- 关于页正常
- 导航链接都能点开
- 404 情况可以接受
样式检查
- 桌面端排版正常
- 手机端排版正常
- 图片没有超出页面
- 代码块可以横向滚动
- 链接颜色清晰
- 深浅颜色对比足够
构建检查
-
npm run build成功 -
npm run preview预览正常 -
dist/不手动修改 -
node_modules/不提交 -
.astro/不提交
28. 常见问题排查
28.1 新文章没有出现在博客列表
检查:
- 文件是否放在
src/content/blog/ - 文件后缀是否是
.md或.mdx - frontmatter 是否正确
draft是否为truepubDate格式是否正确
正确示例:
---
title: "文章标题"
description: "文章摘要"
pubDate: 2026-05-06
tags: ["Blog"]
draft: false
---
28.2 页面报错:frontmatter 字段不合法
可能是 src/content.config.ts 的 schema 不允许这个字段。
例如你写了:
cover: "/images/cover.jpg"
但 schema 没有定义 cover。
解决方法是在 src/content.config.ts 里加:
cover: z.string().optional(),
28.3 日期报错
日期推荐写:
pubDate: 2026-05-06
不推荐乱写:
pubDate: May 6
pubDate: today
28.4 图片不显示
检查:
- 图片是否在
public/images/ - 路径是否写对
- 文件名大小写是否一致
- 是否使用了中文空格或特殊字符
- 部署路径是否需要
withBase()
28.5 链接跳转 404
检查:
- 是否少了
/ - 是否需要
withBase() - 文件名和 URL 是否一致
- 标签名是否包含特殊字符
推荐内部链接写:
<a href={withBase('/blog/')}>博客</a>
28.6 build 失败
先看终端报错。
常见原因:
- Markdown frontmatter 格式错
- TypeScript 类型错误
- 引用了不存在的文件
- import 路径写错
- 新增字段没有更新 schema
- 删除文件后还有引用
28.7 样式没变化
检查:
- 是否改的是
src/styles/global.css BaseLayout.astro是否引入了 global.css- 浏览器是否缓存
- class 名是否写对
- CSS 选择器优先级是否不够
29. 建议的后续开发顺序
不建议一开始就做复杂功能。
推荐顺序:
第一阶段:内容可用
- 跑通项目
- 写 2-3 篇真实文章
- 修改关于页
- 修改首页文案
- 替换联系方式
第二阶段:视觉统一
- 修改全站颜色
- 修改字体和排版
- 优化文章卡片
- 优化正文阅读体验
- 替换 favicon
- 添加头像
第三阶段:内容增强
- 添加文章封面图
- 添加上一篇 / 下一篇
- 添加阅读时间
- 添加 RSS
- 添加 sitemap
- 增强 SEO
第四阶段:文章多了再做
- 分页
- 搜索
- 标签描述
- 系列文章
- 评论系统
最后建议
这个项目目前已经具备个人博客的核心功能。后续不要急着重构,建议优先做这几件事:
- 多写真实文章
- 把关于页改成真实个人介绍
- 把 README 和实际项目状态同步
- 稳定后再加 RSS、SEO、搜索和分页
维护个人博客最重要的不是功能复杂,而是结构清楚、能长期写下去。