likebocai-nuxt4
  • TypeScript 77.5%
  • Vue 16.2%
  • JavaScript 4.9%
  • CSS 1.4%
Find a file
likebocai e9ed805c08
Some checks failed
CI/CD / ci (push) Has been cancelled
chore: init likebocai-nuxt project
2026-07-09 16:51:03 +08:00
.forgejo/workflows chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
.husky chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
app chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
public chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
server chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
shared chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
tests/unit chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
.editorconfig chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
.gitignore chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
.npmrc chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
.nuxtrc chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
.nvmrc chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
.prettierignore chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
.prettierrc chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
BACKEND_INTEGRATION.md chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
commitlint.config.js chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
ecosystem.config.cjs chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
eslint.config.mjs chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
nuxt.config.ts chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
package.json chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
pnpm-lock.yaml chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
pnpm-workspace.yaml chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
PRODUCT_PLAN.md chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
README.md chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
SETUP_HANDOFF.md chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
tailwind.config.js chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
tsconfig.json chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00
vitest.config.ts chore: init likebocai-nuxt project 2026-07-09 16:51:03 +08:00

likebocai-nuxt

单个 Nuxt 4 应用,按二级域名分流,一个 Node 服务撑起全部子站。

以「个人品牌 + 社区互动」为核心的多子域名门户网站前端。 后端为独立 Java 项目Spring Security + Knife4j前端通过 RESTful API 交互。


目录


🌐 子站架构

www.likebocai.com      → 🏠 主站门户(导航 + 动态聚合)
blog.likebocai.com     → 📝 博客(长文 + 📸 随手拍 / 朋友圈式轻分享)
mail.likebocai.com     → ⏳ 时光邮箱(未来信件 + 公开信)
game.likebocai.com     → 🎮 游戏站(平台绑定 + 游戏墙 + 教程 + 论坛)
admin.likebocai.com    → 📊 管理后台
  • 代码组织:单仓库 + 单应用,不拆 monorepo组件放 app/components/ 天然共享
  • 域名分流:方案 B——pages/ 按子站前缀组织(blog/mail/game/ 等),中间件根据 Host 头 rewrite

🛠️ 技术栈

核心框架

类别 方案 版本(精确锁定)
框架 Nuxt 4 + Vue 3 + TypeScript nuxt 4.4.8 / vue 3.5.39 / typescript 6.0.3
Node 22.16.0brew install node@22 .nvmrc 精确锁
包管理器 pnpm + Corepack pnpm@11.10.0packageManager 字段锁)
渲染模式 SSR / SSG 内容页保 SEO

样式 & UI

类别 方案 说明
CSS 方案 Tailwind CSS v3@nuxtjs/tailwindcss 稳字当头v4 生态成熟后再升级
UI 组件 手写为主 + Reka UI 按需 追求活力/原创/扩展性Reka UI 是 Headless 库SSR/SEO 友好
组件命名 Nuxt 自动导入(文件即路由) 子目录自动添加前缀(如 blog/ArticleCard.vue<BlogArticleCard>
动效 分层CSS/motion → GSAP CSS 优先,复杂动画后期引入 GSAPcomposable 封装,兼容升级
深色模式 Tailwind darkMode: 'class' + useDark() @vueuse/core
移动端 响应式 / 移动优先 Tailwind 响应式工具类

内容渲染 & 编辑

场景 编辑器 存储格式 渲染引擎 用户
博客长文 / 游戏教程 md-editor-v3(分屏 MD Markdown markdown-it + Shiki 懂 MD 的作者
时光邮箱 / 评论 Tiptap(所见即所得) JSON @tiptap/html generateHTML() 零门槛泛人群

渲染一致性保证:

  • Tiptap 编辑器 + generateHTML()同一套 extensions 配置
  • 所有 UGC 输出必须经过 isomorphic-dompurifySSR 同构版)消毒
  • 禁止在 onMounted<ClientOnly> 里做正文渲染(毁 SEO

状态管理 & 工具

类别 方案 说明
状态管理 Pinia(复杂业务)+ useState(轻量) @pinia/nuxt
工具库 @vueuse/core + @vueuse/nuxt Vue 瑞士军刀
API 封装 app/composables/useApi.ts $fetch.create + 双 Token 刷新 + 401 拦截
Markdown 渲染 app/composables/useMarkdown.ts markdown-it + Shiki 高亮 + DOMPurify
Tiptap 渲染 app/composables/useTiptapRender.ts generateHTML() + DOMPurify

性能 & SEO & PWA

类别 方案 说明
图片优化 @nuxt/image 懒加载 + WebP/AVIF + 响应式(图多,重中之重)
字体优化 @nuxt/fonts
第三方脚本 @nuxt/scripts 延迟加载
PWA @vite-pwa/nuxt 可安装 + 离线 + 推送
SEO @nuxtjs/sitemap + useSeoMeta 按域名动态生成 sitemap / robots
打包分析 nuxi analyze 按路由分包

搜索方案

类别 方案 说明
后端引擎 Meilisearch 后端已选型,全文检索/分词/高亮/拼写容错
范围 全站聚合搜索 + 各子站精搜 主站大搜索框,各站也有自己的搜索
前端交互 即时搜索(打字实时出结果) Meilisearch 天生擅长
前端对接 JS SDK / instant-meilisearch 只用只读 Search API Key或走 Java 代理
安全 前端直连限只读 Key防抖 + 最小字符数 ⚠️ Phase 2 开发到此模块时重点处理

代码规范 & 测试

类别 方案 说明
ESLint @nuxt/eslint Nuxt 官方模块flat config
Prettier 独立配置 .prettierrc semi: false, singleQuote, trailingComma: all
Husky pre-commit: lint + format; pre-push: test 提交前自动检查
commitlint @commitlint/config-conventional feat:/fix:/docs:/chore:...
单元测试 Vitest + @nuxt/test-utils 轻量策略,只测核心逻辑
E2E Playwright(后期补) 项目稳定后再写用例
错误监控 Phase 1 最小化(onErrorCaptured + 日志) Phase 2 上 Sentry
IDE WebStorm 主力VS Code 备用 .editorconfig 跨 IDE 统一格式

TS 类型同步

  • 开发时手写在 shared/types/
  • 后端 Knife4j 提供 /v3/api-docsOpenAPI JSON
  • CI 中跑 openapi-typescript 自动生成到 shared/types/api.d.ts
  • 前后端类型强制一致

部署

类别 方案 说明
进程守护 PM2 ecosystem.config.cjs,平滑重启
反向代理 Nginx 所有子域名反代到同一 Nuxt 端口,透传 Host 头
HTTPS 全站强制 SSO Cookie Secure 的前提
CI/CD Forgejo Actions push → lint → test → build → 传服务器 → pm2 reload
版本号 3.0.0.260708_Likebocai-nuxt 和后端 3.0.0.260708_Likebocai 对齐

🚀 快速开始

# 1. 确保 Node >= 22.16.0(见 .nvmrc
node --version

# 2. 启用 Corepack锁死 pnpm 版本)
corepack enable

# 3. 安装依赖(冻结 lockfile可复现
pnpm install --frozen-lockfile

# 4. 启动开发服务器
pnpm dev
# → http://localhost:3000

🏗️ 项目架构

1. 域名分流(命根子)

一个 Nuxt 应用,靠读取请求的 Host 头判断访问的是哪个子站,然后切换布局 + 内容

流程

用户浏览器 → Nginx → Nuxt SSR 服务
                        ↓
               domain.global.ts全局中间件
                 → useRequestHeaders(['host']) 读 Host
                   → getSiteByHost(host) 解析子站
                     → useState('site') 注入全站
                       → setPageLayout() 切换布局
                         → 渲染对应内容

实现

  • 域名映射表集中在 app/utils/site-config.ts
  • 页面按子站前缀组织在 pages/ 下(方案 B
  • 各子站布局文件在 layouts/
  • useSite() composable 供全站读取当前子站信息

关键前提

  • Nginx 必须 proxy_set_header Host $host; —— 漏了分流全废
  • 全站 HTTPS —— SSO Cookie 需 Secure
  • 开发环境:配 /etc/hosts 模拟多域名

2. SSO 鉴权(单点登录)

总体方案

JWT 放在 httpOnly Cookie不放 localStorage防 XSS
Cookie domain: .likebocai.com → 所有子域名共享登录态
属性HttpOnly + Secure + SameSite=Lax

双 Token 无感知刷新

Token 生命周期 Cookie 类型 说明
Access TokenJWT 15~30 分钟 会话 Cookie不设 Max-Age 实际鉴权用
Refresh Token 7~30 天 持久 Cookie设 Max-Age 换新 Access Token
API 返回 401Access Token 过期)
  → 前端自动调 POST /api/auth/refresh
    → Java 验 Refresh Token
      → 通过:签发新 Access TokenSet-Cookie重试原请求
      → 失败Refresh 也过期真·401跳登录页

前端职责

  1. 应用启动时调 GET /api/auth/me 获取用户信息 → 存入 Pinia
  2. API 请求时浏览器自动带 Cookie前端不手动加 Token
  3. SSR 时用 useRequestHeaders(['cookie']) 转发 Cookie → Java
  4. 响应 401 → 自动 Refresh → 重试 → 再失败跳 /auth/login
  5. auth.ts 中间件做登录保护

Phase 1 范围

  • 邮箱 + 密码注册/登录
  • OAuthGitHub/Google/微信)→ Phase 2 TODO

需要的后端接口

方法 路径 说明
POST /api/auth/login 邮箱密码登录Set-Cookie 返回双 Token
GET /api/auth/me 获取当前用户信息
POST /api/auth/refresh 刷新 Access Token
POST /api/auth/logout 登出,清除 Cookie

详见 BACKEND_INTEGRATION.md


3. 两条内容管线

博客 / 游戏教程 时光邮箱 / 评论
用户群 作者 / 懂 MD 的人 泛人群(多为小白)
编辑器 md-editor-v3(分屏 MD Tiptap(所见即所得)
编辑体验 # 标题 点按钮加粗/插图
存储格式 Markdown 字符串 Tiptap JSONgetJSON()
图片上传 编辑器配置 OSS 上传 URL 编辑器 Image 扩展 + 上传回调
渲染 markdown-itSSR 阶段) @tiptap/html generateHTML()
代码高亮 Shiki
XSS 消毒 isomorphic-dompurify isomorphic-dompurify
特殊能力 代码块 / 数学公式(可扩展) 自定义表情包(仅评论区用)

表情包归属: 全站只有评论区需要自定义表情包。博客、游戏教程、时光邮箱只需正常图片上传,不涉及表情语法。

Server API给 Java 后端调用):

方法 路径 说明
POST /api/render-md Markdown → HTML供 Java 渲染博客/教程内容)
POST /api/render-tiptap Tiptap JSON → HTML供 Java 渲染邮箱/评论内容)

4. API 请求封装

统一走 app/composables/useApi.ts

  • baseURL 自动读取 runtimeConfig.public.apiBaseUrl
  • 客户端Cookie 自动带(同域名 .likebocai.com
  • SSR转发客户端 Cookie → Java API
  • 401自动 Refresh → 重试 → 再失败跳 /auth/login
  • 防并发刷新(同时多个 API 401 只发一次 refresh

RESTful 约定

统一响应结构:

{
  "code": 0,
  "message": "ok",
  "data": {}
}

分页:

{
  "code": 0,
  "data": {
    "list": [],
    "total": 100,
    "page": 1,
    "pageSize": 10
  }
}

5. SSR 渲染铁律

正文渲染必须在服务端完成,绝不放在客户端。

正确SEO 友好) 错误(毁 SEO
useAsyncData 里渲染 onMounted 里渲染
computed 里渲染 <ClientOnly> 包裹正文
SSR 输出完整 HTML 爬虫看到空壳

markdown-it@tiptap/htmlgenerateHTML() 都是纯 JS 函数, 在 Node 端可以正常跑,关键在于调用时机

isomorphic-dompurify 是同构版本,服务端和浏览器都能消毒。


6. 环境变量管理

环境 配置方式
本地开发 .env + .env.developmentNuxt 原生支持)
PM2 生产 ecosystem.config.cjsenv 字段

runtimeConfig 划分:

级别 范围 示例
public 前端可访问 apiBaseUrl, siteUrl
private 仅 Nitro 服务端 内部 API Token、密钥

当前变量:

变量 用途
NUXT_PUBLIC_API_BASE_URL Java 后端 API 地址(默认 https://api.likebocai.com
NUXT_PUBLIC_SITE_URL Nuxt 自身地址OAuth 回调 / sitemap 生成用(默认 https://www.likebocai.com

.env.example 提交到仓库做示范。


📂 目录结构

likebocai-nuxt/
├── app/
│   ├── assets/css/                # Tailwind 入口 + 各子站主题变量
│   │   └── themes/                # blog.css / mail.css / game.css
│   ├── components/                # 组件Nuxt 自动导入)
│   │   ├── AppHeader.vue          # 全站通用头部
│   │   ├── AppFooter.vue          # 全站通用页脚
│   │   ├── ThemeToggle.vue        # 深色模式切换
│   │   ├── base/                  # 手写基础组件
│   │   │   ├── BaseButton.vue     # 精心打磨,全站复用
│   │   │   ├── BaseCard.vue
│   │   │   ├── BaseInput.vue
│   │   │   └── BaseModal.vue      # 复杂交互内部用 Reka UI
│   │   ├── blog/                  # 博客专属
│   │   │   ├── MarkdownRenderer.vue   # markdown-it + Shiki + DOMPurify
│   │   │   └── moment/            # 随手拍
│   │   ├── mail/                  # 时光邮箱专属
│   │   │   ├── LetterEditor.vue       # Tiptap 封装
│   │   │   ├── MailPreview.vue        # 邮件模板预览(双视图对照)
│   │   │   └── EnvelopeOpen.vue       # 招牌信封动画
│   │   └── comment/              # 评论组件(跨站复用)
│   │       ├── CommentEditor.vue      # Tiptap + 自定义表情包 + 安全护栏
│   │       ├── CommentList.vue        # 首屏 SSR + "加载更多"
│   │       └── CommentItem.vue
│   ├── composables/               # 组合式函数(自动导入)
│   │   ├── useSite.ts             # 当前子站信息(由域名中间件注入)
│   │   ├── useAuth.ts             # 登录态 / SSO
│   │   ├── useTheme.ts            # 深色模式
│   │   ├── useApi.ts              # API 请求封装(双 Token 刷新 + 401 处理)
│   │   ├── useMarkdown.ts         # MD → HTML 渲染SSR 安全)
│   │   ├── useTiptapRender.ts     # Tiptap JSON → HTMLSSR 安全)
│   │   └── useCardHover.ts        # 动效封装示例(便于升级 GSAP
│   ├── layouts/                   # 布局(各子站不同风格)
│   │   ├── default.vue            # 主站 / 兜底
│   │   ├── blog.vue               # 博客
│   │   ├── mail.vue               # 时光邮箱
│   │   ├── game.vue               # 游戏站
│   │   └── admin.vue              # 管理后台(侧边栏布局)
│   ├── middleware/                # 路由中间件
│   │   ├── domain.global.ts       # 🔑 全局域名分流(核心中间件)
│   │   └── auth.ts                # 登录保护(按需使用)
│   ├── pages/                     # 页面(按子站前缀组织)
│   │   ├── index.vue              # 主站首页www
│   │   ├── blog/
│   │   │   ├── index.vue          # 博客首页 / 列表
│   │   │   ├── [slug].vue         # 文章详情
│   │   │   └── moments.vue        # 随手拍时间流
│   │   ├── mail/
│   │   │   ├── index.vue          # 公共信件广场
│   │   │   ├── write.vue          # 写信Tiptap
│   │   │   └── [id].vue           # 信件详情
│   │   ├── game/                  # 游戏站Phase 2
│   │   ├── user/
│   │   │   ├── [username].vue     # 个人主页
│   │   │   └── settings.vue       # 用户设置
│   │   └── auth/
│   │       ├── login.vue          # 登录
│   │       └── callback.vue       # OAuth 回调
│   ├── plugins/                   # 插件TipTap 客户端初始化等)
│   ├── stores/                    # Pinia
│   │   ├── auth.ts                # 用户登录态
│   │   └── ui.ts                  # 主题、全局 UI 状态
│   ├── utils/                     # 纯工具函数
│   │   ├── site-config.ts         # 域名 ↔ 子站映射表(唯一数据源)
│   │   ├── sanitize.ts            # DOMPurify 封装
│   │   └── date.ts                # 日期工具(信件解锁判断、格式化)
│   ├── app.vue                    # 根组件
│   └── error.vue                  # 错误页
│
├── server/                        # Nitro 服务端
│   ├── api/
│   │   ├── render-md.post.ts      # Markdown → HTML给 Java 调)
│   │   └── render-tiptap.post.ts   # Tiptap JSON → HTML给 Java 调)
│   └── routes/
│       └── sitemap.xml.ts         # 按域名动态生成 sitemap
│
├── shared/                        # 前后端共享
│   ├── types/                     # TS 类型
│   │   ├── api.ts                 # API 响应结构 + 分页
│   │   ├── user.ts                # User 实体
│   │   ├── blog.ts                # BlogArticle 实体
│   │   └── mail.ts                # MailLetter 实体
│   ├── constants/                 # 常量(子站/分类/权限枚举)
│   └── email-templates/           # 📮 邮件模板(前后端同源)
│
├── tests/
│   ├── unit/                      # Vitest 单元测试
│   └── e2e/                       # Playwright E2E后期
│
├── .forgejo/workflows/ci.yml     # Forgejo Actions CI/CD
├── ecosystem.config.cjs           # PM2 部署配置
├── nuxt.config.ts                 # Nuxt 配置
├── tailwind.config.js             # Tailwind v3
├── eslint.config.mjs              # ESLint@nuxt/eslint flat config
├── .prettierrc                    # Prettier
├── .prettierignore
├── .editorconfig                  # 跨 IDE 统一格式
├── commitlint.config.js           # 提交信息规范
├── vitest.config.ts               # Vitest
├── tsconfig.json                  # TypeScript
├── .nvmrc                         # Node 版本锁
├── .npmrc                         # save-exact + engine-strict
├── .gitignore
├── README.md                      # 本文档
├── PRODUCT_PLAN.md                # 产品全景需求文档
├── SETUP_HANDOFF.md               # 技术选型 & 决策记录
└── BACKEND_INTEGRATION.md         # 后端对接文档(鉴权/API/类型同步)

💻 本地多域名调试

# 1. 配 /etc/hosts
sudo sh -c 'cat >> /etc/hosts << EOF
127.0.0.1 www.likebocai.local blog.likebocai.local game.likebocai.local mail.likebocai.local admin.likebocai.local
EOF'
访问地址 子站
http://localhost:3000 未知(默认主站布局)
http://blog.likebocai.local:3000 博客
http://mail.likebocai.local:3000 时光邮箱
http://game.likebocai.local:3000 游戏站

用 curl 验证 SSR 分流:

curl http://localhost:3000/                          # → 当前子站:未知
curl -H "Host: blog.likebocai.local" localhost:3000/ # → 当前子站:博客
curl -H "Host: mail.likebocai.local" localhost:3000/ # → 当前子站:时光邮箱

📋 常用命令

命令 用途
pnpm dev 启动开发服务器
pnpm build 生产构建
pnpm preview 本地预览生产构建
pnpm lint ESLint 检查
pnpm format Prettier 格式化
pnpm test Vitest 测试watch 模式)
pnpm test:run Vitest 测试(单次运行)
pnpm typecheck vue-tsc 类型检查
pnpm analyze nuxi analyze 打包体积分析

🔒 版本锁定规范

Owner 上个项目因为没锁版本吃了依赖漂移的大亏,以下每一条都是血的教训。

层级 手段 作用
Node .nvmrc + package.json engines + .npmrc engine-strict=true 锁运行时版本
包管理器 package.json packageManager 字段 + Corepack 锁 pnpm 版本
直接依赖 .npmrc save-exact=true精确版本不用 ^ ~ 锁自己装的包
依赖树 提交 pnpm-lock.yaml + CI 用 pnpm install --frozen-lockfile 锁所有间接依赖
主动升级 pnpm outdated 手动 review 升级 有意识升级,不被动漂移

升级纪律

pnpm outdated           # 查看可升级的包
pnpm up <包名>          # 手动升级(精确版本)
# 升完必须跑测试
pnpm test:run

📏 代码规范

ESLint

  • 使用 @nuxt/eslintNuxt 官方模块flat config
  • 配置文件:eslint.config.mjs

Prettier

{
  "semi": false,
  "singleQuote": true,
  "trailingComma": "all",
  "printWidth": 100,
  "tabWidth": 2
}

Git Hooks

Hook 做什么
pre-commit lint-stagedESLint fix + Prettier write
pre-push pnpm test:run

Commit 规范

feat: 新功能
fix: 修 Bug
docs: 文档
style: 格式(不影响逻辑)
refactor: 重构
perf: 性能优化
test: 测试
chore: 杂项(依赖/构建/配置)
ci: CI/CD
build: 构建系统

🧪 测试策略

轻量策略 —— 只测最怕出错的核心逻辑,不为了测试而测试。

优先级

优先级 模块 测什么
时光邮箱权限判断 仅双方可见/可公开/甄选/匿名——隐私泄露后果严重
时光邮箱解锁时间 到期才开放、时区边界——未到期绝不能泄露
Markdown 渲染 + XSS 渲染正确性 + 脚本过滤——安全红线
评论安全护栏 长度限制、图片数量限制、格式收窄——是否生效
SSO 登录态 Cookie 读取、路由保护中间件
游戏数据处理Phase 2 游戏墙排序、成就聚合、年度报告统计
通用工具函数 日期格式化、数据转换——成本最低,最好测

运行

pnpm test       # watch 模式
pnpm test:run   # 单次运行CI 用)

🚢 部署

PM2

ecosystem.config.cjs

module.exports = {
  apps: [
    {
      name: 'likebocai-nuxt',
      script: './.output/server/index.mjs',
      env: {
        NUXT_PUBLIC_API_BASE_URL: 'https://api.likebocai.com',
        NUXT_PUBLIC_SITE_URL: 'https://www.likebocai.com',
      },
    },
  ],
}
pnpm build
pm2 start ecosystem.config.cjs
pm2 reload ecosystem.config.cjs  # 平滑重启,不断服

Nginx 反代关键点

# 所有子域名反代到同一个 Nuxt 端口
server {
    server_name ~^(www|blog|game|mail|admin)\.likebocai\.com$;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;           # ⚠️ 命根子:漏了域名分流全废
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # 静态资源可让 Nginx 直接托管 .output/public减轻 Node 压力
    # location /_nuxt/ { alias /path/to/.output/public/_nuxt/; }
}

全站必须 HTTPS —— SSO Cookie 的 Secure 标志要求。

CI/CDForgejo Actions

.forgejo/workflows/ci.yml

push (main / dev)
  → install --frozen-lockfile
    → lint
      → test:run
        → build
          → 传 .output 到服务器
            → pm2 reload

⚠️ 服务器地址、SSH 密钥等需和 owner 确认。


🗺️ MVP 分期

🚀 Phase 1第一版上线

模块 范围
主站门户 完整
博客(长文 + 随手拍) 完整
时光邮箱 完整
用户系统 + SSO 邮箱密码
评论系统 完整(含自定义表情包)
友链 完整
SEO 完整SSR/sitemap/meta
深色模式 完整
移动端适配 完整
PWA 完整
RSS 完整

🔧 Phase 2

模块 范围
游戏站 平台绑定 + 游戏墙 + 教程
作品集 完整
消息通知 完整
管理后台 完整
全局搜索 Meilisearch 即时搜索
OAuth GitHub / Google / 微信
Sentry 前端错误监控

🎯 Phase 3

模块 范围
游戏站 ToC 论坛 + 年度报告
多语言 英文支持
统计埋点 GA / Umami

📦 各模块功能概要

主站门户www

  • 个人品牌展示(头像、简介、社交链接)
  • 各子站最新内容聚合
  • 导航到各子站

博客blog

  • 长文:多分类(技术/生活/其他、MD 编辑、草稿/发布/定时、标签、RSS、评论、社交分享
  • 随手拍:短图文、多图九宫格、位置标记、心情标记、时间流、点赞评论、权限控制(公开/好友/自己)

时光邮箱mail

  • 给自己写信:设未来日期,到期才能打开
  • 公开信件:发布到公共广场
  • 给别人写信:指定收件人
  • 隐私控制:仅双方可见/可公开/甄选信件
  • 匿名/实名选项
  • 邮件通知:前端提供邮件模板预览(双视图对照编辑)

游戏站game—— Phase 2

  • 平台绑定Steam/PSN/Xbox/Nintendo Switch
  • 数据同步:游戏库、游玩时长、成就、奖杯
  • 游戏墙:有稀有成就/白金奖杯优先排列
  • 教程 & 评测Markdown与博客共享编辑体验
  • 社区ToC 论坛、组队招募Phase 3
  • 年度游戏报告Phase 3

评论系统(跨站复用)

  • 两层结构(评论 + 楼中楼回复平铺)
  • Tiptap 富文本(加粗/链接/列表/代码/图片/自定义表情包)
  • 安全护栏XSS 消毒、长度限制、图片数量限制、格式收窄
  • 首屏第一页 SSR"加载更多"按钮客户端加载

管理后台admin—— Phase 2

  • 文章管理 / 用户管理 / 信件管理审核 / 论坛管理 / 数据统计看板

🔜 待办

  • git init + 关联 Forgejo 远程仓库
  • pnpm exec husky init(初始化 Git Hooks
  • /etc/hosts 多域名
  • CI/CD 部署步骤补全服务器信息
  • 后端对接文档发给 Java 伙伴