# 个人技术博客

> 地址：**[blog.sercypress.cn](https://blog.sercypress.cn)**  
> 框架：[Astro](https://astro.build/) v5 + [AstroPaper](https://github.com/satnaing/astro-paper) 主题  
> 部署：自托管 Docker，Caddy 反代  
> 写作：Obsidian + WebDAV 同步

---

## 📋 目录

- [博客简介](#-博客简介)
- [写作流程](#-写作流程)
- [本地开发](#-本地开发)
- [部署架构](#-部署架构)
- [运维命令](#-运维命令)
- [项目结构](#-项目结构)

---

## 📝 博客简介

个人技术博客，主要发布程序开发相关的内容。基于 Astro v5 静态生成，AstroPaper 主题，支持：

- Markdown + MDX 写作
- Shiki 代码高亮（min-light / night-owl 双主题）
- Pagefind 全文搜索
- RSS 订阅
- Sitemap
- 深色/浅色模式
- 标签分类
- 草稿管理

---

## ✍️ 写作流程

### 快速发文章

```
Obsidian 写 .md 文件
    ↓ 点 Remotely Save 同步
WebDAV 上传到服务器
    ↓ inotify 自动检测
pnpm run build（~25s）
    ↓ 刷新博客页面
文章上线
```

### 文章要求

AstroPaper 要求每篇文章带有以下 frontmatter：

```yaml
---
title: "文章标题"
published: 2026-05-15
description: "简短描述"
tags: ["标签1", "标签2"]
category: 分类名
draft: false
---
```

文件放在 Obsidian 同步目录下，格式支持 `.md` 和 `.mdx`。

### WebDAV 配置（Remotely Save 插件）

| 字段 | 值 |
|------|-----|
| 服务器地址 | `https://webdav.sercypress.cn/blog/src/data` |
| 用户名 | `webdav` |
| 密码 | 见服务器 `/data/blog/webdav/htpasswd` |
| 文件夹名 | `blog` |

---

## 💻 本地开发

### 前置要求

- Node.js v22+
- pnpm

### 启动

```bash
git clone <repo-url> my-blog
cd my-blog
pnpm install
pnpm run dev       # → http://localhost:4321
pnpm run build     # 生产构建
```

### 常用命令

| 命令 | 作用 |
|------|------|
| `pnpm run dev` | 本地开发服务 |
| `pnpm run build` | 生产构建到 `dist/` |
| `pnpm run preview` | 预览构建结果 |
| `pnpm run lint` | ESLint 检查 |
| `pnpm run format` | Prettier 格式化 |
| `pnpm run sync` | 生成 Astro 类型 |

---

## 🏗️ 部署架构

### 服务器

- 主机：Debian 12, 4 核 Xeon, 3.8GB RAM
- 项目路径：`/data/blog/`
- 反向代理：Caddy v2（Docker，host 网络）

### 容器栈

```
/data/blog/docker-compose.yml
├── blog-webdav     wsgidav (Python)  端口 8080 → 挂载 /data
└── blog-watcher    inotify + pnpm    挂载 /data/blog → 自动构建
```

### 链路

```
用户 → blog.sercypress.cn
  → Cloudflare Proxy 🟠 (SSL 终止 + CDN)
  → Caddy (443 HTTPS)
  → /data/blog/dist/ (静态文件)
```

### WebDAV 同步链路

```
Obsidian → webdav.sercypress.cn
  → Cloudflare DNS-only ⚪
  → Caddy → blog-webdav:8080
  → /data/blog/src/data/blog/
  → inotify → pnpm build → dist/
```

---

## 🛠️ 运维命令

```bash
# 容器管理
cd /data/blog
docker compose up -d          # 启动所有服务
docker compose down           # 停止所有服务
docker compose restart        # 重启
docker compose logs -f        # 查看全部日志

# 查看构建日志
docker compose logs -f watcher

# 手动构建
docker exec blog-watcher sh -c 'cd /blog && pnpm run build'

# Caddy 管理
cd /data/caddy
docker compose restart
docker exec caddy caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile

# 本篇完整运维详见同级 OPS.md
```

---

## 📁 项目结构

```
/data/blog/
├── docker-compose.yml      # 统一编排（webdav + watcher）
├── OPS.md                  # 完整运维文档
├── README.md               # 本文件
├── watcher/
│   ├── Dockerfile           # 自动构建容器镜像
│   └── entrypoint.sh        # inotify 监听脚本
├── webdav/
│   ├── Dockerfile           # WebDAV 容器镜像
│   └── htpasswd             # 密码文件
├── src/
│   ├── data/blog/           # 文章目录（WebDAV 同步目标）
│   ├── pages/               # 页面路由
│   ├── components/          # 组件
│   ├── layouts/             # 布局
│   ├── styles/              # 样式
│   ├── config.ts            # 站点配置
│   └── content.config.ts    # 内容集合配置
├── dist/                    # 构建产物（Caddy 服务目录）
├── public/                  # 静态资源
├── astro.config.ts
├── package.json
└── pnpm-lock.yaml
```

---

## 📄 许可

基于 AstroPaper 主题（MIT License），由 [Sat Naing](https://satnaing.dev) 开发。
