在这个数据为王的时代,拥有一个属于自己的不受平台限制的个人数据中心,是一件非常有成就感的事情。今天,我们将从零开始,亲手打造一个强大快速且几乎零成本的个人书签管理器。

这个项目不仅是一个简单的网页,它是一个完整的生态系统:一个由 Hugo 构建的闪电般快速的前端网站,一个由 Cloudflare Functions 和 D1 数据库驱动的强大后端,以及一个能实现浏览器书签自动同步的 Chrome 扩展。

第一部分:构建云端书签网站

我们的目标是创建一个功能齐全的网站,可以让我们对书签进行增删改查分类导入/导出等所有操作。

第一步:项目规划与技术选型

我们选择一套现代高效且免费的“黄金组合”:

  • 前端框架 (Hugo):一个用 Go 语言编写的静态网站生成器,以其惊人的构建速度而闻名。它将为我们生成一个轻量快速的网站骨架。
  • 部署与后端平台 (Cloudflare Pages):一个集静态托管Serverless 函数(Functions)和数据库(D1)于一体的强大平台。它的免费额度足以支撑绝大多数个人项目。
  • 数据库 (Cloudflare D1):Cloudflare 的无服务器 SQL 数据库,与 Pages Functions 无缝集成,简单易用。
  • UI 样式 (Pico.css):一个极简的 CSS 框架,只需引入一个文件,就能让我们的应用看起来专业美观。

第二步:环境准备与项目初始化

  1. 安装 Hugo: 确保你的电脑上已经安装了 Hugo。

  2. 创建项目:

    hugo new site my-bookmark-app
    cd my-bookmark-app
    
  3. 建立项目结构: 在项目根目录,我们创建 functionsd1 文件夹,并规划出如下结构,确保 static 文件夹和 hugo.toml 配置文件都已就位。

    my-bookmark-app/
    │  hugo.toml        # Hugo 配置文件
    │  wrangler.toml      # Cloudflare 配置文件
    │
    ├─content/
    │      _index.md
    ├─d1/
    │  └─migrations/
    │          0001_create_bookmarks.sql # 数据库结构
    ├─functions/
    │  └─api/
    │      └─[[catchall]].js    # 后端 API
    ├─layouts/
    │      index.html           # 网站主模板
    └─static/
       ├─css/
       │      style.css
       └─js/
              app.js
    

第三步:数据库设计 (d1/migrations)

我们定义书签表 bookmarks 的结构。这个 SQL 文件不仅定义了表,还插入了一些初始数据方便测试。

-- 0001_create_bookmarks.sql
CREATE TABLE bookmarks (
    id INTEGER PRIMARY KEY AUTOINCREMENT
    name TEXT NOT NULL
    url TEXT NOT NULL
    category TEXT DEFAULT '未分类'
    tags TEXT
    created_at TEXT DEFAULT CURRENT_TIMESTAMP
)
-- 插入一些示例数据
INSERT INTO bookmarks (name url category tags) VALUES
('Cloudflare D1 官方文档' 'https://developers.cloudflare.com/d1/' '技术文档' 'CloudflareD1')
('Hugo 官方文档' 'https://gohugo.io/documentation/' '技术文档' 'HugoStatic')

第四步:后端 API 开发 (functions/api)

这是应用的大脑。[[catchall]].js 文件会处理所有 /api/* 的请求,像一个迷你的 API 服务器。它负责连接 D1 数据库,并提供以下核心接口:

  • GET /api/bookmarks:获取所有书签,支持搜索和分类。
  • POST /api/bookmarks:添加一个新书签。
  • PUT /api/bookmarks/:id:修改一个已存在的书签(比如修改分类)。
  • DELETE /api/bookmarks/:id:删除一个书签。
  • GET /api/categories:获取所有分类及其数量。
  • DELETE /api/categories/:name:删除一个分类及其下的所有书签。
  • POST /api/bookmarks/import:批量导入书签。
  • POST /api/bookmarks/exists:检查一组 URL 是否已存在。

第五步:前端界面构建 (layoutsstatic)

  • layouts/index.html: 这是网站的 HTML 骨架,包含了添加表单书签列表数据管理等所有 UI 元素的布局。
  • static/css/style.css: 我们在这里编写自定义样式,利用 CSS Grid 实现多列响应式布局,并美化各种元素。
  • static/js/app.js: 这是前端的交互核心。它负责:
    • 页面加载时,调用 API 获取并渲染书签和分类列表。
    • 处理表单提交删除修改分类等用户操作。
    • 实现导入/导出逻辑,包括解析 HTML 文件和生成浏览器兼容的 HTML 文件。
    • (可选)处理思维导图的生成与交互。

第六步:本地开发与部署

本地开发工作流 (我们最终确定的最佳实践):

  1. 修改代码: 编辑 layouts staticfunctions 里的文件。
  2. 构建前端: 每当修改了前端文件后,运行 hugo --minify 来生成一个干净的不含开发脚本的 public 文件夹。
  3. 启动本地服务: 运行 wrangler pages dev public。这个命令会直接托管 public 文件夹作为静态内容,并同时启动 functions 里的 API。在浏览器中访问 http://localhost:8788 即可测试。

部署到 Cloudflare Pages:

  1. 将您的整个项目推送到一个 GitHub 仓库。
  2. 在 Cloudflare 仪表盘中,新建一个 Pages 项目,连接到您的 GitHub 仓库。
  3. 在“构建设置”中,选择框架预设为 Hugo。Cloudflare 会自动填好构建命令 (hugo) 和输出目录 (public)。
  4. 关键一步:部署完成后,进入项目的 设置 -> 函数 -> D1 数据库绑定,添加一个绑定:变量名为 DB,值为您创建的 D1 数据库。
  5. 最后一步:对您的数据库运行一次远程迁移,在线上创建数据表:wrangler d1 migrations apply <你的数据库名> --remote

至此,您的云端书签网站就完全上线了!

第二部分:开发 Chrome 扩展实现自动同步

为了让书签管理无缝融入日常浏览,我们将创建一个 Chrome 扩展,实现“随手收藏,自动同步”。

第一步:扩展的工作原理

扩展的核心是一个在后台运行的 Service Worker (background.js)。它会使用 Chrome 提供的 chrome.bookmarks.onCreated API 来监听书签创建事件。一旦有新书签被创建,它就会获取书签的标题和 URL,然后通过 fetch API 将这些信息发送到我们网站的 /api/bookmarks 端点。

第二步:创建扩展文件 (manifest.json)

这是扩展的配置文件,声明了它的名称权限和后台脚本。

{
  "manifest_version": 3
  "name": "我的书签自动同步"
  "version": "1.0"
  "permissions": [ "bookmarks" ]
  "host_permissions": [ "https://你的域名.pages.dev/" ]
  "background": { "service_worker": "background.js" }
}
  • "permissions": ["bookmarks"]: 请求访问书签的权限。
  • "host_permissions": 请求向你的网站发送网络请求的权限。

第三步:编写后台脚本 (background.js)

这个脚本是扩展的全部逻辑所在。

const API_ENDPOINT = 'https://你的域名.pages.dev/api/bookmarks'

// 监听书签创建事件
chrome.bookmarks.onCreated.addListener((id bookmark) => {
  if (!bookmark.url) return // 忽略文件夹

  const data = {
    name: bookmark.title || '无标题'
    url: bookmark.url
    category: '来自浏览器'
    tags: 'auto-sync'
  }

  // 发送数据到 API
  fetch(API_ENDPOINT {
    method: 'POST'
    headers: { 'Content-Type': 'application/json' }
    body: JSON.stringify(data)
  })
  .then(response => console.log('书签同步成功:' response.status))
  .catch(error => console.error('书签同步失败:' error))
})
  • 注意API_ENDPOINT 必须是您自己的正确的线上域名。

第四步:加载与测试扩展

  1. 在 Chrome 地址栏输入 chrome://extensions
  2. 打开右上角的“开发者模式”。
  3. 点击“加载已解压的扩展程序”,选择包含 manifest.jsonbackground.js 的文件夹。
  4. 加载成功后,随便收藏一个网页,然后回到您的书签网站刷新查看,新书签应该已经同步过来了!

好的,完全没问题!您提供的这个场景——只保护 /logs 路径,而让网站主体 (/) 保持公开——是一个非常常见且实用的需求。

我将为您撰写一篇极其详细的从零开始的严格按照最新 Cloudflare 界面和您的精确需求的终极指南。这篇文章将是您未来随时可以参考的绝对正确的操作手册。


使用 Cloudflare Access 为你的网站特定页面添加安全登录

 

第一步:注册并进入 Cloudflare Zero Trust

这是我们所有安全配置的起点。

  1. 访问 Zero Trust 仪表盘
  2. 首次登录/注册
    • 如果您已经登录了主 Cloudflare 账户,它可能会自动带您进入。
    • 如果是第一次,它会引导您完成一个简单的注册流程。您需要输入您的邮箱,然后去邮箱里点击验证链接。
  3. 设置团队名称 (Set up your team)
    • 首次进入时,Cloudflare 会要求您创建一个“团队名称”。这只是一个内部标识,您可以输入任何您喜欢的独一无二的名字(比如 yyszone-team),然后点击 “Next”。
    • 在接下来的计划选择页面,选择 Free plan (免费计划),它包含了我们所需的所有功能。

现在,您已经成功进入了 Zero Trust 的主控制台。

第二步:创建服务令牌 (获取您的专属“账号密码”)

服务令牌是专门为程序化访问设计的“固定账号密码”,它由一个 Client ID (用户名) 和一个 Client Secret (密码) 组成。

  1. 导航到服务认证

    • 在 Zero Trust 仪表盘的左侧菜单中,找到 Access,然后点击它的子菜单 服务认证 (Service Auth)
    • URL: https://one.dash.cloudflare.com/<你的账户ID>/access/service-tokens
  2. 创建服务令牌

    • 点击蓝色的 创建服务令牌 (Create Service Token) 按钮。
    • 令牌名称 (Token Name): 输入一个有意义的名字,比如 Logs-Admin-Token
    • 服务令牌持续时间 (Service Token Duration): 选择 无期限 (No Expiration) 或您希望的时长。
    • 点击 生成令牌 (Generate Token)
  3. 立即复制并安全保存!

    • 一个弹窗会出现,显示您的 客户端 ID (Client ID)客户端密钥 (Client Secret)
    • 警告:客户端密钥 (Client Secret) 只会在这里显示一次! 请务必立即将它复制到一个安全的地方(比如您的密码管理器)。一旦关闭这个窗口,您将永远无法再次查看它。

第三步:创建 Access 应用程序 (定义保护目标)

现在,我们要告诉 Cloudflare,我们具体要保护哪个网站的哪个页面。

  1. 进入应用程序列表

    • 在左侧菜单中,点击 Access -> 应用程序 (Applications)
  2. 添加应用程序

    • 点击蓝色的 添加应用程序 (Add an application) 按钮。
    • 选择第一个选项,自托管 (Self-hosted)
  3. 配置应用程序 (这是最关键的一步)

    • 应用程序名称 (Application name): 书签管理器 - 日志页面
    • 会话时长 (Session Duration): 选择 24 hours 或更长。
    • 公共主机名 (Public Hostname):
      • 子域 (Subdomain): bm
      • 域 (Domain): yysresume.work
      • 路径 (Path): /logs
        • 重要:在这里,我们精确地指定了只保护 /logs 这个路径。这意味着,当用户访问 https://bm.yysresume.work/ (首页) 时,不会触发登录只有当他们访问 https://bm.yysresume.work/logs 时,门卫才会出来检查。
    • 跳过高级设置:下方的所有其他设置都保持默认。
    • 点击页面最下方的 下一步 (Next) 按钮。

第四步:创建唯一的 Allow 策略

这是我们将“门规”和“钥匙”关联起来的地方。

  1. 基本信息

    • 策略名称 (Policy name): 仅限管理员密码访问
    • 操作 (Action): Allow
  2. 配置唯一的规则

    • 在 "包括 (Include)" 部分,创建一条规则:
      • 选择器 (Selector): 选择 服务令牌 (Service Token)
      • 值 (Value): 从下拉菜单中,选择我们刚刚创建的 Logs-Admin-Token
    • 确保这是唯一的 Allow 规则! 不要添加任何其他基于邮箱或IP的规则。
  3. 保存策略

    • 滚动到页面底部,点击蓝色的 添加策略 (Add policy) 按钮。
    • 在接下来的 "Setup" 页面,保持默认设置,点击 添加应用程序 (Add application)

第五步:最终测试

现在,您的安全配置已经全部完成。

  1. 测试公开页面

    • 打开一个新的无痕浏览器窗口
    • 访问您的网站首页https://bm.yysresume.work
    • 结果:您应该能直接看到您的书签管理器,无需任何登录
  2. 测试受保护页面

    • 在同一个无痕窗口中,现在访问您的日志页面https://bm.yysresume.work/logs
    • 结果:这一次,您会被 Cloudflare Access 拦截,并看到一个专门用于输入服务令牌的登录页面。
    • 截图描述:页面标题为 "Access to bm.yysresume.work",下面有两个输入框:"CF-Access-Client-Id" 和 "CF-Access-Client-Secret"。
  3. 使用您的“账号密码”登录(好像没用)

    • 在登录页面中,输入您在第二步保存的 Client IDClient Secret
    • 点击 Sign in
    • 成功! 您现在应该能看到您的日志页面了。
  4. 登录方法:你的应用->登录方法->管理登录方法->登录方式(新增)
  • ​​​​可以加入github登录,去策略添加->(选择器Login Methods, 值 github(登录方式要打勾才行)) 
  • 登录界面

 

结语

通过这个项目,不仅亲手打造了一个完全属于自己的功能强大的云端书签管理器,还掌握了从前端构建后端 API 开发数据库设计到浏览器扩展集成的全栈技能。

这段旅程充满了挑战,但每一次调试每一次修复,都让我们对技术的理解更深一层。现在,享受你的成果吧!这个项目将成为你数字世界里一个得心应手的强大工具。