echoes博客使用说明

快速开始

环境要求

  • Node.js 18+
  • pnpm

三步启动

代码块BASH · 3 行收起展开
git clone https://github.com/lsy2246/newechoes.git
cd echoes && pnpm i
pnpm run dev  # 访问 http://localhost:4321

快捷部署

Vercel

Deploy with Vercel

  • 构建命令:pnpm run build:vercel
  • 输出目录:dist
  • 后端目录:api/

Cloudflare Pages

  1. 打开 Cloudflare Dashboard,进入 Workers & Pages
  2. 选择 Create application -> Pages -> Import an existing Git repository
  3. 连接 GitHub,并选择 lsy2246/newechoes
  4. 构建命令填写:pnpm run build:cloudflare
  5. 构建输出目录填写:dist

如果你用本地 CLI 直传,命令是:

代码块BASH · 1 行收起展开
pnpm run deploy:cloudflare

EdgeOne Pages

EdgeOne 目前更适合直接通过控制台导入 Git 仓库快速部署。

  1. 打开 EdgeOne Pages,选择“导入 Git 仓库”
  2. 连接 GitHub,并选择 lsy2246/newechoes
  3. 构建命令填写:pnpm run build:edgeone
  4. 根目录填写:/

部署完成后,静态页面会从 dist/ 发布,后端函数会从 cloud-functions/api/ 自动识别。

参考文档:

部署说明

部署架构

当前项目统一采用这套结构:

  • 前端:Astro 输出纯静态文件到 dist/
  • 共享后端逻辑:src/server/api/
  • Vercel 函数入口:api/(构建生成)
  • Cloudflare Pages 函数入口:functions/api/(构建生成)
  • EdgeOne Cloud Functions 入口:cloud-functions/api/(构建生成)

也就是说,三个平台现在都是同一套思路:

  • 页面本身只输出静态文件
  • 搜索索引、文章页、列表页都来自静态产物
  • 豆瓣、微信读书、Git 项目、相册这些动态数据,通过各平台自己的函数目录接到同一份共享处理器上

这不是“某个平台单独走 SSR”,而是“统一静态前端 + 平台函数后端”。

Vercel

  • 构建命令:pnpm run build:vercel
  • 输出目录:dist
  • 函数目录:api/
  • 配置文件:vercel.json

api/ 由构建前的包装生成脚本输出,源码只保留在 src/server/api/

Cloudflare Pages

  • 构建命令:pnpm run build:cloudflare
  • 输出目录:dist
  • 函数目录:functions/api/
  • CLI 部署命令:pnpm run deploy:cloudflare

Cloudflare Pages 可以同时托管静态站点和 Pages Functions。
如果项目里有 functions/,函数文件必须放在仓库根目录,不能放进 dist/ 里。当前仓库会在构建或部署前自动生成这个目录。

EdgeOne Pages

  • 构建命令:pnpm run build:edgeone
  • 输出目录:dist
  • 函数目录:cloud-functions/api/
  • 配置文件:edgeone.json

EdgeOne Pages 也是静态前端和平台函数并存的模式。
它读取 dist/ 里的静态站点,同时读取仓库根目录下构建生成的 cloud-functions/edgeone.json

路由备注

文章页现在统一输出为 articles/*.html,不是旧的目录式 articles/*/index.html
如果后面再改平台路由或重写规则,这个点要保持一致。

核心功能

文章系统

创建文章(推荐方式):

代码块BASH · 1 行收起展开
pnpm new-post

运行后会进入交互模式:

  • 动态扫描 src/content 下现有目录
  • 先选择目标目录,默认使用当前目录
  • 再输入文章标题

也支持直接指定目录:

代码块BASH · 1 行收起展开
pnpm new-post "server/文章标题"

create_post.sh 已废弃,请使用 pnpm new-post。 也支持直接创建到根目录,例如 pnpm new-post "文章标题",但建议优先放到下面的场景目录里。

内容目录结构:

代码块TEXT · 8 行收起展开
src/content/
  ai/
  creator/
  dev/
  life/
  misc/
  server/
  system/

手动创建: 在合适的内容目录下创建 .md 文件

代码块MARKDOWN · 7 行收起展开
---
title: "文章标题"
date: 2026-05-29
tags: ["标签1", "标签2"]
---

文章内容...

title 是文章身份,也是文章 URL 的唯一来源。标题不能重复;移动文件、修改文件名或调整目录时,只要 title 不变,文章 URL 和历史归属就不会变化。

旧的文件路径详情页不会生成;文章正文里残留的旧链接只会被解析到新的标题地址,避免同时存在两套访问规则。

Markdown 写作能力

文章可以使用 .md.mdx 文件。普通文章建议先用 .md,需要在正文里直接引入 Astro/React 组件时再改用 MDX(.mdx)。

Frontmatter

每篇文章顶部需要写 frontmatter:

代码块MARKDOWN · 6 行收起展开
---
title: "文章标题"
date: 2026-05-29
tags: ["标签1", "标签2"]
summary: "可选摘要,会被搜索、RSS、列表页等功能使用"
---
  • title 必填,并且不能重复。
  • date 必填,用来表示发布时间。
  • tags 可选,用于筛选、索引和文章页展示。
  • summary 可选,适合放一句文章摘要。

Mermaid 图表

文章内置 Mermaid 图表支持。直接写 mermaid 代码块即可:

代码块MARKDOWN · 7 行收起展开
```mermaid
graph TD;
    A[开始] --> B[处理];
    B --> C{判断};
    C -->|通过| D[发布];
    C -->|退回| A;
```

构建时会把 Mermaid 代码块识别成图表容器,文章页只在检测到 Mermaid 时加载渲染脚本,页面切换后也会重新渲染。

代码块

普通代码块会使用 Shiki 高亮,并被增强成可折叠代码块,顶部会显示语言、行数和复制按钮:

代码块MARKDOWN · 5 行收起展开
```typescript
export function hello(name: string) {
  return `Hello, ${name}`;
}
```

没有语言时会按纯文本处理:

代码块MARKDOWN · 3 行收起展开
```text
这是一段纯文本示例
```

GFM 表格和任务列表

项目开启了 GFM,可以直接写表格、任务列表等常见 GitHub Markdown 语法。表格会自动包一层滚动容器,移动端不容易撑破页面。

代码块MARKDOWN · 8 行收起展开
| 功能 | 写法 |
| --- | --- |
| Mermaid 图表 | ` ```mermaid ` |
| 代码高亮 | ` ```typescript ` |
| 表格 | `| 标题 | 内容 |` |

- [x] 已完成
- [ ] 待处理

链接和引用

外链会自动添加 target="_blank"noopenernoreferrer 等属性。站内文章链接建议使用文章 URL,例如:

代码块MARKDOWN · 2 行收起展开
[查看文章列表](/articles)
[查看某篇文章](/articles/echoes博客使用说明)

如果文章标题保持不变,即使移动文件位置,系统也会尽量保持文章身份和历史记录稳定。

Git 修订历史

文章的发布时间来自 frontmatter 的 date。文章的最后更新时间和修订记录来自 Git 历史,不需要手写 updatedDate

  • 文件移动或改名时会优先通过 git log --follow 追踪
  • title 用来保证文章身份稳定,作为 Git rename 推断失败时的长期锚点
  • 文章页会展示 commit-like 的修订记录
  • 时间轴保留发布时间轴,并提供修订时间轴查看文章维护历史
代码块TYPESCRIPT · 3 行收起展开
export const SOURCE_REPOSITORY_CONFIG = {
  url: "",
};

不配置时,页面仍会读取本地 Git 历史,但不会生成提交或历史快照外链。GitHub、Gitee、GitLab、Bitbucket 等常见平台会根据 url 识别;自建 Gitea、Forgejo 或私有 GitLab 域名无法识别时,可以额外填写 provider: "gitea"provider: "forgejo"provider: "gitlab"

RSS 订阅

自动为所有文章生成 /rss.xml 订阅源,无需额外配置。

页面过渡与性能

  • View Transitions APISwup 实现流畅的无刷新切换
  • WebAssembly 优化前端数据处理性能
  • SEO 优化:自动生成元标签和站点地图
  • 响应式设计:自适应桌面和移动端

基础配置

编辑 src/consts.ts 配置网站必选信息:

代码块TYPESCRIPT · 19 行收起展开
export const SITE_META = {
  url: "https://your-domain.com",
  title: "你的网站名称",
  author: "作者名",
} as const;

// 导航结构
export const NAV_STRUCTURE = [
  { id: "home", text: "首页", href: "/" },
  {
    id: "articles",
    text: "文章",
    items: [
      { id: "filter", text: "筛选", href: "/filtered" },
      { id: "path", text: "网格", href: "/articles" },
    ],
  },
  { id: "albums", text: "相册", href: "/albums" },
];

可选功能模块

文章过期提醒

默认不启用。需要时从 src/consts.example.ts 复制这段可选配置到 src/consts.ts

代码块TYPESCRIPT · 5 行收起展开
export const ARTICLE_EXPIRY_CONFIG = {
  enabled: true,
  expiryDays: 365,
  warningMessage: "文章内容可能已过时",
};

项目展示

使用 @/components/GitProjects 展示 Git 平台项目:

代码块ASTRO · 6 行收起展开
<GitProjects
  platform={GitPlatform.GITHUB}
  username="your-username"
  title="我的项目"
  client:load
/>

豆瓣数据集成

使用 @/components/DoubanList 展示观影和读书记录:

代码块ASTRO · 4 行收起展开
// 观影记录
<DoubanList type="movie" title="看过的电影" doubanId="your-id" />
// 读书记录
<DoubanList type="book" title="读过的书" doubanId="your-id" />

相册瀑布流

相册页使用 Google Photos 分享链接作为数据源,并通过 @/components/PhotoAlbumMasonry 实现类似豆瓣页面的无限瀑布流加载。

页面示例:

代码块ASTRO · 9 行收起展开
---
import PhotoAlbumMasonry from "@/components/PhotoAlbumMasonry";
---

<PhotoAlbumMasonry
  shareId="your-share-id"
  title="我的相册"
  client:load
/>

从分享链接获取 ID:https://photos.app.goo.gl/your-share-id

相册数据来自 Google Photos 分享页内部接口,并非官方稳定 API。如果 Google 调整页面结构,可能需要同步适配。

微信读书书单

使用 @/components/WereadBookList 展示书单:

代码块ASTRO · 1 行收起展开
<WereadBookList listId="12345678" client:load />

从分享链接获取 ID:https://weread.qq.com/misc/booklist/12345678

旅行足迹

使用 @/components/WorldHeatmap 展示全球足迹:

代码块ASTRO · 4 行收起展开
<WorldHeatmap
  client:only="react"
  visitedPlaces={["中国-北京", "美国", "日本"]}
/>

故障排除

问题解决方案
图片显示问题确保图片放在 public 目录
豆瓣数据无法加载检查用户 ID,确认记录公开
相册无法加载检查 Google Photos 分享链接是否公开
Git 项目无法显示验证用户名和 API 访问权限
旅行足迹地球加载失败检查浏览器 WebAssembly 支持、CSP 设置与地图资源请求