7ちゃんねる
技術ドキュメント
ホーム

7ch 技術ドキュメント

アーキテクチャ、データ契約、匿名 ID の仕組み

#プロジェクト概要

7ch 匿名交流のためのテキストコミュニティで、低い参入障壁と軽量なアイデンティティを重視しています。

本番環境はフロントエンドとバックエンドを分離した構成です。ブラウザ SPA が UI と操作を担い、API サービスが機能を提供し、Postgres が内容を保存します。フロントは Vercel、バックエンドは Render、DB は Neon に配置されています。

フロントエンドスタック
  • React 19 + React Router 7(ルーティング)
  • TypeScript + Vite(型とビルド)
  • Tailwind CSS + Radix UI(スタイルとコンポーネント)
  • i18next(多言語)
主要概念
  • フロント/バック分離と REST API
  • 実 API + 任意の Mock(開発/デモ)
  • 匿名アイデンティティ:Daily ID + Tripcode
  • サーバー永続化 + クライアント設定キャッシュ
ソースコードは公開していませんが、本ドキュメントでは主要メカニズムと公開データ項目、特に Daily ID の算出方法を説明します。

#アーキテクチャとデプロイ

システムはブラウザクライアント、API サービス、データベースの三層で構成されます。クライアントは /api を通じてのみ通信し、サーバー側でレート制限・フィルタリング・ID 計算を行った上で保存されます。

ルーティングとページ構成

主なページパス(簡略):

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 やタイムスタンプ等の内部フィールドがありますが、公開 API では必要なフィールドのみ返します。

エンティティ

  • Board: 板は固定定義で、ID・名称・説明を持ちます。
  • Thread: スレッドはタイトル、返信数、閲覧数、更新日時、OP プレビューを含みます。
  • Post: 投稿は表示名、Tripcode、本文、Daily 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. Daily ID(毎日変わる匿名 ID)

Daily ID は同一板・同一日における発言者の識別に使われ、長期的な追跡を避けるため毎日変化します。

  • 入力:クライアントの送信元 IP、現在日付(UTC)、板 ID、サーバーの秘密ソルト。
  • 処理:SHA-256 ハッシュ → Base64 URL Safe(パディングなし)→ 先頭 8 文字を使用。
  • 出力:ID:A1b2C3d4 のような短い識別子。

同一 IP は同一板・同一日で安定。日付変更、板の変更、ネットワーク変更で ID は変化します。共有回線(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. フィルタリングと風紀対策

サーバー側で NG ワードの置換と基本的なレート制限を行い、スパムや攻撃を抑制します。

#国際化とローカライズ

現在は中国語(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ちゃんねる