7ちゃんねる
技术文档
首页

7ch 技术文档

架构、数据契约与匿名 ID 机制

#项目概览

7ch 是一个面向匿名交流的文本社区,主打低门槛发言与轻量身份识别。

生产环境采用前后端分离:浏览器 SPA 负责界面与交互,API 服务提供业务能力,Postgres 存储内容。前端部署在 Vercel,后端部署在 Render,数据库位于 Neon。

前端技术栈
  • React 19 + React Router 7(页面路由)
  • TypeScript + Vite(类型与构建)
  • Tailwind CSS + Radix UI(样式与组件)
  • i18next(多语言)
核心概念
  • 前后端分离与 REST API
  • 真实 API + 可选 Mock(开发/演示)
  • 匿名身份:每日 ID + Tripcode
  • 服务端持久化 + 客户端偏好缓存
源码未对外公开,但本文档公开关键机制与数据字段,尤其是每日匿名 ID 的计算方式,便于用户理解与验证。

#架构与部署

系统由浏览器客户端、API 服务与数据库三层组成。客户端仅通过 /api 与服务交互,服务端负责限流、过滤与身份计算后再读写数据库。

路由与页面结构

主要页面路径(简化示意):

Routing Map
/                       -> Home (Boards)
/board/:boardId         -> Board
/board/:boardId/thread/:threadId -> Thread
/favorites              -> Favorites
/docs | /help | /terms | /privacy | /QA -> Static Pages

所有业务数据(板块、线程、回帖)都由 API 提供,客户端仅持久化语言、关注与隐藏等偏好。

#数据模型与契约

客户端看到的核心实体为 Board / Thread / Post。服务端保存更多字段(如 IP、时间戳),但对外仅返回公开字段。

实体

  • Board: 板块为固定配置,包含 ID、名称、描述。
  • Thread: 线程包含标题、回复数、浏览数、更新时间,以及 OP 预览。
  • Post: 帖子为楼层记录,包含显示名、Tripcode、内容、每日 ID 等。

对外字段统一为 camelCase。

Public Post Shape
{
  "id": 12,
  "threadId": "<uuid>",
  "name": "Anonymous",
  "tripcode": "◆abcd1234ef",
  "content": "...",
  "createdAt": "2026-02-03T12:00:00Z",
  "uid": "A1b2C3d4",
  "isOp": false
}

#匿名与核心机制

1. 每日匿名 ID(Daily ID)

每日 ID 用于区分同一天、同板块内的发言者,同时避免长期追踪。

  • 输入:客户端来源 IP、当前日期(UTC)、板块 ID、服务器私有盐值。
  • 处理:SHA-256 哈希 → Base64 URL Safe(无补位)→ 截断前 8 位。
  • 输出:形如 ID:A1b2C3d4 的短标识。

同一 IP 在同一天同一板块 ID 稳定;跨天、换板块或更换网络会变化。共享出口 IP(NAT/校园网)可能显示相同 ID。

Daily ID Algorithm (Pseudo)
Raw = IP + Date(UTC: YYYY-MM-DD) + BoardId + SecretSalt
Hash = SHA256(Raw)
Encoded = Base64UrlSafeNoPad(Hash)
DailyId = Encoded.substring(0, 8)

为防滥用,服务端会保留来源 IP 用于风控,但不会在页面中公开。

2. Tripcode(绊码)

名字栏输入 Name#password 会生成 Tripcode,用于“证明同一人”但不需要账号。密码只参与哈希计算,存储的是短哈希片段。

Input: "Name#password"
Name = "Name"
Tripcode = "◆" + hex(SHA256(password + SecretSalt)).slice(0, 10)

3. Sage 下沉

Email 字段包含 sage(不区分大小写)时,回帖不会顶帖,只增加回复数。

const isSage = email?.toLowerCase().includes('sage');
if (!isSage) {
  thread.updatedAt = now; // bump only when NOT sage
}

4. 引用与预览

客户端解析 >>123 引用并提供悬停预览;服务器只存原文,不做特殊解析。

5. 内容过滤与风控

服务端对敏感词进行替换,并进行基础限流以降低刷屏与攻击风险。

#国际化与本地化

目前提供中文(zh-CN)与日文(ja-JP)。

基于 react-i18next,包含针对日文日期格式的本地化处理:

  • 日本纪元日期:如 2025 显示为 R7。
  • 星期几:显示为 (月)、(火) 等。
Date Format (ja-JP)
if (d.getFullYear() >= 2019) y = 'R' + (d.getFullYear() - 2018); // Reiwa
else if (d.getFullYear() >= 1989) y = 'H' + (d.getFullYear() - 1988); // Heisei
7ch 技术文档 | 7ちゃんねる