メンバー追加・削除の運用手順
データの二重管理について
メンバーデータは以下の2か所で管理されている。
| 場所 | 用途 | 更新タイミング |
|---|---|---|
data/work/members.json |
ビルド時のルート生成(generateStaticParams)に使用。各メンバーの詳細ページ URL を静的に生成するためのシード。 |
メンバー追加・削除時に手動編集 |
Vercel Blob (members.json) |
ランタイムに getMembersFromBlob() で読まれる実データ。トップ画面・詳細画面・API が参照する。 |
新規メンバー追加時: bun run upload-members でマージ追加。既存メンバーの更新(OG 変更等): PUT /api/members で直接更新 |
注意: ランタイムが読むのは Vercel Blob のみ。data/work/members.json を編集しただけでは画面に反映されない。Blob も必ず更新すること。
注意: data/work/ は作業用の一時ファイル置き場(.gitignore 対象)。data/work/members.json は手順のたびに用意し、Blob への反映が完了したら削除してよい。
bun run upload-membersの用途: 新規メンバー追加専用。Blob-first マージのため、既存メンバーのフィールド変更(OG への変更等)には使用できない。既存メンバーの更新はPUT /api/membersを使用すること。
新メンバー追加手順
1. data/work/members.json を編集する
以下の JSON 構造に従いエントリを追加する。配列末尾に追記することを推奨(id 重複・JSON 構文エラーに注意)。
{
"id": "yamada-hanako",
"name": "山田花子",
"ruby": "やまだ はなこ",
"status": "Active",
"generation": 14,
"profile": {
"dob": "2005-01-01",
"joinDate": "2023-04-01",
"gradDate": null,
"family": ""
},
"latestStatus": {
"content": "活動状況の初期説明文。",
"lastUpdated": "2026-01-01",
"sources": []
},
"statusHistory": [],
"officialSns": [
{
"url": "https://example.com/yamada-hanako/",
"active": true
}
]
}
フィールド仕様
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
id |
string |
✅ | URLセーフなローマ字表記(例: yamada-hanako)。変更不可。 |
name |
string |
✅ | 表示名(漢字) |
ruby |
string |
✅ | ふりがな(半角スペース区切り) |
status |
"Active" | "OG" |
✅ | Active=現役、OG=卒業済み。OG は不可逆(一度 OG にしたら Active に戻さない) |
generation |
number |
✅ | 期番号(整数) |
profile.dob |
string |
✅ | 生年月日(YYYY-MM-DD) |
profile.joinDate |
string |
✅ | 加入日(YYYY-MM-DD) |
profile.gradDate |
string | null |
✅ | 卒業日(YYYY-MM-DD)。現役は null |
profile.family |
string |
✅ | 家族構成の説明文(空文字可) |
latestStatus.content |
string |
✅ | 最新の活動状況テキスト |
latestStatus.lastUpdated |
string |
✅ | 最終更新日(YYYY-MM-DD) |
latestStatus.sources |
string[] |
✅ | 情報源 URL のリスト(空配列可) |
statusHistory |
StatusEntry[] |
— | 近況履歴。初期値は [] |
officialSns |
SnsEntry[] |
— | 公式 SNS URL リスト。省略可。 |
officialSns[].url |
string |
— | SNS の URL |
officialSns[].active |
boolean |
— | true=有効(検索対象)、false=無効(スキップ) |
snsCheck |
SnsCheck |
— | バッチが自動更新するフィールド。手動設定不要。 |
2. Vercel Blob を更新する
data/work/members.json の新規メンバーを Vercel Blob の既存データとマージしてアップロードする。
bun run upload-members
実行後に出力される URL が現在の MEMBERS_BLOB_URL と一致していることを確認する(固定 URL で上書きされるため通常は同じ)。
マージ動作について:
bun run upload-membersは Blob の既存データを保持したままマージを行う(Blob 優先)。
idをキーに照合し、Blob にのみ存在するメンバーはそのまま保持される。- ローカルにのみ存在するメンバー(新規)は追加される。
- 同一
idのメンバーは Blob 側の内容が優先される(バッチや画面編集で蓄積した近況・SNSデータを保護するため)。環境変数の準備:
BLOB_READ_WRITE_TOKENは Vercel ダッシュボード → Blob ストア → Tokens から取得する。 ローカルで実行する場合は.env.localに設定する。MEMBERS_BLOB_URLも設定しておくことで Blob の既存データを取得してマージできる(未設定の場合はローカルデータのみアップロード)。
3. 再デプロイする
data/work/members.json を変更した場合、generateStaticParams による静的ルート生成に反映するために再デプロイが必要。
# Vercel CLI を使う場合
vercel --prod
または GitHub に push して Vercel の自動デプロイを待つ。
注意: 再デプロイしないと、新メンバーの詳細ページ(
/members/<id>)が 404 になる。 ランタイムのトップ画面は Blob を直接読むため、Blob 更新後はデプロイなしでも反映される。
メンバー削除(または OG への変更)手順
OG(卒業済み)への変更
注意:
bun run upload-membersは Blob-first マージのため、ローカルでstatus: "OG"に変更しても Blob 側のstatus: "Active"が優先される。スクリプト経由では OG への変更は Blob に反映されない。 Blob の更新には API への直接呼び出しが必要。
1. data/work/members.json を更新する(ビルドシード用)
status を "OG" に変更し、profile.gradDate に卒業日を設定する。
"status": "OG",
"profile": {
"gradDate": "2026-03-01"
}
この変更は静的ルート生成(generateStaticParams)にのみ影響する。ランタイムに反映させるには次の手順が必要。
2. Blob を API 経由で更新する
PUT /api/members を直接呼び出して Blob を更新する。デプロイ済みのアプリの URL に対して実行する。
# 1. 現在のメンバーデータを Blob から取得する
curl -s "$MEMBERS_BLOB_URL" -o /tmp/members_current.json
# 2. 対象メンバーの JSON を /tmp/member_patch.json に用意する
# (/tmp/members_current.json から対象 id のオブジェクトを取り出し、
# status と profile.gradDate を変更したもの)
# 3. PUT リクエストで Blob を更新する
curl -X PUT https://<your-app>.vercel.app/api/members \
-H "Content-Type: application/json" \
-d @/tmp/member_patch.json
成功すると {"message":"Member updated successfully","member":{...}} が返る。
3. 再デプロイする
data/work/members.json を変更した場合は再デプロイして静的ルートに反映させる(新メンバー追加手順の 3 と同じ)。
メンバーエントリの物理削除
原則として物理削除は行わない。過去の活動記録を残すため status: "OG" への変更を推奨する。
どうしても削除が必要な場合は、data/work/members.json からエントリを削除した後、Blob 更新 → 再デプロイを行う。
officialSns の更新
SNS URL を追加・変更する場合は data/work/members.json を編集後、以下のスクリプトで Blob 上のデータに一括マージできる。
BLOB_READ_WRITE_TOKEN=<token> MEMBERS_BLOB_URL=<url> bun scripts/patch-official-sns.ts
詳細は docs/operations/patch-official-sns.md を参照。
Instagram アカウントは公式アカウントのみ登録する
ファン運営の非公式アカウント(.fanpage 等)は本人・事務所の管理下になく、非公開化・投稿停止・削除がいつ起きても不思議ではない。登録すると投稿収集(collect-instagram-posts.ts)でタイムアウトが連日発生する原因になるため、officialSns には公式アカウントのみを登録すること(#1348)。
メンバーカラーの登録・変更
メンバーカラーはメンバー詳細画面の期バッジ、メンバー一覧の期バッジ、歴史タイムラインのカード装飾に使用される。未設定のメンバーは世代共通カラー(GENERATION_COLORS)にフォールバックする。
CSV の管理
カラー定義は data/inputs/member-colors.csv で一元管理する。
id,color
nakazawa-yuko,#e60012
ishiguro-aya,#ff8c00
| 列 | 形式 | 説明 |
|---|---|---|
id |
文字列 | メンバー ID(data/work/members.json の id と一致させる) |
color |
#RRGGBB |
メンバーカラー(16進数 6 桁) |
カラーを Blob に反映する
BLOB_READ_WRITE_TOKEN=<token> MEMBERS_BLOB_URL=<url> bun scripts/patch-member-colors.ts
.env.local に環境変数が設定済みの場合は以下で実行できる。
bun --env-file=.env.local scripts/patch-member-colors.ts
動作仕様:
- CSV に記載された ID だけを対象に Blob の
colorフィールドを上書きする - CSV に載っていないメンバーは変更されない(既存カラーを保持)
- Blob に存在しない ID はスキップしてログ出力する
新メンバー追加時の対応
新メンバーを追加した際は、カラーが決まり次第 CSV に行を追加してスクリプトを実行する。カラーが未設定の間は世代カラーで表示される。
カラーを変更する場合
CSV の該当行の color 値を更新してスクリプトを再実行する。Blob の値が上書きされる。