---
title: "ユニット機能 画面設計書"
---

最終更新: 2026-04-04（#567・#568・#569）

## 1. 概要

ユニット機能（#531）で追加・変更される画面の設計。
新規2画面（ユニット一覧・詳細）と、既存4画面（メンバー詳細・リリース詳細・曲詳細・プレイリスト詳細）への追加を定義する。

データ設計については [unit-data-design.md](/design/unit/unit-data-design) を参照。

---

## 2. 画面一覧（ユニット関連）

| 画面名 | URL パターン | レンダリング方式 | 対応 Issue |
| --- | --- | --- | --- |
| ユニット一覧 | `/units` | SSR（動的） | #535 |
| ユニット詳細 | `/units/[id]` | SSR（動的） | #536 |

> 既存画面への追加セクションは §5 を参照。
> `parentId` を持つ各期ユニットは URL を持たない（詳細ページなし）。

---

## 3. ユニット一覧画面（`/units`）

### 概要

全ユニットをカード形式で一覧表示する画面。
`units.json` のデータを Vercel Blob から取得して表示する。

### 表示コンテンツ

| 要素 | 内容 |
| --- | --- |
| ナビゲーション | 「ホームに戻る」リンク（`/` へ） |
| ページタイトル | 「ユニット」 |
| ユニット数 | 一覧表示ユニット件数（例: `15件`）。各期ユニット（`parentId` あり）は件数に含めない |
| ユニットカード一覧 | 後述のルールに従って表示 |

### 表示対象と並び順

`parentId` を持つ各期ユニットは一覧に表示しない。表示対象は以下の2種のみ:

| 種別 | 条件 | 並び順 |
| --- | --- | --- |
| 上位ユニット | `parentId` なし・かつ子ユニット（`parentId` が自身の `id` を指すエントリ）が存在する | `activeFrom` 降順（新しい順） |
| 単独ユニット | `parentId` なし・かつ子ユニットが存在しない | `activeFrom` 降順（新しい順） |

### ユニットカードの表示項目

| 項目 | 内容 |
| --- | --- |
| ユニット名 | `Unit.name`（ユニット詳細画面へのリンク） |
| 活動期間 | `activeFrom` ～ `activeTo`。`activeTo` 未設定の場合は「現在」と表示 |
| 所属メンバー数 | 上位ユニットの場合は全期の `memberIds` を合算してユニーク化した件数。単独ユニットは `memberIds.length` 件 |

### データなし表示

`units` が空配列の場合は「ユニットデータがまだありません」などのメッセージを表示する。

### ヘッダーナビゲーション

トップ画面（`/`）のヘッダーには「ユニット」へのナビリンクを追加する（#535 で実装）。

---

## 4. ユニット詳細画面（`/units/[id]`）

### 概要

特定ユニットの詳細情報・所属メンバー一覧・関連リリース一覧を表示する画面。
`[id]` は `Unit.id`（kebab-case の識別子）。`parentId` を持つ各期ユニットは詳細ページを持たない。

### アクセス制御

| 条件 | 挙動 |
| --- | --- |
| `[id]` に一致するユニットが存在しない | `notFound()` を返す |
| 一致したユニットが `parentId` を持つ（各期ユニット） | `notFound()` を返す |

### 表示コンテンツ

| 要素 | 内容 |
| --- | --- |
| ナビゲーション | 「ユニット一覧に戻る」リンク（`/units` へ） |
| ユニット名 | `Unit.name` |
| 活動期間 | `activeFrom` ～ `activeTo`。`activeTo` 未設定の場合は「現在」と表示（`activeFrom` は必須項目のため常に表示される） |
| 各期セクション | 上位ユニット（子を持つ）のみ表示。後述 |
| 所属メンバーセクション | 単独ユニットのみ表示。後述 |
| 関連リリースセクション | `releaseIds` から引いたリリース一覧（後述） |

### 各期セクション（上位ユニットのみ）

上位ユニット（`parentId` なし・かつ子ユニットが存在する）の場合に表示する。

**データソース**: `units.json` から `parentId` が当該ユニットの `id` と一致するエントリを全件取得する。

**表示形式**: 各期ユニットを `activeFrom` 昇順（古い順）でセクション分けして表示する。

各期セクションの内容:

| 要素 | 内容 |
| --- | --- |
| セクション見出し | `Unit.name`（各期ユニット名。例: 「タンポポ（第1期）」） |
| 活動期間 | `activeFrom` ～ `activeTo`。`activeTo` 未設定の場合は「現在」と表示 |
| メンバー一覧 | 原則 `memberIds` から引いたメンバーバッジ（後述の所属メンバーセクションと同形式）。ただし対象ユニットが `morning-musume`（モーニング娘。本体）かつ当該期の `memberIds` が空の場合のみ、`activeFrom`〜`activeTo`（未設定時は当年12/31）の期間に在籍していたメンバーを `getMembersActiveBetween` で動的に算出して表示する |

### 所属メンバーセクション

**表示対象**: 単独ユニット（`parentId` なし・かつ子ユニットが存在しない）のみ。上位ユニットは各期セクション内で期ごとに表示するため、このセクションは表示しない。

**データソース**: `members.json`（Vercel Blob）から `memberIds` に一致するメンバーを取得する。

**表示項目**（バッジ形式）:

| 項目 | 内容 | リンク先 |
| --- | --- | --- |
| メンバー名 | `Member.name`（漢字氏名） | `/members/{id}` |
| 世代バッジ | `{generation}期` | — |

読み（ルビ）・ステータスバッジ（現役/OG）はこのバッジには表示しない。

**ソート順**: 実装なし（`members.json` の登録順のまま表示される）。

**ゼロ件時**: `memberIds` が空の場合はセクション自体を表示しない（上位ユニットの各期セクションでは、`morning-musume` 以外かつ `memberIds` が空の場合に「所属メンバーデータがありません」を表示）。

### 関連リリースセクション

**データソース**: `releases.json`（Vercel Blob）から `releaseIds` に一致するリリースを取得する。上位ユニットの場合は自身の `releaseIds` に加えて、全ての子ユニットの `releaseIds` も集約（重複排除）して対象にする。

**表示項目**:

| 項目 | 内容 | リンク先 |
| --- | --- | --- |
| フォーマットバッジ | `FORMAT_LABEL[format]` のラベル | — |
| リリースタイトル | `Release.title` | `/releases/{id}` |
| リリース日 | `Release.releaseDate`（YYYY-MM-DD 形式。不明の場合は「発売日不明」） | — |

**ソート順**: `releaseDate` 降順（新しい順）。

**ゼロ件時**: `releaseIds` が未設定・空配列、または全 ID が解決できない場合はセクション自体を非表示にする。

---

## 5. 既存ページへの追加

### 5.1 メンバー詳細画面（`/members/[id]`）への追加

**追加セクション名**: 「所属ユニット」

**配置場所**: 「選曲した楽曲」セクションの後・「ご当地ライブ」セクションの前に配置する。

**データソース**: `units.json`（Vercel Blob）から `memberIds` に当該メンバーの ID を含むユニットを抽出する。`parentId` を持つ各期ユニットが該当する場合、上位ユニット（`parentId` の指す先）へのリンクを表示する。

**表示項目**:

| 項目 | 内容 | リンク先 |
| --- | --- | --- |
| ユニット名 | 上位ユニットが存在する場合は `上位ユニット名（各期ユニット名）`の形式で表示。単独ユニットは `Unit.name` のみ | `/units/{上位ユニット or 単独ユニットの id}` |
| 活動期間 | 各期ユニットの `activeFrom` ～ `activeTo`。`activeTo` 未設定の場合は「現在」と表示 | — |

**ゼロ件時**: 所属ユニットが存在しない場合はセクション自体を非表示にする。

---

### 5.2 リリース詳細画面（`/releases/[id]`）への追加

**追加セクション名**: 「収録ユニット」

**配置場所**: 「収録曲一覧」セクションの後・「メンバー」セクションの前に配置する。

**データソース**: `units.json`（Vercel Blob）から `releaseIds` に当該リリースの ID を含むユニットを抽出する。

**表示項目**:

| 項目 | 内容 | リンク先 |
| --- | --- | --- |
| ユニット名 | `Unit.name` | `/units/{id}`（`parentId` を持つ場合は上位ユニットへのリンク） |
| 活動期間 | `activeFrom` ～ `activeTo`。`activeTo` 未設定の場合は「現在」と表示 | — |

**ゼロ件時**: 該当ユニットが存在しない場合はセクション自体を非表示にする。

---

### 5.3 曲詳細画面（`/songs/[id]`）への追加

**追加セクション名**: 「アーティスト」

**配置場所**: 再生時間の右に並べて表示する（YouTube MV インライン表示の上）。

**データソース**: `Track.unitId`（`releases.json` 内でトラックに直接紐づくユニットID）から `units.json` のユニットを取得する（`releaseIds` を逆引きする方式ではない）。

- 一致したユニットが各期ユニット（`parentId` あり）の場合、ユニット名はそのまま使い、上位ユニットへのリンクを表示する
- 一致したユニットが上位ユニット（子ユニットを持つ）かつ2014年以前の `morning-musume` 以外の場合、リリース年と各期ユニットの活動期間を照合し（`shouldResolveSubUnitByPeriod`・`findActiveSubUnit`）、該当する期のサブユニット名に解決して表示する
  - 候補となる子ユニットが `releaseIds` を持つ場合（特定楽曲のみに紐づく企画ユニット。例: バカ殿様とミニモニ姫。）は、対象リリースがその `releaseIds` に含まれる場合のみ候補にする。`releaseIds` を持たない子ユニット（活動期間で親を隙間なく分割する各期ユニット。例: ミニモニ。（第1期））は従来通り期間のみで判定する（#1426）

**表示項目**:

| 項目 | 内容 | リンク先 |
| --- | --- | --- |
| アーティスト名 | 解決後のユニット名（サブユニット名 or 上位ユニット名 or 単独ユニット名） | `/units/{上位ユニット or 単独ユニットの id}` |

**ゼロ件時**: 一致するユニットが存在しない場合はセクション自体を非表示にする（アーティストなし曲やモーニング娘。本体リリースはユニット紐づけなしで問題ない）。

**実装 Issue**: #538

---

### 5.4 プレイリスト詳細画面（`/playlists/[id]`）への追加

プレイリスト詳細には以下の2種のユニット関連リンクを追加する。

#### 5.4.1 楽曲アーティスト → ユニット詳細リンク（#561・#539 で実装）

**追加対象**: 楽曲エントリの各行

**データソース**: `PlaylistEntry.trackId` をキーに `releases.json` のトラックを直引きし、`Track.unitId` から `units.json` のユニットを取得する。コンピレーションアルバム等でトラック単位のユニット判定が必要なため、`releaseId` による逆引きではなく `trackId → Track.unitId` の直引きを採用する（#585 で変更）。

**表示項目**:

| 項目 | 内容 | リンク先 |
| --- | --- | --- |
| アーティスト名 | `Unit.name`（各期ユニットの場合は上位ユニット名） | `/units/{上位ユニット or 単独ユニットの id}` |

**ゼロ件時**: 一致するユニットが存在しない場合はアーティスト名自体を非表示にする。

**詳細**: [playlist-screen-design.mdx §4](/design/playlist/playlist-screen-design) を参照。

#### 5.4.2 選曲メンバー → 所属ユニットリンク（#539 で設計・実装）

**追加方針**: 楽曲エントリのメンバー名の直後に、選曲メンバーが所属するユニットへの遷移リンクを追加する。

**データソース**: `units.json`（Vercel Blob）から `memberIds` に当該メンバーの ID を含むユニットを抽出する。`parentId` を持つ各期ユニットが該当する場合は上位ユニットへのリンクを表示する。同一上位ユニットは重複して表示しない。

**表示項目**:

| 項目 | 内容 | リンク先 |
| --- | --- | --- |
| ユニット名 | `Unit.name`（各期ユニットの場合は上位ユニット名） | `/units/{上位ユニット or 単独ユニットの id}` |

**配置場所**: メンバー名リンクの直後、同一行内。1件目は `（ユニット名` 形式、複数件は `・ユニット名` で連結し末尾に `）` を付与する。

**ゼロ件時**: 所属ユニットが存在しない場合はリンクを表示しない（メンバー名のみ表示）。

---

## 6. クロスリンク設計図

```mermaid
flowchart LR
  UNITS["ユニット一覧\n/units"]
  UNIT["ユニット詳細\n/units/:id"]
  MEMBER["メンバー詳細\n/members/:id"]
  RELEASE["リリース詳細\n/releases/:id"]
  TRACK["曲詳細\n/songs/:id"]
  PLAYLIST["プレイリスト詳細\n/playlists/:id"]

  UNITS -- カードクリック --> UNIT
  UNIT -- 一覧に戻る --> UNITS
  UNIT -- メンバー名クリック --> MEMBER
  UNIT -- リリースタイトルクリック --> RELEASE
  MEMBER -- 所属ユニット > ユニット名 --> UNIT
  RELEASE -- 収録ユニット > ユニット名 --> UNIT
  TRACK -- アーティスト > ユニット名 --> UNIT
  PLAYLIST -- ユニット詳細リンク --> UNIT
```

---

## 7. 後続 Issue との関係

| Issue | 本設計書への依存内容 |
| --- | --- |
| #534 ユニット機能の Figma 詳細設計 | 本設計書の §3・§4・§5 を Figma でビジュアル化 |
| #535 ユニット一覧ページ実装 | §3 の設計に基づいて実装 |
| #536 ユニット詳細ページ実装 | §4 の設計に基づいて実装 |
| #537 メンバー詳細への所属ユニットセクション追加 | §5.1 の設計に基づいて実装 |
| #538 リリース詳細・曲詳細にユニット情報追加 | §5.2・§5.3 の設計に基づいて実装 |
| #539 プレイリストとユニット詳細の画面遷移追加 | §5.4.1・§5.4.2 の設計に基づいて実装 |
| #555 上位ユニットを追加する | §3・§4 の上位ユニット対応設計に基づいて実装 |

---

## 改訂履歴

| 版 | 更新日 | 変更内容 |
| --- | --- | --- |
| 1.7 | 2026-07-18 | 実装との乖離是正: ナビゲーション文言、モーニング娘。本体の各期メンバー動的算出ロジック（`getMembersActiveBetween`）、所属メンバーソート未実装の明記、親ユニット関連リリースへの子ユニット集約、メンバー詳細内セクション順序、§5.3曲詳細のユニット紐付けロジック（`Track.unitId`直引き）を実装に合わせて修正（#1366） |
| 1.6 | 2026-04-06 | §5.4.1 データソースを releaseId 逆引きから trackId → Track.unitId 直引きに変更（#585） |
| 1.5 | 2026-04-05 | §5.4.2 選曲メンバー→所属ユニットリンクの詳細仕様を記述（#539） |
| 1.4 | 2026-04-04 | §5.2 配置場所の説明を「収録曲一覧と関連メンバーの間」に修正（プレイリスト掲載情報削除反映）（#568）。§5.3 アーティストの配置を「再生時間の右に並べて表示」に変更（#569） |
| 1.3 | 2026-04-04 | §5.3 曲詳細アーティストセクションの詳細仕様を記述（#554）。§5.4 を §5.4.1（楽曲アーティスト→ユニット）・§5.4.2（選曲メンバー→ユニット）に分割し §5.4.1 の詳細仕様を追加（#561） |
| 1.2 | 2026-04-03 | §3 所属メンバー数をユニーク化件数に修正（#558） |
| 1.1 | 2026-04-03 | §3・§4 に上位ユニット対応を追加、§5.3 曲詳細追加、§5.3 プレイリストを §5.4 に繰り下げ（#555・#554） |
| 1.0 | 2026-03-30 | 初版作成（#533） |
