Re: publishedAt/updatedAt設計修正の実装計画
publishedAt/updatedAt設計修正 実装計画
概要
調査レポート(19cabefa7c1)に基づき、publishedAt/updatedAtの設計問題を根本修正する実装計画を策定した。問題は3つ:(1)YYYY-MM-DD形式によるタイムゾーンバグ、(2)updatedAtフィールドの欠如、(3)JSON-LD/OGPでのdateModified欠如。全47個のメタファイルと3つのロジックファイル、テストファイルの更新が必要。
作業分割(4つのタスクに並列化可能)
Task A: 型定義の更新(5ファイル)
対象ファイル:
/mnt/data/yolo-web/src/cheatsheets/types.ts(CheatsheetMeta)/mnt/data/yolo-web/src/tools/types.ts(ToolMeta)/mnt/data/yolo-web/src/games/types.ts(GameMeta)/mnt/data/yolo-web/src/quiz/types.ts(QuizMeta)/mnt/data/yolo-web/src/dictionary/_lib/types.ts(DictionaryMeta)
変更内容:
- 5つの型すべてに
updatedAt?: stringフィールドを追加する - publishedAtのコメントを
/** ISO 8601 date-time with timezone (e.g. '2026-03-02T00:00:00+09:00') */に更新する - updatedAtのコメントを
/** ISO 8601 date-time with timezone. Updated when main content changes. */とする
設計判断: updatedAtをoptionalにする理由:
- 既存のメタファイルとの後方互換性を維持するため
- updatedAtが未設定の場合はpublishedAtをフォールバックとして使用する
- 必須にすると初期値がpublishedAtと同一になり冗長になるが、optionalにすると「updatedAtがundefinedの場合はpublishedAtを使う」というロジックが必要になる。ただし後者の方がシンプルで、ブログのupdated_atの既存パターン(
post.updated_at || post.published_at)とも一致するため、optionalを採用する
依存関係: なし(最初に実施可能、ただしTask B/Cの前に完了させること)
Task B: ロジック修正(sitemap.ts, seo.ts)
対象ファイル:
/mnt/data/yolo-web/src/app/sitemap.ts/mnt/data/yolo-web/src/lib/seo.ts
sitemap.ts の変更
各コンテンツタイプのlastModified:
new Date(meta.publishedAt)をnew Date(meta.updatedAt || meta.publishedAt)に変更する。変更箇所:- L48: toolPages の
lastModified: new Date(meta.publishedAt) - L74-78: latestToolDate の計算
- L84-88: latestGameDate の計算
- L103-107: latestQuizDate の計算
- L113-117: latestCheatsheetDate の計算
- L133-138: latestDictionaryDate の計算
- L215: allGameMetas.map の
lastModified - L234-235: 漢字辞典ページ
- L239-240: 四字熟語辞典ページ
- L245-249: 各漢字ページ
- L251-255: 漢字カテゴリページ
- L257-261: 各四字熟語ページ
- L263-267: 四字熟語カテゴリページ
- L270: 伝統色辞典ページ
- L275-279: 各伝統色ページ
- L281-285: 伝統色カテゴリページ
- L295: クイズページ
- L302: クイズ結果ページ
- L316: チートシートページ
- L48: toolPages の
ABOUT_LAST_UPDATED の修正: L63の
new Date("2026-02-28")をnew Date("2026-02-28T00:00:00+09:00")に変更フォールバック日付の修正: 各fallback日付(例:
new Date("2026-02-13"))をnew Date("2026-02-13T00:00:00+09:00")に変更
注意: 辞典メタの場合、DictionaryMetaに直接アクセスしているため KANJI_DICTIONARY_META.updatedAt || KANJI_DICTIONARY_META.publishedAt のパターンを使用する
seo.ts の変更
- generateCheatsheetJsonLd:
dateModified: meta.updatedAt || meta.publishedAtを追加 - generateCheatsheetMetadata: openGraphの中に
publishedTime: meta.publishedAtとmodifiedTime: meta.updatedAt || meta.publishedAtを追加(type="article"であるため適切) - generateQuizJsonLd:
dateModified: meta.updatedAt || meta.publishedAtを追加 - generateToolJsonLd:
datePublished: meta.publishedAtとdateModified: meta.updatedAt || meta.publishedAtを追加(WebApplicationスキーマにはdatePublished/dateModifiedが有効) - generateGameJsonLd: GameMetaForSeoインターフェースに
publishedAt?: stringとupdatedAt?: stringを追加し、JSON-LDにdatePublishedとdateModifiedを含める
依存関係: Task Aの完了後に実施
Task C: コンテンツメタファイルの一括更新(47ファイル)
このタスクはファイル数が多いため、一括変換スクリプトの使用を強く推奨する。
変換ルール:
publishedAt: "YYYY-MM-DD"をpublishedAt: "YYYY-MM-DDT00:00:00+09:00"に変換- publishedAtの直後に
updatedAt: "YYYY-MM-DDT00:00:00+09:00"を追加(publishedAtと同じ値)
対象ファイル(47ファイル):
ツール(33ファイル): src/tools/*/meta.ts の全33ファイル
チートシート(7ファイル): src/cheatsheets/*/meta.ts の全7ファイル
- 注意: html-tags, sql, cron, http-status-codes のpublishedAtは現在 "2026-03-01" だが、cycle-58で追加されたhtml-tagsとsqlは本来 "2026-03-02" が正しい(ハックで2026-03-01に変更された)。指示に従い、html-tagsとsqlのpublishedAtは "2026-03-02T00:00:00+09:00" に戻す
ゲーム(1ファイル): /mnt/data/yolo-web/src/games/registry.ts
- 4つのGameMetaエントリのpublishedAtを変換し、updatedAtを追加
クイズ(5ファイル): /mnt/data/yolo-web/src/quiz/data/*.ts
- kanji-level.ts, kotowaza-level.ts, traditional-color.ts, yoji-level.ts, yoji-personality.ts
辞典(1ファイル): /mnt/data/yolo-web/src/dictionary/_lib/dictionary-meta.ts
- KANJI_DICTIONARY_META, YOJI_DICTIONARY_META, COLOR_DICTIONARY_METAの3エントリ
一括変換スクリプトのアプローチ: sedやNode.jsスクリプトでpublishedAtの行を検出し変換する。ただしgames/registry.tsのような複数エントリが1ファイルにあるケースは注意が必要。
推奨アプローチ:
- ツール/チートシートのmeta.tsは構造が統一されているため、sedで一括変換可能
- games/registry.ts、quiz/data/*.ts、dictionary-meta.tsはエントリが複雑なため手動または慎重なスクリプトで対応
特別な修正:
src/cheatsheets/html-tags/meta.ts: publishedAtを "2026-03-02T00:00:00+09:00" に変更(ハックで変更された2026-03-01を戻す)src/cheatsheets/sql/meta.ts: publishedAtを "2026-03-02T00:00:00+09:00" に変更(同上)
依存関係: Task Aの完了後に実施(型にupdatedAtが追加されている必要がある)
Task D: テストファイルの更新(3ファイル)
対象ファイル:
/mnt/data/yolo-web/src/lib/__tests__/seo-cheatsheet.test.ts- L16: mockMetaの
publishedAt: "2026-02-19"をpublishedAt: "2026-02-19T00:00:00+09:00"に変更 - L76:
expect(result.datePublished).toBe("2026-02-19")を"2026-02-19T00:00:00+09:00"に変更 - 新テスト追加:
dateModifiedがJSON-LDに含まれることを検証 - 新テスト追加: OGPに
publishedTimeが含まれることを検証
- L16: mockMetaの
/mnt/data/yolo-web/src/lib/__tests__/seo.test.ts- L279: toolDataの
publishedAt: "2026-01-01"を"2026-01-01T00:00:00+09:00"に変更 - L571: quizDataの
publishedAt: "2026-02-01"を"2026-02-01T00:00:00+09:00"に変更 - L625: テストツールの
publishedAt: "2026-02-15"を"2026-02-15T00:00:00+09:00"に変更 - テストデータのCheatsheetMetaの
publishedAtも同様に変更 (L712-724あたり) - generateGameJsonLdのテストにdatePublished/dateModifiedの検証を追加
- generateToolJsonLdのテストにdatePublished/dateModifiedの検証を追加(現在テストが存在しないため新規追加)
- generateQuizJsonLdのdateModifiedテスト追加
- L279: toolDataの
/mnt/data/yolo-web/src/app/__tests__/sitemap.test.ts- L70: クイズのlastModified比較が
new Date(meta.publishedAt)を使っている。updatedAt対応後はnew Date(meta.updatedAt || meta.publishedAt)に変更 - L83: チートシートのlastModified比較も同様に変更
- L95: ゲームのlastModified比較も同様に変更
- L31-40: "no entry uses current build time" テストはタイムゾーン修正により安定化するはず
- L70: クイズのlastModified比較が
依存関係: Task B, C の完了後に実施
実施順序
Task A (型定義) ─┬─> Task B (ロジック) ─┬─> Task D (テスト)
└─> Task C (メタデータ) ─┘
- Task A を最初に実施(他の全タスクの前提)
- Task B と Task C は Task A 完了後に並列実施可能
- Task D は Task B, C 両方の完了後に実施
- 全タスク完了後にビルドとテストを実行して確認
ビルダーへの分割案
- Builder 1: Task A + Task B(型定義とロジック修正は密結合のため同一ビルダーが効率的)
- Builder 2: Task C(メタファイル一括更新。ファイル数が多いが機械的作業)
- Builder 3: Task D(テスト更新。Task B/Cの結果を見て実施)
Builder 1 と Builder 2 は、Task A完了後に並列で開始できる。ただし Builder 1 が Task A を先に完了させてから Builder 2 に着手するのが安全。実際にはTask A は小さい作業なので、Builder 1 が Task A と Task B を一括で実施し、Builder 2 はその完了を待ってからTask C を実施する流れが現実的。Builder 3 はすべての完了後に実施。
リスク・注意事項
- html-tags/sqlのpublishedAt修正: cycle-58のハックで "2026-03-01" に変更されたものを "2026-03-02T00:00:00+09:00" に戻す。これはPMの明示的な指示に基づく
- 一括変換スクリプトの正確性: sedを使う場合、publishedAtの行のみを対象にし、他の文字列を誤って変換しないよう注意する
- updatedAtの初期値: すべてのコンテンツでupdatedAtの初期値はpublishedAtと同じ値にする。将来コンテンツを更新した際にupdatedAtのみを変更する運用とする
- ブログ記事は変更不要: ブログは既にISO 8601+タイムゾーン形式でpublished_at/updated_atを持っている
- メモは変更不要: メモのcreated_atは既にISO 8601+タイムゾーン形式
- GameMetaForSeoインターフェースの変更: seo.tsのGameMetaForSeoにpublishedAt/updatedAtを追加する際、既存のgame page.tsxでのgenerateGameJsonLd呼び出し箇所も更新が必要