画面設計書
概要
MorningStatusApp は Next.js App Router をベースとした Web アプリケーション。 以下の38画面で構成される。
画面一覧
| 画面名 | URL パターン | レンダリング方式 | 追加バージョン |
|---|---|---|---|
| Topページ | / |
SSR(動的) | v0.1.0〜 |
| メンバー一覧 | /members |
SSR(動的) | v0.1.0〜 |
| メンバー詳細 | /members/[id] |
SSR(動的) | v0.1.0〜 |
| リリース一覧 | /releases |
SSR(動的) | v0.2.0〜 |
| リリース詳細 | /releases/[id] |
SSR(動的) | v0.2.0〜 |
| 曲詳細 | /songs/[id] |
SSR(動的) | v0.6.0 |
| プレイリスト一覧 | /playlists |
SSR(動的) | v0.7.0 |
| プレイリスト詳細 | /playlists/[id] |
SSR(動的) | v0.7.0 |
| 曲検索 | /search |
SSR(動的) | v1.0.0 |
| 対比一覧 | /comparisons |
SSR(動的) | v1.1.0 |
| 対比詳細 | /comparisons/[id] |
SSR(動的) | v1.1.0 |
| ユニット一覧 | /units |
SSR(動的) | v1.5.0 |
| ユニット詳細 | /units/[id] |
SSR(動的) | v1.5.0 |
| ライブ一覧 | /lives |
SSR(動的) | v3.0.0 |
| ライブ詳細 | /lives/[id] |
SSR(動的) | v3.0.0 |
| 地域ブロックマップ | /lives/map |
SSR(動的) | v3.0.0 |
| 都道府県別公演 | /lives/prefecture/[code] |
SSR(動的) | v3.0.0 |
| 同期状況 | /sync-status |
SSR(動的) | v3.3.0〜(デスクトップ専用) |
| 楽曲リンク修正 | /link-editor |
SSR(動的) | v5.5.0〜(デスクトップ専用) |
| YouTube投稿一覧 | /youtube |
SSR(動的) | v6.5.0 |
| YouTube公式チャンネル | /youtube/official |
SSR(動的) | v6.5.0 |
| YouTube OGチャンネル | /youtube/og/[memberId] |
SSR(動的) | v6.5.0 |
| フェス一覧 | /festivals |
SSR(動的) | v3.9.0 |
| フェス詳細 | /festivals/[id] |
SSR(動的) | v3.9.0 |
| セットリスト | /setlists/[id] |
SSR(動的) | v4.0.0 |
| ラジオ番組一覧 | /radio |
SSR(動的) | v4.3.0 |
| 番組別放送回一覧 | /radio/[show_id] |
SSR(動的) | v4.3.0 |
| 放送回詳細 | /radio/episodes/[episode_id] |
SSR(動的) | v4.3.0 |
| Instagram投稿一覧 | /instagram |
SSR(動的) | v4.5.0 |
| Instagramアカウント別 | /instagram/[accountId] |
SSR(動的) | v7.6.0 |
| TikTok投稿一覧 | /tiktok |
SSR(動的) | v4.2.0 |
| Amebaブログ一覧 | /ameba |
SSR(動的) | v4.5.0 |
| タイムライン | /timeline |
SSR(動的) | v5.0.0 |
| イベント詳細 | /events/[id] |
SSR(動的) | v10.0.0(#1583) |
| メンバー関係性マップ | /member-map |
SSR(動的) | v8.0.0 |
| レーダーチャート | /member-map/radar |
SSR(動的) | v9.0.0 |
| 平均年齢の変遷 | /average-age |
SSR(動的) | v10.2.0(#1595) |
| 世代マトリックス | /generational-matrix |
SSR(動的) | v10.6.0(#1632) |
機能別の詳細設計書:
- プレイリスト画面
- 曲対比画面
- ユニット画面
- ライブ機能画面
- YouTube投稿一覧画面
- タイムライン画面
- イベント詳細画面
- メンバー関係性マップ画面
- メンバー関係性マップ レーダーチャート画面
- 平均年齢の変遷グラフ画面
- 世代マトリックス画面
- ラジオオンエア データ(UI設計セクションあり)
- Amebaブログ機能(UI設計セクションあり)
画面遷移図
Topページが全ドメインのハブとなり1枚の図に収まらないため(#1435)、「TOP画面内遷移図」「外部遷移図(タイムライン・年表・関係性マップ系列)」「外部遷移図(リリース・ライブ・ラジオ等イベント系列)」の3図に分割する。
TOP画面内遷移図
Topページから各セクション一覧への一次遷移のみを示す。各セクション内部の詳細な遷移は後続の外部遷移図を参照。
外部遷移図(タイムライン・年表・関係性マップ系列)
EVENT(イベント詳細画面)の詳細設計はイベント詳細画面 設計書を参照(実装Issue: MorningStatusApp#1583)。
外部遷移図(リリース・ライブ・ラジオ等イベント系列)
音楽コンテンツ・ライブ/フェス・ラジオ・SNS投稿の4クラスタに分けて表示する。クラスタをまたぐ遷移(例: ライブ詳細→メンバー詳細)も存在する。
既知の制約: メンバー詳細(曲詳細も一部)が他クラスタと相互に繋がる実質的なハブになっているため、1枚の図にまとめるとMermaidのレイアウトエンジンが4クラスタを横に並べて配置し、図全体の実寸幅が広くなりすぎて何を見ているか把握しづらくなる(#1435, #30)。クラスタ単位、さらにクラスタ内でも関連の薄いグループ単位で図を分割し、他グループへの遷移先は接続先ノード(メンバー詳細・曲詳細等)のみを示す形にすることで、1図あたりのサイズを読める範囲に抑えている。接続先ノードの内部遷移は、そのノードが属する図を参照。
音楽コンテンツ
メンバー・リリース・曲・ユニット
プレイリスト・対比
ライブ・フェス
ライブ
フェス
ラジオ
SNS投稿
TikTok・Ameba
YouTube
各画面の設計
1. Topページ(/)
概要: ナビゲーション・新着投稿ダイジェストを表示するトップ画面。メンバーカード一覧は「2. メンバー一覧画面(/members)」に分離されている。
備考: タイトル要素(下表)は、世代マトリックス画面(
/generational-matrix)への隠し単語タップシーケンス入力も兼ねる。タイトルを構成する単語(Hello!/Project/History)そのものをタップ対象として使うため、このページのタイトル文言を変更する際は 世代マトリックス 画面設計書 §5-1aの仕様(タップ対象の単語構成・順序)に影響しないか必ず確認すること。
表示コンテンツ
| 要素 | 内容 |
|---|---|
| タイトル | “Hello! Project History” |
| サブテキスト | アプリの説明文(歴代メンバー数・対象年を含む) |
| バージョン・更新日 | `v{version} |
| ナビゲーションリンク | メンバー・ユニット・関係性マップ・平均年齢・リリース・プレイリスト・ライブ・フェス・ラジオ・対比(横並び。デスクトップモード時は楽曲リンク修正・同期状況も追加) |
| 曲検索・タイムラインリンク | グローバルヘッダー(全画面共通)。クリックでそれぞれ /search・/timeline に遷移 |
| 過去のこの日セクション | 参照日と月日が一致するメンバーの記念日(誕生日・加入日・卒業日)に加え、過去複数年にわたるリリース・ライブ・フェス・メディア(ラジオ)出演・トピック等の出来事を年ごとに一覧表示(OnThisDaySection)。新着投稿セクションより上に表示(#1514)。ライブ・フェスの出来事には会場名を併記し、時刻は00:00以外の場合のみ会場名の後ろに表示する(ライブはライブ・フェス機能 画面設計書の公演リスト表示項目と同一仕様、#1531。フェスはフェスの代表時刻を使う。定義はライブ・フェス機能 テーブル設計書 §2-7) |
| 新着投稿セクション | 「公式」「現役」「OG」の3ブロックでAmeba・Instagram・TikTok・YouTubeの新着をまとめて表示(後述、各ブロック内の各SNSの一覧画面へのリンクは新着0件でも常時表示) |
新着投稿セクション
- 表示条件: 各ブロック内の各SNSサブセクション(見出し・一覧画面へのリンク)は新着の有無に関わらず常時表示する。新着が0件のSNSは中身を「本日の新着投稿はありません」に差し替える(#1404の原則をブロック単位でも維持。以前は0件のSNSはリンクごと非表示になり、全SNSが0件の日はセクション全体が非表示だったため、一覧画面への導線が失われる不具合があった)
- 参照日ヘッダー:
{参照日の JST 日付} の新着投稿(詳細は後述の「参照日ヘッダー」を参照) - 著作権表記: 「(Instagram/TikTok/YouTubeの各画像は参考表示:権利はすべて投稿者に帰属しています)」。TikTok画像の参考表示期限切れ時はリンクのみの表示になる旨を併記
- ブロック構成(#1514): SNS別の4ブロック構成(Instagram→TikTok→YouTube→Amebaの固定順)から、投稿主体(公式アカウント/現役メンバー本人/OGメンバー本人)による3ブロック構成に再編する
| ブロック | 含まれるSNS | 各SNSでの対象投稿の絞り込み |
|---|---|---|
| 公式 | YouTube・TikTok・Instagram | 各SNSの公式アカウント・公式チャンネルの投稿のみ |
| 現役 | Ameba・Instagram | 現役(Active)メンバー本人の投稿のみ |
| OG | Ameba・Instagram・TikTok・YouTube | OGメンバー本人の投稿のみ |
- TikTok・YouTubeに「現役」ブロックが無いのは、収集対象外にしているためではなく、現役メンバーが個人でTikTok・YouTubeチャンネルを運用していないため(現役メンバーが自ら発信するSNSはAmebaブログ・Instagramのみ。TikTok・YouTubeでの現役メンバーの登場は公式チャンネル動画への出演・言及としてのみ間接的に確認できる。詳細は本ドキュメント「3. メンバー詳細画面」のTikTok投稿セクション・YouTube動画セクションを参照)
- Amebaに「公式」ブロックが無いのは、グループ公式のAmebaブログという概念自体が存在しないため(個人ブログのみ。詳細は Amebaブログ機能 データ設計書 を参照)
- 各ブロック内のSNSサブセクションの並び順: そのブロックにおける各SNSの最新投稿日時(下表「並び順の算出方法」列を参照)を比較し、新しい投稿があるSNSから順に表示する。SNSサブセクション自体の見出し・グリッド・カードデザインは変更しない
- タイブレーク(同日・比較不能時)のフォールバック順: ブロックごとに固定の順序へフォールバックする(詳細ページの並び順に関する既存知見: 開発ノート「UI/UX設計」#5 に準拠)
- 公式ブロック: YouTube → TikTok → Instagram
- 現役ブロック: Ameba → Instagram
- OGブロック: Ameba → Instagram → TikTok → YouTube
- SNSサブセクション内の個々の投稿の並び順・表示内容は現行のまま変更しない(下表を参照)
| SNS | 新着ありの場合の内容 | 0件時の表示 | 一覧へのリンク | 並び順の算出方法(#1514) | 備考 |
|---|---|---|---|---|---|
| 当日新規取得の投稿(サムネイル/Live) | 「本日の新着投稿はありません」 | /instagram |
対象投稿のcapturedAtの最大値 |
サムネイル正方形グリッド。Reel/Live投稿は専用ラベル表示 | |
| TikTok | 直近の収集日(capturedAt)の投稿 |
「本日の新着投稿はありません」 | /tiktok |
対象投稿のcreatedAt(未設定時はcapturedAt)の最大値 |
サムネイル有効期限切れの投稿はキャプションのみのカードリンクで表示(#1408: 投稿日時基準から収集日時基準に変更)。実投稿日(createdAt)がそのソースの前回同期時刻以前の場合は遡及収集と判定し、実投稿日を併記する(#1502) |
| YouTube | 直近の収集日(capturedAt)の投稿 |
「本日の新着投稿はありません」 | /youtube |
対象動画のpublishedAtの最大値 |
実投稿日(publishedAt)がそのソースの前回同期時刻以前の場合は遡及収集と判定し、実投稿日を併記する(#1502。カード自体への公開日時表示は本対応が初出、詳細は YouTube投稿一覧機能 画面設計書 参照) |
| Ameba | 該当メンバーの、新着ウィンドウ(前々回の定期同期時刻〜直近の同期時刻)内の投稿 | 「本日の新着投稿はありません」 | /ameba |
対象statusHistoryエントリのlastUpdatedの最大値 |
メンバー名+投稿タイトル(statusHistory各エントリのcontent先頭行)のリストで表示。1メンバーが同ウィンドウ内に複数件投稿している場合は全件表示。実投稿日(lastUpdated)が新着ウィンドウ開始時刻(前々回の定期同期時刻)以前の場合は遡及収集と判定し、実投稿日を併記する(#1502)。詳細は Amebaブログ機能 データ設計書 を参照(#1387) |
参照日ヘッダー
- 表示条件: 新着投稿の参照日(当日の新着日時、なければメンバーデータの最終更新日時)が取得できる場合に表示。新着が全SNSで0件の日も、メンバーデータの最終更新日を参照日として表示する
- 日付ラベル:
{参照日の JST 日付} の新着投稿 - 出来事表示: 参照日と月日が一致するメンバーの記念日を表示
| 種別 | 集約単位 | 表示形式 |
|---|---|---|
| 誕生日 | 個別(1人1エントリ) | {name} 誕生日 |
| 加入日 | 同年グループ(同じ年に加入した複数名を1エントリに集約。異なる年は別エントリ) | {name1}・{name2} 加入日 |
| 卒業日 | 同年グループ(同じ年に卒業した複数名を1エントリに集約。異なる年は別エントリ) | {name1}・{name2} 卒業日 |
2. メンバー一覧画面(/members)
概要: 全メンバーのカードを現役・OG に分けて表示する一覧画面。
表示コンテンツ
| 要素 | 内容 |
|---|---|
| 見出し | 「メンバー一覧」 |
| メンバー選択 | 現役・OGをoptgroupで分けたドロップダウン(MemberSelect)。選択すると対象メンバーの詳細画面(/members/{id})に直接遷移する(検索・絞り込みではない) |
| セクションリンク | 「現役メンバー」「OGメンバー」(見出し行の下に横並び、各セクションへのアンカー) |
| 現役メンバーセクション | status === 'Active' のメンバーカード一覧(MemberCard グリッド、人数表示付き) |
| OGメンバーセクション | status === 'OG' のメンバーカード一覧(MemberCard グリッド、人数表示付き) |
MemberCard の表示内容
| 要素 | 内容 |
|---|---|
| 世代バッジ | {generation}期 |
| メンバー名 | 漢字氏名(name)+ルビ(ruby) |
| ステータスバッジ | 現役 または OG |
| SNSステータスバッジ | SNS更新あり・SNS更新なし・SNS取得エラーの状態表示。公式SNS未設定(skipped/unknown)のメンバーは非表示 |
| 更新日時 | {投稿 or 更新}: {YYYY-MM-DD}。公式SNSソースと一致する場合は「投稿」、それ以外は「更新」と表示。公式SNS未設定のメンバーは非表示 |
| SNS確認日時 | SNS確認: {YYYY-MM-DD}(未確認の場合は「未確認」)。公式SNS未設定のメンバーは非表示 |
| カードリンク | クリックで /members/{id} に遷移 |
SNSステータスバッジの状態
| 状態 | 表示色 | 条件 |
|---|---|---|
| SNS更新あり | 緑 | status === 'ok' && hasRecentUpdate === true |
| SNS更新なし | 灰 | status === 'ok' && hasRecentUpdate === false |
| SNS取得エラー | 赤 | status === 'error' |
| (非表示) | — | status === 'skipped' または 'unknown'(公式SNS未設定) |
3. メンバー詳細画面(/members/[id])
概要: 特定メンバーのプロフィール・近況・ディスコグラフィーを表示し、データ編集もできる画面。
動的レンダリング: generateStaticParams() でルートを定義し、リクエスト時に Vercel Blob から最新データを取得する(getMembersFromBlob() が cache: "no-store" でフェッチするため SSR として動作)。
表示コンテンツ
| 要素 | 内容 |
|---|---|
| ナビゲーション | 「メンバー一覧に戻る」+「前のメンバー / 次のメンバー」 |
| プロフィールヘッダ | 氏名・読み・世代バッジ・ステータスバッジ |
| 編集ボタン | デスクトップモード(DESKTOP_MODE=1)のみ表示。「編集」ボタンはプロフィールヘッダ内のステータスバッジの左に配置。クリックで編集モードに切り替え |
| 基本情報 | 生年月日・出身地(設定時のみ表示)・加入日・卒業日・家族構成 |
| 公式 SNS | アクティブな SNS URL のリンク一覧(inactive は打ち消し線表示) |
| ページ内リンク | SNS 投稿部(Ameba投稿/Exa検索結果・Instagram 投稿・TikTok 投稿・YouTube 動画)以下の各セクションへのリンク。SNS 投稿部内のリンク順は各セクションの並び順(後述)に追従する |
| SNS チェック結果 | SNS の最終確認日時・更新状態(snsCheck の値を表示)。公式SNS未設定のメンバーは非表示 |
| Ameba投稿 / Exa検索結果 | 直近30日以内に更新があるときのみ latestStatus.content を表示。情報ソースが1件のときのアンカー化ルール・2件以上のときのURL一覧表示ルールは#1496のまま。直近30日以内の更新が無い場合はバッジに「近況なし」を表示し本文は表示しない。この場合、該当する最新エントリは近況履歴側の「さらに古い履歴を表示」に含める(#1503)。見出しは表示中エントリの sources に応じて「Ameba投稿」「Exa検索結果」のいずれかを動的に表示する(Ameba ブログ記事URLを含む場合は「Ameba投稿」、それ以外は「Exa検索結果」)。SNS 投稿部の一員として並び順制御の対象(後述) |
| 検索注記 | ※Exa検索の結果をを表示していることを注記 |
| 近況履歴 | statusHistory の折りたたみ一覧(最新順)。導線(見出し・開閉トグル)は最新エントリより古い履歴が1件でもあれば常に表示する。開閉時のデフォルト表示は直近30日以内のエントリ。30日を超える履歴(最大100件)は「さらに古い履歴を表示」操作で追加表示できる(#1503)。見出しは「Ameba投稿/Exa検索結果」見出しより一段下位の視覚的階層で表示し、その下位区分であることを示す(#1615) |
| Instagram 投稿 | 最新12件の投稿グリッド(3カラム)。officialSns に Instagram URL が未登録または active: false のメンバーはセクション非表示。SNS 投稿部の一員として並び順制御の対象(詳細は Instagram 投稿セクション参照) |
| TikTok 投稿 | 現役メンバーは公式チャンネル動画でのタグ付け、OGメンバーは自身のTikTokチャンネル投稿が対象のグリッド表示。マッチが0件の場合はセクション非表示。SNS 投稿部の一員として並び順制御の対象(詳細は TikTok 投稿セクション参照、#1513) |
| YouTube 動画 | 公式チャンネル動画のうち、タイトルにメンバーのフルネームが含まれる動画のグリッド表示。マッチが0件の場合はセクション非表示。SNS 投稿部の一員として並び順制御の対象(詳細は YouTube 動画セクション参照) |
| 所属ユニット | このメンバーが所属するユニット一覧(詳細は unit-screen-design.mdx §5.1) |
| 関連リリース | 在籍期間に紐づくモーニング娘。リリース一覧(サブユニット専用リリースを除く。リリース詳細へのリンク) |
| 選曲した楽曲 | プレイリスト掲載情報の抜粋表示(プレイリスト一覧リンクをラベル直下に配置) |
| 関連ライブ | 出演した公演の一覧(詳細は live-screen-design.mdx §12.1「関連ライブセクション」) |
| イベント一覧 | 手動登録イベント(source='manual'。音楽番組・バラエティ等への単発出演を含む)のうち本人が関連するものの一覧(詳細は イベント詳細画面 設計書 §3。実装Issue: MorningStatusApp#1583) |
備考: データ型名(Member.latestStatus/statusHistory、StatusEntry)は「Ameba」等の個別SNS名を冠さない汎用名のままとしている。Amebaブログを開設していない・SNSで自ら発信しないOGメンバーも同じ仕組み(Exa検索によるWeb上の言及収集)で近況を表現する必要があり、データ構造をAmeba固有の名称にできないため(#1513)。表示側の見出し(「Ameba投稿」/「Exa検索結果」)はエントリごとの実際の情報源に応じて動的に決まる。
SNS 投稿部の並び順(#1513)
「Ameba投稿/Exa検索結果」「Instagram 投稿」「TikTok 投稿」「YouTube 動画」の4セクションは固定順ではなく、各セクションの最新日時を比較し新しい順に並べる。投稿が0件のセクションは従来通り非表示(並び順の計算対象から除外)。ページ内リンクも同じ順序に追従する。
| セクション | 日時の算出方法 |
|---|---|
| Ameba投稿 / Exa検索結果 | statusHistory?.[0]?.lastUpdated ?? latestStatus.lastUpdated |
| Instagram 投稿 | 対象投稿の capturedAt の最大値 |
| TikTok 投稿 | 対象投稿の createdAt(未設定時は capturedAt)の最大値 |
| YouTube 動画 | 対象動画の publishedAt の最大値 |
同日・比較不能などのタイブレーク時は、固定順「Ameba投稿/Exa検索結果 → Instagram 投稿 → TikTok 投稿 → YouTube 動画」にフォールバックする(詳細ページの並び順に関する既存知見: 開発ノート「UI/UX設計」#5 に準拠)。
区切り線(#1615): 各セクションの先頭には区切り線(<hr>)を1本表示する。区切り線は並び替え対象の各セクション自身が描画する責務を持ち、MemberDetailView側に共通の区切り線を重ねて持たない。並び替えにより先頭に来るセクションが変わるため、区切り線をコンテナ側と特定セクション側の両方に置くと、そのセクションが先頭に来たときだけ区切り線が二重表示になってしまうため。
備考: 旧実装ではAmeba投稿/Exa検索結果セクションのみ自前の先頭区切り線を持たず、コンテナ側の共通区切り線に依存する作りだった(元々このセクションが常に先頭という前提で書かれたため)。#1513で並び替えが導入された後、Instagram/TikTok/YouTubeのいずれかが並び替えで先頭に来ると、自前の区切り線とコンテナ側の共通区切り線が連続して二重表示される不具合があった(#1615で修正)。
これらのセクションより後ろに続く所属ユニット・関連リリース・選曲した楽曲・関連ライブの各セクションは、この並び替えの対象外で従来通りの固定順のまま。
編集モード
| 要素 | 内容 |
|---|---|
| 近況テキスト入力 | latestStatus.content の編集(required バリデーション) |
| 情報ソース入力 | latestStatus.sources の URL 追加・削除 |
| YouTubeチャンネル名入力 | youtubeChannel.handle(@〜 形式・空欄可)の編集。保存時にサーバー側が YouTube Data API でプレイリストIDに変換する(#1105) |
| 保存ボタン | PUT /api/members で Vercel Blob に保存し statusHistory へ蓄積 |
| キャンセルボタン | 編集内容を破棄して表示モードに戻る |
前/次ナビゲーション順序: 世代・加入日昇順でソートしたメンバーリストの前後インデックス。
Ameba投稿 / Exa検索結果セクション(#1513)
- 表示条件: 常に表示する。
latestStatusは全メンバーが必須で持つデータのため、Instagram/TikTok/YouTube投稿セクションのような「対象0件ならセクション非表示」の概念はない。ただし直近30日以内の更新が無い場合は本文を表示せず「近況なし」バッジのみ表示する(#1503) - 表示位置: SNS 投稿部内。他の3セクションとの並び順は前述「SNS 投稿部の並び順」を参照(固定位置ではない)
- データソース:
member.statusHistory(未設定時はmember.latestStatus) - 見出し判定ロジック: 表示中エントリの
sourcesに、本人がofficialSnsへ公式登録しているAmebaブログのURLと一致するURL(hasOfficialSnsSourceMatchで判定)が含まれる場合は「Ameba投稿」、それ以外(Instagram Blob由来・他SNSドメイン限定Exa検索由来・一般Web検索Exa由来を含む)は「Exa検索結果」を見出しに表示する(#1513、判定ロジックはMorningStatusApp#1628で修正)- 備考: 旧実装(#1513当初〜#1628修正前)は
sourcesのURLが単にameblo.jpドメインかどうか(extractAmebaIdで判定)だけを見ており、投稿者本人のブログかどうかを検証していなかった。公式Amebaブログを登録していないメンバーが一般Web検索(Exaのドメイン制限なし検索)で近況を収集した際、検索結果にたまたま他人のameblo.jp URLが混ざると「Ameba投稿」と誤表示される不具合があった(MorningStatusApp#1628)
- 備考: 旧実装(#1513当初〜#1628修正前)は
| 要素 | 内容 |
|---|---|
| 日付バッジ | 直近30日以内に更新があればYYYY/MM/DD 投稿またはYYYY/MM/DD 更新(officialSnsとのURL一致有無で文言切替)、無ければ「近況なし」 |
| 検索注記 | officialSnsが0件のメンバーのみ「※Exa検索の結果をもとに表示しています」を表示 |
| 本文 | contentをMarkdownレンダリング。情報ソースが1件のときは本文全体をそのURLへのアンカーにする。2件以上のときは本文下に情報ソース一覧(URLリンク)を表示(#1496) |
| 空データ時 | 直近30日以内の更新が無い場合、本文の代わりに「直近30日以内の近況はありません。近況履歴から過去の投稿を確認できます。」を表示(#1503) |
Instagram 投稿セクション
- 表示条件:
officialSnsにinstagram.comを含むactive: trueの URL が登録されているメンバーのみ表示。条件を満たさない場合はセクション自体を非表示にする - 表示位置: SNS 投稿部内。他の3セクションとの並び順は前述「SNS 投稿部の並び順」を参照(#1513、固定位置ではない)
- データソース: Vercel Blob の
instagram/{memberId}/posts.json(InstagramPost[]型) - 表示件数: 最新12件(
capturedAt降順) - レイアウト: 3カラムグリッド
| 要素 | 内容 |
|---|---|
| 投稿画像 | imageBlobUrl(レガシー)または thumbnailUrl(外部参照)の正方形画像(アスペクト比 1:1)。imageBlobUrl を優先し、なければ thumbnailUrl を使用する |
| Reelラベル | isReel: true の投稿は画像左下に「Reel」ラベルを表示する |
| キャプション | ホバー時に画像上にオーバーレイ表示(caption が空文字の場合は非表示) |
| クリック動作 | postUrl(元の Instagram 投稿 URL)を新しいタブで開く |
| 画像エラー時 | 投稿削除済等で画像ロード失敗した場合はグレーのプレースホルダーを表示 |
- データ未取得時: Instagram URL は登録されているが Blob に
posts.jsonが存在しない場合は「まだ投稿データが取得されていません」を表示する(セクションは表示する)
TikTok 投稿セクション(#1513)
- 表示条件: 対象投稿が1件以上ある場合のみ表示する。対象は「公式チャンネル動画でのタグ付け(
mentionedMemberIdsに一致、主に現役メンバー)」または「自身のTikTokチャンネル投稿(channelType === 'og'かつmemberId一致、OGメンバー)」のいずれか。現役メンバーは前者、OGメンバーは後者が中心となる(TikTokは現役メンバー自身のチャンネルを収集していないため) - 表示位置: SNS 投稿部内。他の3セクションとの並び順は前述「SNS 投稿部の並び順」を参照(固定位置ではない)
- データソース: Neon
tiktok_posts(getTikTokPosts()) - 表示件数: 上限なし(対象条件に一致した全件、
createdAt降順) - レイアウト: グリッド(
auto-fill, minmax(140px, 1fr))
| 要素 | 内容 |
|---|---|
| 投稿画像 | imageBlobUrl を優先し、なければ thumbnailUrl を使用する正方形カード。サムネイルが無効な場合はキャプション(無ければ取得日時)のみのテキストカードに切り替える |
| スライドショー表示 | isSlideshow: true(またはサムネイルURLからの判定)の投稿は「Slide」ラベルを表示する |
| クリック動作 | postUrl(元の TikTok 投稿 URL)を新しいタブで開く |
- 参考表示に関する注記: 画像はあくまで参考表示であり権利は投稿者に帰属する旨、および参考表示の有効期限切れ時はリンクのみの表示になる旨を注記する
YouTube 動画セクション(#9)
- 表示条件: 公式チャンネル動画のタイトルにメンバーのフルネームが一致する動画が1件以上ある場合のみ表示する。
officialSnsの登録有無やメンバー自身のYouTubeチャンネル登録有無は問わない(言及ベースの表示のため)。現役・OGを問わず公式チャンネル動画への言及のみが対象で、OGメンバー自身のYouTubeチャンネル(channelType: 'og')の投稿はメンバー詳細画面には表示されない(TikTok投稿セクションと異なる点。ホーム画面の新着投稿セクションではOGメンバー個人チャンネルの動画も収集対象だが、メンバー詳細画面への導線はない。#1513時点では現状維持) - 表示位置: SNS 投稿部内。他の3セクションとの並び順は前述「SNS 投稿部の並び順」を参照(固定位置ではない)
- データソース: Neon
youtube_posts(channelType = 'official')をgetAllOfficialYoutubePosts()で取得し、attributeYoutubeVideoToMembers()でフィルタする(詳細は youtube-data-design.md §6.1) - 表示件数: 上限なし(マッチした全件)
- レイアウト: グリッド(TikTok投稿セクションと同様のパターン)
| 要素 | 内容 |
|---|---|
| サムネイル | https://i.ytimg.com/vi/{videoId}/hqdefault.jpg(16:9) |
| タイトル | 動画タイトル(2行 clamp) |
| クリック動作 | https://www.youtube.com/watch?v={videoId} を新しいタブで開く |
- 判定結果の保存: DBには保存せず、表示のたびに都度計算する(詳細は youtube-data-design.md §6.1)
4. リリース一覧画面(/releases)
概要: モーニング娘。(年号付き含む)のディスコグラフィーをフォーマット別(シングル・アルバム・EP・その他)に分けて表示する画面。サブユニット専用リリース(タンポポ・ミニモニ。・W 等の Unit.releaseIds に含まれるもの)は除外する。
表示コンテンツ
| 要素 | 内容 |
|---|---|
| アンカーナビゲーション | 存在するフォーマット(single / album / ep / live / soundtrack / compilation / other)へのリンク。各リンクの先頭に ReleaseBadge を表示 |
| フォーマット別セクション | リリース日降順のリリースタイトル一覧(リリース詳細へのリンク) |
| データなし表示 | リリースデータが空の場合は「同期ジョブ実行後に表示」メッセージ |
フォーマットラベル(ReleaseBadge)
| フォーマット | ラベル | バッジ色 |
|---|---|---|
| single | シングル | 青 (#2563eb) |
| album | アルバム | 緑 (#16a34a) |
| ep | EP | 紫 (#7c3aed) |
| live | ライブアルバム | オレンジ (#ea580c) |
| soundtrack | サウンドトラック | 黄 (#ca8a04) |
| compilation | コンピレーション | シアン (#0891b2) |
| other | その他 | グレー (#6b7280) |
5. リリース詳細画面(/releases/[id])
概要: 特定リリースの詳細情報とメンバーを表示する画面。
表示コンテンツ
| 要素 | 内容 |
|---|---|
| 前後ナビゲーション | 「前の画面に戻る」(BackLink によりブラウザ履歴がある場合は router.back()、なければ /releases にフォールバック)+ 「← 前のリリース / 次のリリース →」(同フォーマット内でリリース日降順・同日はタイトル昇順) |
| フォーマットバッジ | FORMAT_LABEL[format] のラベル |
| タイトル | リリースタイトル |
| ユニット名 | releaseIds に当該リリース ID を含むユニット名(ユニット詳細へのリンク)。詳細は unit-screen-design.mdx §5.2 |
| リリース日 | YYYY-MM-DD 形式(不明の場合は「日付不明」) |
| ソース URL | MusicBrainz 等の情報ソースリンク(有効 URL のみ表示) |
| YouTube MV | links に youtube タイプのエントリが設定されている場合のみ表示。新しいタブで YouTube を開くリンクボタン(#348, #425) |
| 収録曲一覧 | トラックリスト(#339 完了後に表示。未取得時は非表示) |
| メンバー | 在籍期間が重なるメンバー一覧(メンバー詳細へのリンク) |
収録曲一覧セクション
- 配置場所: ソース URL とメンバーの間に配置する
- 表示項目:
| 項目 | 内容 |
|---|---|
| トラック番号 | Track.trackNumber(ディスク内での連番) |
| 曲名 | Track.title |
| 再生時間 | Track.length をミリ秒から M:SS 形式に変換して表示。未登録の場合は非表示 |
- ゼロ件時:
tracksフィールドが存在しない、または空配列の場合はセクション自体を非表示にする(「収録曲なし」等のメッセージは表示しない) - マルチディスク構成:
Track.discNumberが複数値を持つ場合は、ディスク番号ごとにグループ化して見出し(「Disc 1」「Disc 2」等)を表示する。全曲が同一ディスクの場合はグループ見出しを省略する - ソート順:
discNumber ASC, trackNumber ASC(discNumberが省略された場合は1として扱う)
6. 曲詳細画面(/songs/[id])
概要: 特定楽曲(recording)の詳細情報・収録リリース・外部リンク・プレイリスト掲載情報を表示する画面。
URL パラメータ: [id] = Track.id(MusicBrainz recording UUID)
データソース: Neon DB(releases / tracks テーブル)を全走査し、Track.id が一致するトラックを特定する。同一 recording UUID は複数リリースに存在し得る(例: シングル収録後にアルバムにも収録)。
動的レンダリング: force-dynamic で Neon DB から最新データを取得する(getMembersFromBlob() / getReleases() を使用)。
表示コンテンツ
| 要素 | 内容 |
|---|---|
| ナビゲーション | 「前の画面に戻る」(ブラウザ履歴を1つ戻る。リリース詳細・ユニット詳細・プレイリスト詳細のどちらから遷移しても対応。直接アクセス時のフォールバック: リリース詳細) |
| 曲タイトル | Track.title |
| 再生時間 | Track.length をミリ秒から M:SS 形式に変換して表示。未登録の場合は非表示 |
| アーティスト | 再生時間の右にユニット名をリンク表示。トラックの releaseId をキーに units.json を逆引きして特定(#538 で実装。詳細は unit-screen-design.mdx §5.3) |
| 動画(MV / YouTube Shorts) | Track.links に youtube または youtube-short タイプが存在する場合、アーティストの直下に VideoSelector でインライン iframe(16:9)表示。MV のみの場合はそのまま埋め込み、Shorts も存在する場合はドロップダウンで切り替え可能(#452, #774, #828) |
| YouTube リンク編集 | デスクトップモード(DESKTOP_MODE=1)のみ表示。現在の YouTube URL を確認・削除・URL 変更できる(#696)。DELETE /api/tracks/[id]/youtube-link / PUT /api/tracks/[id]/youtube-link を使用。更新・削除成功後、revalidateTag('releases', 'max') でデスクトップアプリ自身のキャッシュを無効化する。さらにデスクトップモードかつ APP_URL/REVALIDATE_TOKEN が設定されている場合、本番Web側のData Cache(getReleases())も POST /api/revalidate 経由で無効化する(revalidateCache、lib/revalidate-cache.ts、#1600) |
| YouTube Shorts 編集 | デスクトップモード(DESKTOP_MODE=1)のみ表示。既存 Shorts リンクの個別削除と「次回バッチで再取得する」チェックボックス(Track.shortsRefetchRequested フラグ)を提供(#824)。DELETE /api/tracks/[id]/youtube-shorts / PATCH /api/tracks/[id]/youtube-shorts を使用 |
| 外部リンクセクション | Track.links の YouTube Music 等リンク(youtube・youtube-short・genius 以外のみ表示) |
| 収録リリース一覧 | この recording を収録しているリリース一覧(/releases/[id] へのリンク。リリース日昇順) |
| 対比候補 | 該当 trackId を持つ対比グループが存在する場合のみ表示(/comparisons/[groupId] へのリンク。詳細は 曲対比機能 データ設計書 §5) |
| プレイリスト掲載情報 | PlaylistEntry.trackId === track.id のプレイリスト一覧(詳細は playlist-screen-design.mdx §5.2) |
収録リリース一覧セクション
| 項目 | 内容 |
|---|---|
| リリースタイトル | Release.title(リリース詳細画面へのリンク) |
| フォーマット | FORMAT_LABEL[release.format] のラベル(バッジ表示) |
| リリース日 | Release.releaseDate(不明の場合は「発売日不明」) |
| トラック情報 | Disc {discNumber} / Track {trackNumber}(マルチディスクの場合のみ Disc 番号を表示) |
- 収録リリースが複数ある場合はリリース日昇順(古い順)で表示する
- 収録リリースが必ず1件以上存在することを前提とする(
Track.idに一致するリリースが見つからない場合はnotFound()を返す)
外部リンクセクション
| リンク種別 | 表示形式 |
|---|---|
| YouTube Music | 「♪ YouTube Music で聴く」ボタン(新しいタブで開く) |
- YouTube MV・YouTube Shorts はインライン表示のためこのセクションには含めない
youtube・youtube-short・genius以外のリンクが存在する場合のみセクションを表示するTrack.linksが空またはフィールド自体が存在しない場合はセクション自体を非表示にする
対比候補セクション
| 項目 | 内容 |
|---|---|
| 対比候補リンク | 対比グループの title(/comparisons/[groupId] へのリンク) |
- 該当
track.idを持つ対比グループが存在する場合のみセクションを表示する - 存在しない場合はセクション自体を非表示にする
プレイリスト掲載情報セクション(#366 完了後に実装)
| 項目 | 内容 |
|---|---|
| プレイリスト名 | プレイリスト詳細画面(/playlists/[id])へのリンク |
| 選曲メンバー | プレイリストを作成したメンバーの名前(メンバー詳細画面へのリンク) |
- このトラックを選曲しているプレイリストが存在しない場合はセクション自体を非表示にする
リリース詳細画面からのリンク仕様
- リリース詳細画面(
/releases/[id])の収録曲一覧に表示される各曲名を、/songs/[Track.id]へのリンクにする Track.idが空文字列の場合はリンクなしでテキストのみ表示する(後方互換)- リンクはインラインリンク(
<Link>)で同一タブ遷移
7. 同期状況画面(/sync-status)
概要: 各種バッチ同期ジョブの最終実行状況・取得進捗をまとめて確認するデスクトップ専用画面。
アクセス制限: デスクトップモードでのみ表示。
データソース
| セクション | データソース |
|---|---|
| 近況同期 | Vercel Blob の members.json(resolveSnsCheck で各メンバーのステータスを集計) |
| Instagram同期 | Vercel Blob の instagram-sync-status.json |
| Genius リンク同期 | Vercel Blob の genius-links-status.json |
| ディスコグラフィー同期 | Vercel Blob の discography-status.json |
表示コンテンツ(共通)
| 要素 | 内容 |
|---|---|
| ナビゲーション | 「← メンバー一覧に戻る」(/ へのリンク) |
| ページタイトル | 「同期状況」 |
近況同期セクション
| 項目 | 内容 |
|---|---|
| 最終バッチ実行 | 全メンバーの snsCheck.lastCheckedAt の最大値を JST 表示(未確認の場合は「未確認」) |
| 成功 | snsCheck.status === 'ok' のメンバー数 |
| エラー | snsCheck.status === 'error' のメンバー数 |
| 未確認 | snsCheck.status === 'unknown' または 'skipped' のメンバー数 |
Instagram同期セクション
データが存在しない場合は「データがありません。Instagram同期を実行後に表示されます。」を表示。
| 項目 | 内容 |
|---|---|
| 最終同期 | instagramSyncStatus.lastSyncedAt を JST 表示 |
| セッション状態 | sessionStatus === 'valid' → 「有効」(緑)、それ以外 → 「失効」(赤) |
| メンバー取得率 | capturedMembersCount / totalTargetMembersCount * 100(%表示)+ N / M 人表示 + プログレスバー |
Genius リンク同期セクション
データが存在しない場合は「データがありません。Genius リンク同期を実行後に表示されます。」を表示。
| 項目 | 内容 |
|---|---|
| 最終同期 | geniusLinksStatus.lastSyncedAt を JST 表示 |
| 最新状況 | 最新スナップショットの取得率(%)・取得済 / 対象曲数・残り曲数・プログレスバー |
| 棒グラフ | GeniusLinksStatusChart(履歴 1 件以上の場合に表示)。過去 N 日分の取得済 / 未取得をスタック棒グラフで表示 |
ディスコグラフィー同期セクション
データが存在しない場合は「データがありません。ディスコグラフィー同期を実行後に表示されます。」を表示。
| 項目 | 内容 |
|---|---|
| 最終同期 | discographyStatus.lastSyncedAt を JST 表示 |
| YouTube リンク取得率 | youtubeFetchedTracks / youtubeTargetTracks * 100(%表示)・N / M 曲・リリース N 件・プログレスバー |
| Shorts リンク取得率 | shortsFetchedTracks / shortsTargetTracks * 100(%表示)・N / M 曲・残り N 曲・プログレスバー。shortsTargetTracks が undefined の場合は非表示 |
| 棒グラフ | DiscographyStatusChart(履歴 1 件以上の場合に表示)。過去 N 日分の YouTube 取得済 / 未取得(緑)をスタック棒グラフで表示。shortsTargetTracks を持つ履歴が存在する場合は Shorts 取得済 / 未取得(ピンク)の系列を並列表示(#832) |
DiscographyStatusChart 仕様
| 系列名 | 色 | stackId | 条件 |
|---|---|---|---|
| 取得済 | #4ade80(緑) |
youtube |
常時 |
| 未取得 | rgba(255,255,255,0.2) |
youtube |
常時 |
| Shorts取得済 | #f472b6(ピンク) |
shorts |
履歴に shortsTargetTracks が存在する場合のみ |
| Shorts未取得 | rgba(255,255,255,0.15) |
shorts |
履歴に shortsTargetTracks が存在する場合のみ |
- Shorts 系列が表示される場合、棒の幅は 24px に縮小(非表示時は 40px)
- チャート上部の説明文: Shorts 系列あり → “YouTube / Shorts 取得進捗(過去 N 日分)”、なし → “YouTube リンク取得進捗(過去 N 日分)”(#836)
8. 楽曲リンク修正画面(/link-editor)
概要: シングル曲トラックの TikTok・YouTube・Genius リンクを手動で確認・編集するデスクトップ専用画面。
アクセス制限: デスクトップモードでのみ表示。
データソース
| セクション | データソース |
|---|---|
| トラック選択肢 | Release(format: 'single'、releaseDate 降順)+ 各リリースの Track(Prisma、trackNumber 昇順) |
| リンク済URL | TrackLink(type が tiktok / youtube / genius) |
| TikTok候補投稿 | TikTokPost(トラックタイトルのトークンマッチ、またはリンク済URL) |
表示コンテンツ(共通)
| 要素 | 内容 |
|---|---|
| ナビゲーション | 「← トップ」(/ へのリンク) |
| ページタイトル | 「楽曲リンク修正」 |
| トラック選択 | シングル曲トラックのセレクトボックス(リリースタイトル — 曲タイトル 形式) |
| サービスタブ | TikTok / YouTube / Genius の3タブ切り替え |
トラック選択肢の絞り込み(isVersionTrack)
Instrumental・カラオケ等のバージョン違い楽曲を選択肢から除外する。以下のいずれかに該当するトラックは対象外:
- タイトル末尾が角括弧(
< >/< >)で終わる - タイトル末尾の丸括弧(
( )/( ))内に既知のバージョンキーワード(instrumental/off vocal/インスト/カラオケ/tv mix等)を含む
TikTokタブ
| 項目 | 内容 |
|---|---|
| 候補投稿の抽出 | 選択中トラックのタイトルをトークン分解(tokenizeTitle。バージョン表記除去 → 記号区切りで分割 → 2文字以上のトークンのみ)し、TikTokPost.caption にいずれかのトークンを含む投稿を候補として抽出。このトラックに既にリンク済の投稿はトークン不一致でも必ず候補に含める |
| キーワード追加検索 | 検索欄にキーワードを入力すると caption の部分一致(大小文字を区別しない)で追加検索し、既存候補にマージ(重複除去) |
| リンク済/未リンクの表示分け | 「リンク済(N件)」「未リンク(N件)」の2セクションに分け、チェックボックス一覧で表示 |
| 他トラックへのリンク除外 | 他のトラックに既にリンク済(DB上)の投稿URLは「未リンク」候補から除外する(1投稿は1トラックにのみリンクする前提) |
| キャプション表示 | 80文字を超える場合は末尾を … で省略表示 |
YouTube/Geniusタブ
| 項目 | 内容 |
|---|---|
| リンク一覧 | リンク済URLをチェックボックス一覧表示(チェックを外すと削除対象になる) |
| URL追加 | 入力欄にURLを入力し「追加」ボタンまたは Enter キーで一覧に追加(保存前はクライアント側の状態のみ) |
保存
- 追加・削除いずれかの変更がある場合のみ「保存」ボタンが活性化する
PATCH /api/link-editorに{ trackId, type, addUrls, removeUrls }を送信し、TrackLinkを差分更新する(removeUrlsをdeleteManyした後、addUrlsをcreate)- 更新成功後、
revalidateTag('releases', 'max')でデスクトップアプリ自身のキャッシュを無効化する。さらにデスクトップモードかつAPP_URL/REVALIDATE_TOKENが設定されている場合、本番Web側のData Cache(getReleases())もPOST /api/revalidate経由で無効化する(revalidateCache、lib/revalidate-cache.ts、#1600) - 保存成功後は
router.refresh()でサーバー側データを再取得する - TikTok / YouTube / Genius の各タブは独立した保存状態(
idle/saving/success/error)を持つ
API エンドポイント
| メソッド | パス | 概要 |
|---|---|---|
| GET | /api/members |
Vercel Blob から全メンバーデータを JSON で返す |
| PUT | /api/members |
メンバーデータを更新し Vercel Blob に保存する |
アクセス制限: PUT はデスクトップモード(DESKTOP_MODE=1)でのみ許可し、それ以外は403を返す。
備考: 従来はサーバー側のアクセス制限が無く、編集ボタンの非表示(クライアント側の表示制御)のみに依存していた。本番Web環境に対して直接 PUT リクエストを送るとメンバーデータを書き換えられる状態だったため、他の編集系API(PATCH /api/link-editor・PUT/DELETE /api/tracks/[id]/youtube-link等)と同様の requireDesktopMode() ガードを追加した(MorningStatusApp#1603)。
PUT リクエストボディ
{
"id": "string",
"latestStatus": {
"content": "string",
"lastUpdated": "YYYY-MM-DD",
"sources": ["url"]
}
}
PUT 成功時: statusHistory に新エントリを蓄積(最大 100 件)、revalidatePath でデスクトップアプリ自身のキャッシュを無効化する。さらにデスクトップモード(DESKTOP_MODE=1)かつ APP_URL/REVALIDATE_TOKEN が設定されている場合、本番Web側のData Cacheも POST /api/revalidate 経由で無効化する(revalidateCache、lib/revalidate-cache.ts、#1600)。
備考: 従来は revalidatePath のみを呼んでおり、これはデスクトップアプリ自身の standalone サーバープロセスのキャッシュしか無効化しなかった。本番Webは別プロセス・別デプロイで独立したData Cache(getMembersFromBlob() の fetch(..., { next: { revalidate: 3600 } }))を持つため、デスクトップで編集・保存しても本番Webには最大1時間古いデータが表示され続ける不具合があった(#1600)。
youtubeChannel の解決(#1105): youtubeChannel.handle が空・未指定の場合はフィールドを削除、既存と同一の場合は解決済 playlistId を引き継ぎ(API 呼び出しなし)、新規・変更時は YouTube Data API(fetchPlaylistId)でプレイリストIDに変換して保存する。変換できない場合は 422 を返し保存を中断する。
改訂履歴
| 版 | 更新日 | 変更内容 |
|---|---|---|
| 3.34 | 2026-09-22 | 対比機能の再構築(Neon DB化)に伴い、曲詳細画面の対比候補セクションの説明をtrackComparisonMap(Vercel Blob)参照から対比グループ(ComparisonGroup、Neon DB)参照に更新。リンク先パラメータ名をpairIdからgroupIdに変更(MorningStatusApp#1633, morning-status-blume#148) |
| 3.33 | 2026-09-22 | 【対応する実装: 実装時に追記(MorningStatusApp#1545)】Topページの過去のこの日セクションに、フェスの出来事にも会場名とフェスの代表時刻(00:00・未設定は非表示)を併記する仕様を追加。あわせて、これまで記載のなかったライブ出来事の会場名の併記を明記(MorningStatusApp#1545) |
| 3.32 | 2026-09-21 | 画面一覧の世代マトリックス画面の導入バージョンを v10.6.0 とし、「設計のみ先行」の注記を削除(実装済のため。MorningStatusApp#1632、morning-status-blume#141) |
| 3.31 | 2026-09-20 | 世代マトリックス画面(/generational-matrix)を画面一覧・機能別詳細設計書リンクに追加。シークレットモード限定・ナビゲーションからリンクしない隠しルートのため画面遷移図には追加しない(唯一の遷移経路はTopページの隠しジェスチャーで、可視のリンク・矢印を伴わないため)。Topページのタイトル要素がこのジェスチャーの入力対象を兼ねる旨を§1に備考として追加。詳細設計は新設の世代マトリックス 画面設計書に分離(設計のみ先行、実装はMorningStatusApp#1632、morning-status-blume#128) |
| 3.30 | 2026-09-16 | §3メンバー詳細画面「Ameba投稿 / Exa検索結果セクション」の見出し判定ロジックを修正。ameblo.jpドメインのURLかどうかだけで判定していたため、公式Amebaブログ未登録のメンバーで一般Web検索結果に他人のameblo.jp URLが混ざると「Ameba投稿」と誤表示される不具合を修正し、本人の公式登録ブログURLとの一致を検証するよう変更(MorningStatusApp#1628) |
| 3.29 | 2026-09-13 | §3メンバー詳細画面のSNS投稿部について、区切り線はセクション自身が描画する責務であることを明記(旧実装はAmeba投稿/Exa検索結果セクションのみ区切り線を持たずコンテナ側に依存しており、並び替えで他セクションが先頭に来ると区切り線が二重表示される不具合があった)。近況履歴の見出しをAmeba投稿より一段下位の視覚的階層で表示する仕様を追加(MorningStatusApp#1615) |
| 3.28 | 2026-09-10 | 平均年齢の変遷画面(/average-age)を画面一覧・Topページナビゲーションリンク・TOP画面内遷移図に追加。詳細設計は新設の平均年齢の変遷グラフ画面 設計書に分離(実装Issue: MorningStatusApp#1595) |
| 3.27 | 2026-09-07 | §3メンバー詳細画面「編集ボタン」・APIエンドポイント節PUT /api/membersに「デスクトップモード限定」の記載を追加。PUT /api/membersにサーバー側のアクセス制限が無く、本番Web環境に直接リクエストを送るとメンバーデータを書き換えられた不具合の修正に伴う仕様明確化(MorningStatusApp#1603) |
| 3.26 | 2026-09-07 | APIエンドポイント節PUT /api/members・§8楽曲リンク修正PATCH /api/link-editor・§6曲詳細画面「YouTube リンク編集」PUT/DELETE /api/tracks/[id]/youtube-linkのキャッシュ無効化説明を修正。デスクトップモードの保存操作が本番Web側のData Cacheを無効化していなかった不具合(デスクトップ自身のプロセスにしか効かないrevalidatePath/revalidateTagのみ呼んでいたため)の修正に伴う仕様明確化(MorningStatusApp#1600) |
| 3.25 | 2026-09-03 | 外部遷移図(タイムライン・年表・関係性マップ系列)の「イベント詳細」ノードについて、「タイムラインに戻る」固定エッジを削除し、タイムラインからの新規導線(イベントカードクリック)と、遷移元別の「前の画面に戻る」エッジ2本に置き換え。詳細設計はイベント詳細画面 設計書を参照(blume#101。MorningStatusApp#1583実装中に発覚した設計不備の修正) |
| 3.24 | 2026-09-01 | イベント詳細画面(/events/[id]。source='manual'のイベントが対象)を画面一覧・外部遷移図に追加。§2メンバー詳細の表示コンテンツに「イベント一覧」セクションを追加。詳細設計は新設のイベント詳細画面 設計書に分離(blume#97。実装Issue: MorningStatusApp#1583) |
| 3.23 | 2026-08-25 | §7・§8の「アクセス制限」表現を「デスクトップモードでのみ」に統一(環境変数一覧の用語定義に合わせ、notFound()等の実現方法の記述は削除)(#1521) |
| 3.22 | 2026-08-22 | 過去のこの日セクションのライブ出来事について、時刻00:00以外の場合のみ表示する仕様を明記。実装が独自の時刻フォーマット処理を持ち、この要件(ライブ・フェス機能の公演リスト表示項目と共通)を満たしていなかった不具合の修正に伴う仕様明確化(#1531) |
| 3.21 | 2026-08-20 | ラジオオンエア データ設計書へのリンクテキストをタイトル変更(「ラジオオンエア収集 設計書」→「ラジオオンエア データ設計書」)に追随して更新(#1523) |
| 3.20 | 2026-08-17 | §2 メンバー詳細のSNS投稿部(Ameba投稿/Exa検索結果・Instagram・TikTok・YouTube)を固定順から各セクション最新日時順に変更する設計を追加。抜けていたTikTok投稿セクションの記載も補完(#1513) |
| 3.19 | 2026-08-15 | §2 メンバー詳細の近況履歴セクションを、直近30日以内の履歴が0件でも導線を表示し、古い履歴(最大100件)を展開表示できるよう改修。あわせて最新の近況も直近30日以内の更新が無い場合は「近況なし」を表示するよう変更(#1503) |
| 3.18 | 2026-08-15 | §1 新着投稿セクションのTikTok・YouTube・Ameba行に、遡及収集(実投稿日がソースの前回同期時刻以前)と判定された投稿の実投稿日併記仕様を追記(#1502) |
| 3.17 | 2026-08-14 | §2 メンバー詳細「最新の近況」「近況履歴」の表示仕様を変更。情報ソースが1件(ブログ投稿)のときは本文をアンカー化し生URL表示を省略、2件以上(Exa検索結果)は従来通りURL一覧を表示(#1496) |
| 3.16 | 2026-07-29 | §2 メンバー詳細に YouTube 動画セクション(公式チャンネル動画のフルネーム一致によるメンバー判定)の設計を追加(#9) |
| 3.15 | 2026-07-24 | §1 新着投稿セクションのTikTok・YouTubeの新着判定基準を投稿日時から収集日時(capturedAt)に変更。収集が遅延した投稿が投稿日時基準では新着ウィンドウから漏れる不具合を修正(#1408) |
| 3.14 | 2026-07-24 | §1 新着投稿セクションの表示条件を変更。各SNSの一覧画面へのリンクを新着0件でも常時表示し、0件時は「本日の新着投稿はありません」を表示するよう修正(#1404) |
| 3.13 | 2026-07-22 | §2 メンバー詳細 Instagram投稿セクションにReelラベルの表示仕様を追記(#1373) |
| 3.12 | 2026-07-22 | /link-editor 画面を画面一覧・画面遷移図に追加(除外対象から解除)、§8 楽曲リンク修正画面の設計を新規追加(#1368) |
| 3.11 | 2026-07-20 | §1 新着投稿セクションのAmeba表示条件を、当日の暦日一致から新着ウィンドウ(前々回の定期同期時刻〜直近の同期時刻)判定に変更。1メンバー複数件表示に対応(#1387) |
| 3.10 | 2026-07-19 | /ameba 画面を画面一覧・画面遷移図に追加(除外対象から解除)。機能別詳細設計書に Amebaブログ機能 を追加(#1367) |
| 3.9 | 2026-06-23 | §1 新着投稿セクション参照日ヘッダーの出来事表示仕様を追加(加入日・卒業日は同年グループで集約、異なる年は別エントリ)(#1216) |
| 3.8 | 2026-06-22 | メンバー詳細画面の近況履歴セクションの表示件数を明記(直近30日以内 かつ 100件以内(早い方を適用))(#1206) |
| 3.7 | 2026-06-12 | §2 編集モードに YouTubeチャンネル名入力を追加、API エンドポイントに youtubeChannel 解決仕様を追記(#1105) |
| 3.6 | 2026-06-12 | 画面一覧に YouTube 関連3画面を追加、詳細設計書リンクを箇条書きに整理し youtube-screen-design.mdx を追加(#1106) |
| 3.5 | 2026-05-08 | §6 DiscographyStatusChart の説明文切り替え仕様を追記(#836) |
| 3.4 | 2026-05-07 | §6 同期状況画面の設計を新規追加。DiscographyStatusChart に Shorts 系列追加仕様を記載(#832) |
| 3.3 | 2026-05-06 | §5 曲詳細画面の動画セレクターをボタンからドロップダウンに変更(#828) |
| 3.2 | 2026-05-06 | §5 曲詳細画面に YouTube Shorts 編集セクションを追加(個別削除・再取得フラグ)(#824) |
| 3.1 | 2026-05-06 | §5 曲詳細画面の YouTube MV 行を動画セレクター(MV / Shorts 切り替え)に更新し、外部リンクセクションの除外条件に youtube-short を追加(#774) |
| 3.0 | 2026-05-01 | §1 新着Instagram投稿セクションのタイトルを capturedAt JST 日付に動的変更(フォールバック: 「本日の」)(#733) |
| 2.9 | 2026-04-30 | §1 トップ画面に新着Instagram投稿セクションを追加、§2 メンバー詳細の投稿画像ソース記述を更新(thumbnailUrl 対応)(#721, #751, #754) |
| 2.8 | 2026-04-26 | §2 メンバー詳細に Instagram 投稿セクションを追加(#716) |
| 2.7 | 2026-04-11 | §2 メンバー詳細のセクション順を「所属ユニット→関連リリース→選曲した楽曲→関連ライブ」に変更(#523) |
| 2.6 | 2026-04-11 | 画面一覧・遷移図にライブ関連4画面を追加、live-screen-design.mdx への参照を追加(#523) |
| 2.5 | 2026-04-05 | §1 一覧ページリンクに「ユニット一覧」を追加(#576) |
| 2.4 | 2026-04-05 | §4 収録ユニットセクション行を削除・「関連メンバー」→「メンバー」に訂正(Figmaデザインと同期) |
| 2.3 | 2026-04-04 | §2 編集ボタンの位置明記・SNSチェック結果追加・近況→最新の近況・Instagram投稿履歴削除・所属ユニット追加(#567)。§4 ユニット名行追加(#568)。§5 アーティストの配置を再生時間の右と明記・対比候補サブセクション追加(#569) |
| 2.2 | 2026-04-04 | §5 表示コンテンツ表のアーティストと YouTube MV の順序を入れ替え(アーティスト→YouTube MV に統一)(#565) |
| 2.1 | 2026-04-04 | §4 前後ナビ追加・プレイリスト掲載情報削除(#400 反映)・収録ユニット行追加(#563)。§5 アーティスト・対比候補追加、セクション順を実装と整合(#554) |
| 2.0 | 2026-03-30 | 画面一覧・遷移図にユニット一覧・詳細を追加、unit-screen-design.mdx への参照を追加(#533) |
| 1.9 | 2026-03-28 | メンバー詳細画面に Instagram 投稿履歴セクションの設計を追加(#475) |
| 1.8 | 2026-03-28 | 遷移図に曲検索画面への入口矢印を追加、メンバー一覧の一覧ページリンクに対比一覧・曲検索アイコンを追記(#492) |
| 1.7 | 2026-03-28 | 画面一覧・遷移図に曲検索(v1.0.0)・対比一覧・対比詳細(v1.1.0)を追加(#489) |
| 1.6 | 2026-03-27 | メンバー詳細の「選曲した楽曲」セクションのレイアウト調整(プレイリスト一覧リンクの移動) |
| 1.5 | 2026-03-25 | 曲詳細画面の YouTube MV 表示をインライン iframe に変更(#452)、メンバー詳細のソートトグルボタンスタイルをリファクタリング(#454) |
| 1.4 | 2026-03-22 | メンバー一覧のナビゲーション構成変更(プレイリスト一覧リンク追加・配置調整)、曲詳細の戻るリンクをブラウザ履歴ベースに変更(#393 #394) |
| 1.3 | 2026-03-21 | 画面一覧にプレイリスト一覧・詳細を追加、画面遷移図にプレイリスト関連遷移を追加 |
| 1.2 | 2026-03-19 | 曲詳細画面(/songs/[id])の設計を追加 |
| 1.1 | 2026-03-19 | リリース詳細画面に収録曲一覧・プレイリスト掲載情報セクションを追加 |
| 1.0 | — | 初版作成(メンバー一覧・詳細・リリース一覧・詳細) |