尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證うんjレゼ
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
unj-reze うんjレゼ APIルートなし・モックデータのみの静的サイトとして自動デプロイされます。 • トリガー:main ブランチへの push、または Actions の手動実行 • 設定ファイル:.github/workflows/gh-pages.yml • URL:https:// .github.io/unj-reze/ • Netlify アカウント • Neon PostgreSQL プロジェクト • Cloudflare アカウント(R2 バケット・KV Namespace を作成済み) Netlify ダッシュボード → Add new site → Import an existing project → GitHub リポジトリを選択。 ビルド設定は netlify.toml から自動読み込みされるため変更不要。 netlify.toml に設定済みのため、Netlify 側で自動インストールされる場合は不要。 Netlify ダッシュボード → Site configuration → Environment variables で以下を登録: まず Cloudflare ダッシュボード → Workers & Pages → KV で Namespace を作成する。 その後、以下を Netlify の環境変数として登録:檢視完整 README ↗
うんjレゼ
| モード | 用途 | ホスト |
|---|---|---|
| 静的エクスポート | デモ・確認用 | GitHub Pages |
| サーバーモード | 本番運用 | Netlify |
APIルートなし・モックデータのみの静的サイトとして自動デプロイされます。
main ブランチへの push、または Actions の手動実行.github/workflows/gh-pages.ymlhttps://<user>.github.io/unj-reze/手動でローカルから静的ビルドを確認する場合:
NEXT_PUBLIC_STATIC_EXPORT=true pnpm build
# out/ ディレクトリに生成される
Netlify ダッシュボード → Add new site → Import an existing project → GitHub リポジトリを選択。
ビルド設定は netlify.toml から自動読み込みされるため変更不要。
pnpm add -D @netlify/plugin-nextjs
netlify.tomlに設定済みのため、Netlify 側で自動インストールされる場合は不要。
Netlify ダッシュボード → Site configuration → Environment variables で以下を登録:
データベース(Neon)
| 変数名 | 値 |
|---|---|
DATABASE_PROVIDER | neon |
DATABASE_URL | Neon の接続文字列(postgresql://...) |
KV(Cloudflare KV)
まず Cloudflare ダッシュボード → Workers & Pages → KV で Namespace を作成する。
その後、以下を Netlify の環境変数として登録:
| 変数名 | 値 |
|---|---|
KV_PROVIDER | cloudflare |
KV_ACCOUNT_ID | Cloudflare のアカウント ID |
KV_NAMESPACE_ID | 作成した Namespace の ID |
KV_API_TOKEN | KV 読み書き権限を持つ API Token |
API Token の作成:Cloudflare ダッシュボード → My Profile → API Tokens → Create Token
テンプレート「Edit Cloudflare Workers」または権限「Account / Workers KV Storage / Edit」を付与。
ストレージ(Cloudflare R2)
まず Cloudflare ダッシュボード → R2 → Create bucket でバケットを作成する。
その後、以下を Netlify の環境変数として登録:
| 変数名 | 値 |
|---|---|
STORAGE_PROVIDER | r2 |
R2_ACCOUNT_ID | Cloudflare のアカウント ID |
R2_ACCESS_KEY_ID | R2 API トークン(アクセスキー) |
R2_SECRET_ACCESS_KEY | R2 API トークン(シークレット) |
R2_BUCKET | バケット名 |
R2_PUBLIC_URL | バケットのパブリック URL(例:https://pub-xxxx.r2.dev) |
R2 API トークンの作成:Cloudflare ダッシュボード → R2 → Manage R2 API Tokens → Create API Token
権限は「Object Read & Write」を選択。
R2 パブリックアクセスの有効化:バケットの Settings → Public access → Allow Access をオンにする。
自動マイグレーションは廃止されました。初回セットアップ時やデータベースをリセットする際は、手動でSQLを適用してください。
docker compose up -d db-neon で
ローカルDBを初期化するのと同じSQLです)。docker/init.sql は作り直し用(先頭で全テーブルを DROP する)なので、稼働中の本番 Neon には
流さないこと。スキーマを変えたときは、既存DBに当てる差分SQLを新しい順にここへ書き足す。
(docker/init.sql と unj リポジトリの wiki/init.sql にも同じ変更を入れておく。)
2026-10-15 — 検索用インデックス(lib/db/pg.ts searchPosts / searchMedia)
検索を LOWER(content_text) LIKE に直して既存の trgm インデックスに乗せた。名前での一致は
reze 利用者の id を引いて user_id = ANY で足すので、そのためのインデックスを足す。当てる前でも
動くが、名前が一致する語では全件走査のまま。大きい表なので CONCURRENTLY で当てる
(トランザクションの外で1文ずつ)。
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_threads_user_id ON threads (user_id);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_res_user_id ON res (user_id);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_users_search_display_name
ON users USING gin (LOWER(display_name) gin_trgm_ops) WHERE display_name IS NOT NULL;
2026-10-09 — post_reposts(リポストをユーザーごとに。lib/db/pg.ts repostPost)
以前は threads/res.reposted という全員共通のフラグを反転していたので、誰かがリポストすると
全員の表示が切り替わっていた。デプロイ前に当てること:当てるまではリポスト操作が 500 になり、
ログイン中の閲覧(userId 付きのフィード等)で reposts > 0 の投稿があるページも 500 になる。
既存の reposts 件数は誰が押したかの記録が無いので引き継げない(下で 0 に戻す。戻さないと、
誰も解除できない件数が残る)。reposted 列は読まなくなったのでドロップしてよい(unj 側も未使用)。
鍵アカウント(users.is_private 等)の反映は既存の列だけで動くので、SQL は要らない。
CREATE TABLE IF NOT EXISTS post_reposts (
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
post_kind SMALLINT NOT NULL, -- 0=スレ(threads.id) / 1=レス(res.id)
target_id INT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (user_id, post_kind, target_id)
);
UPDATE threads SET reposts = 0 WHERE reposts <> 0;
UPDATE res SET reposts = 0 WHERE reposts <> 0;
-- 任意(後日でよい):
-- ALTER TABLE threads DROP COLUMN reposted;
-- ALTER TABLE res DROP COLUMN reposted;
2026-10-02 — otomads(音MAD。manifest 本体は R2、docs/otomad-feature-design.md §7)
POST /api/otomads が書く。当てるまでは音MAD付きの投稿が 500 になる(GET /api/otomads/1 が 404 を返すかで
表の有無を確認できる)。uploader-worker 側の otomad 種別(TEXT_KINDS)のデプロイも必要。
CREATE TABLE otomads (
id BIGINT PRIMARY KEY,
title TEXT NOT NULL,
manifest_url TEXT NOT NULL,
manifest_delete_id TEXT,
manifest_delete_hash TEXT,
bg_url TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
creator_user_id INT REFERENCES users(id) ON DELETE SET NULL,
plays BIGINT NOT NULL DEFAULT 0
);
CREATE INDEX idx_otomads_plays ON otomads (plays DESC);
CREATE INDEX idx_otomads_creator_user_id ON otomads (creator_user_id);
ALTER TABLE threads ADD COLUMN otomad_id BIGINT REFERENCES otomads(id) ON DELETE SET NULL;
ALTER TABLE res ADD COLUMN otomad_id BIGINT REFERENCES otomads(id) ON DELETE SET NULL;
CREATE INDEX idx_res_otomad_id ON res (otomad_id) WHERE otomad_id IS NOT NULL;
2026-09-21 — talks(かけあい動画。本番 Neon には適用済み)
記録のために残す。docs/talk-video-feature-design.md §5 と同じ内容。
CREATE TABLE talks (
id BIGINT PRIMARY KEY,
title TEXT NOT NULL,
manifest_url TEXT NOT NULL,
manifest_delete_id TEXT,
manifest_delete_hash TEXT,
bg_url TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
creator_user_id INT REFERENCES users(id) ON DELETE SET NULL,
plays BIGINT NOT NULL DEFAULT 0
);
CREATE INDEX idx_talks_plays ON talks (plays DESC);
CREATE INDEX idx_talks_creator_user_id ON talks (creator_user_id);
ALTER TABLE threads ADD COLUMN talk_id BIGINT REFERENCES talks(id) ON DELETE SET NULL;
ALTER TABLE res ADD COLUMN talk_id BIGINT REFERENCES talks(id) ON DELETE SET NULL;
CREATE INDEX idx_res_talk_id ON res (talk_id) WHERE talk_id IS NOT NULL;
2026-09-28 — preset_opens(ゲームエディタの見本プリセット/テンプレートが開かれた回数、日別)
POST /api/games/preset-open が書く。当てるまではその API が黙って数え漏らすだけで、エディタは壊れない。
CREATE TABLE IF NOT EXISTS preset_opens (
preset TEXT NOT NULL,
day DATE NOT NULL,
opens INT NOT NULL DEFAULT 0,
PRIMARY KEY (preset, day)
);
集計を見るとき(直近30日、多い順):
SELECT preset, SUM(opens) AS opens
FROM preset_opens
WHERE day >= (now() AT TIME ZONE 'Asia/Tokyo')::date - 30
GROUP BY preset
ORDER BY opens DESC;
main ブランチへの push で自動デプロイされます。手動デプロイは Netlify CLI から:
npx netlify deploy --prod
docker compose up -d # db-neon(Postgres) + minio(R2互換) を起動
cp .env.example .env
pnpm install
pnpm dev
.env.example のデフォルト値は上の docker-compose に向いているので、Neon/R2 の契約が
無くてもこのまま動きます。DB・ストレージそれぞれ独立して本物のサービスに切り替え可能:
| 変数 | docker(デフォルト) | 本物のサービスに切り替える場合 |
|---|---|---|
DATABASE_PROVIDER=neon + DATABASE_URL | postgresql://neon:neon@localhost:5432/unj_reze | Neonダッシュボードの接続文字列に差し替えるだけ(lib/db/pg.ts がホスト名で自動判別) |
STORAGE_PROVIDER=r2 + R2_* | R2_ENDPOINT=http://localhost:9000(minio) | R2_ENDPOINT を空にして R2_ACCOUNT_ID を設定するだけ(lib/storage/r2.ts が R2_ENDPOINT の有無で自動判別) |
DATABASE_PROVIDER=mock にすれば docker-compose すら不要(インメモリのモックデータのみ)。
.env.example を参照。