UFO部署教程:Cloudflare Pages + KV 搭建宇宙奥秘科普站,带管理后台和主题切换

前言

UFO-zh-kg 是一个基于 Cloudflare Pages + KV 存储 构建的宇宙奥秘科普内容站,前端采用纯 HTML/CSS/JS(零依赖),后端通过 Cloudflare Pages Functions 提供边缘 API,文章数据存储在 Cloudflare KV 中。整个项目开箱即用,支持在线文章管理后台、暗色/亮色主题切换、分类和标签筛选等功能。


功能特点

功能 说明
🛸 纯前端零依赖 HTML/CSS/JS 原生开发,无需构建步骤,部署即运行
🌐 边缘 API Cloudflare Pages Functions 提供全球边缘节点 API
💾 KV 存储 Cloudflare KV 存储文章数据和网站配置
📚 分类浏览 支持按分类和标签筛选文章
🌙 主题切换 暗色/亮色双主题,偏好自动保存到 localStorage
🔐 管理后台 带密码鉴权的管理界面,支持文章 CRUD
🔑 Session 鉴权 Token 鉴权机制,24 小时有效期
📦 种子数据 一键初始化预置文章数据到 KV
GitHub Actions 推送 main 分支自动部署到 Cloudflare Pages
📱 响应式设计 适配桌面端和移动端
🎨 SEO 友好 Open Graph 元数据,社交分享友好

技术栈

类别 技术
前端 纯 HTML / CSS / JavaScript(零依赖)
后端 Cloudflare Pages Functions(边缘计算)
数据存储 Cloudflare KV(键值存储)
部署 GitHub Actions → Cloudflare Pages(自动部署)
开发工具 Wrangler CLI(本地开发调试)

项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
ufo-zh-kg/
├── public/ # 静态文件
│ ├── index.html # 首页(文章列表)
│ ├── article.html # 文章详情页
│ ├── admin.html # 管理后台
│ ├── favicon.ico # 图标
│ ├── favicon.png
│ ├── favicon-32x32.png
│ └── favicon.svg
├── functions/ # Cloudflare Pages Functions
│ ├── _data/
│ │ └── articles.js # 文章种子数据
│ └── api/
│ ├── articles.js # GET /api/articles(文章列表)
│ ├── articles/[id].js # GET /api/articles/:id(文章详情)
│ ├── seed.js # POST /api/seed(初始化数据)
│ ├── settings.js # GET /api/settings(公开配置)
│ └── admin/
│ ├── login.js # POST /api/admin/login(登录)
│ ├── check.js # GET /api/admin/check(登录状态)
│ ├── list.js # GET /api/admin/list(管理文章列表)
│ ├── article.js # POST/PUT/DELETE /api/admin/article(CRUD)
│ ├── settings.js # GET/POST /api/admin/settings(网站配置)
│ └── change-password.js # POST /api/admin/change-password(改密码)
├── wrangler.toml # Cloudflare 配置
├── package.json
└── .github/
└── workflows/
└── deploy.yml # GitHub Actions 自动部署

部署步骤

1. 准备工作

开始之前,需要准备以下内容:

  1. Cloudflare 账号 — 注册 Cloudflare 并绑定一个域名
  2. GitHub 账号 — 用于 Fork 仓库
  3. API Token — 需要具有 Pages 部署权限的 API Token

2. 创建 KV 命名空间

  1. 登录 Cloudflare Dashboard
  2. 进入 Workers 和 PagesKV创建命名空间
  3. 输入名称,例如 UFO_ARTICLES,点击创建
  4. 创建后右侧会显示一串字符,这就是 KV namespace ID,请保存下来备用

示例 KV ID:28733a27837f4aef9be0b8d6f7b58cac

3. Fork 项目仓库

访问 UFO-zh-kg 项目,先给项目点个 ⭐,然后点击右上角 Fork,将仓库克隆到你的 GitHub 账号下。

4. 配置 wrangler.toml

打开 wrangler.toml,将 KV ID 填入:

1
2
3
4
5
6
7
name = "ufo-zh-kg"
compatibility_date = "2024-01-01"
pages_build_output_dir = "./public"

[[kv_namespaces]]
binding = "ARTICLES"
id = "你的KV_NAMESPACE_ID" # 替换为你的 KV ID

5. 配置 GitHub Secrets

在 Fork 的仓库中,按以下步骤设置:

  1. 进入仓库 SettingsSecrets and variablesActions
  2. 点击 New repository secret,添加以下 secrets:
Secret 名称 说明 必填
CLOUDFLARE_ACCOUNT_ID Cloudflare 账户 ID(不是邮箱)
CLOUDFLARE_API_TOKEN API Token(需 Pages 部署权限)

⚠️ API Token 需要具有 Pages 部署 的权限,否则部署会失败。

如何获取 Cloudflare 账户 ID:
登录 Cloudflare Dashboard,在右上角头像下拉菜单中可以看到账户 ID,或者从 URL 中提取:https://dash.cloudflare.com/ACCOUNT_ID/...

6. 推送部署

在 Fork 的仓库中,将修改推送到 main 分支:

1
2
3
git add .
git commit -m "init: 配置KV和部署"
git push origin main

推送后,GitHub Actions 会自动触发部署流程,将 public/ 目录部署到 Cloudflare Pages。部署完成后会生成一个 Pages 项目链接(如 ufo-zh-kg.pages.dev)。

[!TIP]
你也可以绑定自定义域名:在 Cloudflare Pages 项目设置中添加自定义域(如 ufo.你的域名),然后在 Cloudflare DNS 中添加相应的 CNAME 记录。

7. 初始化数据(Seed)

部署完成后,需要调用 seed 接口将文章数据写入 KV 存储:

1
curl -X POST https://ufo.zh.kg/api/seed?key=ufo-zh-kg-seed-2024

首次执行后,种子数据会被写入 KV。如果需要强制重新写入(覆盖已有数据),添加 force=1 参数:

1
curl -X POST https://ufo.zh.kg/api/seed?key=ufo-zh-kg-seed-2024&force=1

[!NOTE]
seed 密钥 ufo-zh-kg-seed-2024 硬编码在 functions/api/seed.js 中,出于安全考虑,建议在生产环境中修改为自己的密钥。


API 接口

方法 路径 说明 鉴权
GET /api/articles 获取文章列表(支持 ?category=xxx?tag=xxx 筛选) 公开
GET /api/articles/:id 获取单篇文章详情 公开
POST /api/seed 初始化 KV 数据(需密钥) 密钥验证
GET /api/settings 获取网站公开配置 公开
POST /api/admin/login 管理员登录 密码验证
GET /api/admin/check 检查登录状态 Token 鉴权
GET /api/admin/list 获取管理文章列表 Token 鉴权
POST /api/admin/article 新建文章 Token 鉴权
PUT /api/admin/article?id=xxx 更新文章 Token 鉴权
DELETE /api/admin/article?id=xxx 删除文章 Token 鉴权
GET /api/admin/settings 读取网站配置 Token 鉴权
POST /api/admin/settings 保存网站配置 Token 鉴权
POST /api/admin/change-password 修改管理密码 Token 鉴权

文章列表接口

GET /api/articles 支持通过查询参数筛选:

1
2
3
GET /api/articles                 # 获取全部文章
GET /api/articles?category=经典案例 # 按分类筛选
GET /api/articles?tag=UFO # 按标签筛选

返回结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"articles": [
{
"id": "roswell-incident",
"title": "罗斯威尔事件:最著名的UFO坠毁案",
"category": "经典案例",
"tags": ["经典案例", "UFO", "政府档案"],
"summary": "1947年,美国新墨西哥州罗斯威尔发生了一起震惊世界的事件……",
"image": "https://images.unsplash.com/photo-xxx?w=800&h=600&fit=crop",
"date": "1947-07-08"
}
],
"total": 1
}

文章详情接口

1
GET /api/articles/roswell-incident

返回完整的文章内容(含 content 字段,HTML 格式)。


管理后台

管理后台页面在 https://ufo.zh.kg/admin.html,首次部署后默认密码为:

1
ufo-admin-2024

⚠️ 强烈建议:部署成功后,第一时间在管理后台修改默认密码!

管理后台功能

功能 说明
文章列表 查看所有文章,支持搜索
新建文章 填写标题、分类、标签、摘要、图片、内容等
编辑文章 修改已有文章内容
删除文章 删除不再需要的文章
网站配置 修改站名、副标题、导航、分类、主题、背景图等
修改密码 修改管理后台登录密码

网站配置项

配置项 说明
title 网站标题
subtitle 网站副标题
subtitleUrl 副标题链接
categories 文章分类列表
nav 导航栏配置(支持按分类筛选)
theme 默认主题(dark / light
bgImage 暗色主题背景图
bgImageLight 亮色主题背景图

前端页面

首页(index.html)

  • 顶部导航栏:Logo + 导航菜单 + 主题切换
  • 文章列表卡片:缩略图 + 标题 + 摘要 + 标签
  • 分类/标签筛选:点击导航或筛选按钮过滤文章
  • 暗色/亮色主题:点击月亮/太阳图标切换,偏好保存到 localStorage

文章详情页(article.html)

  • 大图展示:文章封面图
  • 文章内容:HTML 格式渲染
  • 分类/标签:文章分类和标签展示
  • 暗色/亮色主题:与首页保持一致

本地开发

如果你想在本地调试和开发,可以使用 Wrangler CLI:

1
2
3
4
5
6
7
8
9
10
11
# 安装 Wrangler
npm install -g wrangler

# 登录 Cloudflare
wrangler login

# 本地开发(会自动模拟 KV)
wrangler pages dev public --kv=ARTICLES

# 部署
wrangler pages deploy public

本地开发时,KV 数据会在本地模拟,无需真实 KV 环境即可调试。


常见问题

部署后文章列表为空?

这是正常现象,KV 是空的。需要调用 seed 接口初始化数据:

1
curl -X POST https://你的域名/api/seed?key=ufo-zh-kg-seed-2024

首页显示「加载中」但不消失?

检查 Cloudflare Pages 项目的 KV 绑定 是否正确:

  1. 进入 Cloudflare Pages 项目
  2. 点击 设置变量和机密
  3. 确认 KV 绑定名称为 ARTICLES,且 KV ID 正确

管理后台登录失败?

确认密码是否正确。默认密码为 ufo-admin-2024。如果之前修改过密码但忘记了,需要在 Cloudflare KV 中删除 admin_password 键即可恢复默认密码:

1
2
3
# 通过 Wrangler CLI
wrangler kv:namespace list # 找到 namespace ID
wrangler kv:key delete admin_password --namespace-id=YOUR_KV_ID

如何修改 seed 密钥?

编辑 functions/api/seed.js 中的 SEED_SECRET 常量:

1
const SEED_SECRET = "ufo-zh-kg-seed-2024";  // 改成你自己的密钥

如何添加新的预置文章?

编辑 functions/_data/articles.js,按照现有格式添加新文章对象,然后重新运行 seed 接口(带 ?force=1)。

图片 404 或加载失败?

文章中的图片使用 Unsplash 和 Picsum 的图床服务,访问可能需要稳定的网络环境。你也可以替换为自己的图床 URL。


参考

推荐链接