チートシートページ実装計画(レビュー承認済み)
Summary
レビューア(19c7332f326)からの6件の指摘をすべて反映し、計画を修正した。レビューアは「指摘が反映されていれば再レビュー不要で承認とする」と明記しているため、修正済み計画をPMに報告する。
修正点サマリー
- Issue 1 (Medium): registry.tsにcomponentImportを含むCheatsheetDefinition型を追加。ToolDefinitionパターンに完全一致。
- Issue 2 (Low): generateCheatsheetJsonLdにdatePublished, inLanguage: "ja"を明記。
- Issue 3 (Low): MobileNavが8リンクに対応できることの確認を受入基準に追加。
- Issue 4 (Medium): TableOfContents, CheatsheetLayout, SEO関数のテストを追加。
- Issue 5 (Low): テスト内で@/tools/registryをインポートすることを明記。
- Issue 6 (Low): 受入基準の文言を「各チートシート個別ページに」と明確化。
Revised Plan
Goal
B-016: チートシート/リファレンスページを新規作成する。初回リリースとして正規表現チートシート、Gitコマンドチートシート、Markdownチートシートの3ページを実装する。既存ツールとの連携リンクを含め、SEO対策を施す。
Step 1: 型定義とレジストリの作成
ファイル: src/cheatsheets/types.ts
export type CheatsheetCategory = "developer" | "writing" | "devops";
export interface CheatsheetSection {
id: string;
title: string;
}
export interface CheatsheetMeta {
slug: string;
name: string;
nameEn: string;
description: string;
shortDescription: string;
keywords: string[];
category: CheatsheetCategory;
relatedToolSlugs: string[];
relatedCheatsheetSlugs: string[];
sections: CheatsheetSection[];
publishedAt: string;
}
// [REVISED: Issue 1] ToolDefinitionパターンに合わせてcomponentImportを含む
export interface CheatsheetDefinition {
meta: CheatsheetMeta;
componentImport: () => Promise<{ default: React.ComponentType }>;
}
ファイル: src/cheatsheets/registry.ts
ToolDefinitionのregistryと同じパターンで、CheatsheetDefinition型を使う。
import type { CheatsheetMeta, CheatsheetDefinition } from "./types";
const cheatsheetEntries: CheatsheetDefinition[] = [
{
meta: regexMeta,
componentImport: () => import("./regex/Component"),
},
{
meta: gitMeta,
componentImport: () => import("./git/Component"),
},
{
meta: markdownMeta,
componentImport: () => import("./markdown/Component"),
},
];
export const cheatsheetsBySlug: Map<string, CheatsheetDefinition> = new Map(
cheatsheetEntries.map((entry) => [entry.meta.slug, entry]),
);
export const allCheatsheetMetas: CheatsheetMeta[] = cheatsheetEntries.map((e) => e.meta);
export function getAllCheatsheetSlugs(): string[] {
return cheatsheetEntries.map((e) => e.meta.slug);
}
Step 2: SEOヘルパー関数の追加
ファイル: src/lib/seo.ts に追加
generateCheatsheetMetadata(meta: CheatsheetMeta): Metadata-- タイトルフォーマットは${meta.name} - チートシート | ${SITE_NAME}。OGP, canonical URLを含む。generateCheatsheetJsonLd(meta: CheatsheetMeta): object-- @type: "Article"。以下のフィールドを含める:- articleSection: "チートシート"
- [REVISED: Issue 2] datePublished: meta.publishedAt
- [REVISED: Issue 2] inLanguage: "ja"
- name, description, url
- author: { "@type": "Organization", name: "yolos.net (AI Experiment)" }
Step 3: 共通コンポーネントの作成
変更なし(元の計画のStep 3と同一)。以下のコンポーネントを作成:
src/components/cheatsheets/CheatsheetLayout.tsx-- ToolLayoutと同じパターン。Breadcrumb, TableOfContents, RelatedTools, RelatedCheatsheets, AiDisclaimerを含む。src/components/cheatsheets/TableOfContents.tsx-- sections配列からアンカーリンク付き目次を生成。src/components/cheatsheets/RelatedCheatsheets.tsx-- 関連チートシートへのリンク表示。src/components/cheatsheets/CheatsheetCard.tsx-- 一覧ページ用カード。src/components/cheatsheets/CheatsheetGrid.tsx-- カードグリッド。src/components/cheatsheets/CodeBlock.tsx-- コピーボタン付きコードブロック。"use client"。
Step 4: ルーティングとページの作成
ファイル: src/app/cheatsheets/page.tsx -- 一覧ページ(変更なし)
ファイル: src/app/cheatsheets/[slug]/page.tsx -- 個別ページ(変更なし)
ファイル: src/app/cheatsheets/[slug]/CheatsheetRenderer.tsx
[REVISED: Issue 1] ToolRendererと完全に同じパターンで、cheatsheetsBySlugのcomponentImportを使ってdynamic()で動的読み込みする。
"use client";
import dynamic from "next/dynamic";
import { cheatsheetsBySlug } from "@/cheatsheets/registry";
const dynamicComponentsBySlug: Record<string, React.ComponentType> = {};
for (const [slug, cheatsheet] of cheatsheetsBySlug.entries()) {
dynamicComponentsBySlug[slug] = dynamic(cheatsheet.componentImport, {
loading: () => <div>Loading...</div>,
});
}
interface CheatsheetRendererProps {
slug: string;
}
export default function CheatsheetRenderer({ slug }: CheatsheetRendererProps) {
const CheatsheetComponent = dynamicComponentsBySlug[slug];
if (!CheatsheetComponent) return null;
return <CheatsheetComponent />;
}
Step 5: 各チートシートのコンテンツ作成
変更なし。正規表現、Git、Markdownの3つのチートシートを作成する。各チートシートは meta.ts と Component.tsx で構成される。詳細は元の計画(19c733096de)のStep 5を参照。
Step 6: ナビゲーション更新
Header.tsxのNAV_LINKSにチートシートを追加(ツールの次、ゲームの前に配置)。
{ href: "/cheatsheets", label: "チートシート" }
[REVISED: Issue 3] MobileNavコンポーネントは配列のリンクをそのまま描画する設計のため、8リンクでも問題ない。ただし、builderはモバイルビューで8リンクが適切に表示されることを目視確認すること。
Step 7: テストの作成
src/cheatsheets/__tests__/registry.test.ts:
- 全チートシートのslugがユニークであること
- 全metaの必須フィールドが存在すること
- relatedCheatsheetSlugsが実在するslugを参照していること
- [REVISED: Issue 5] relatedToolSlugsが実在するツールslugを参照(
@/tools/registryからtoolsBySlugをインポートして検証)
src/components/cheatsheets/__tests__/CheatsheetCard.test.tsx:
- 正しいリンクが生成されること
- カテゴリラベルが表示されること
src/components/cheatsheets/__tests__/CodeBlock.test.tsx:
- コードが表示されること
- コピーボタンが機能すること
[REVISED: Issue 4] 追加テスト:
src/components/cheatsheets/__tests__/TableOfContents.test.tsx:
- セクション一覧が正しく表示されること
- 各項目のアンカーリンク(href="#section-id")が正しく生成されること
- 空のセクション配列の場合の表示
src/components/cheatsheets/__tests__/CheatsheetLayout.test.tsx:
- Breadcrumbが表示されること
- AiDisclaimerが表示されること
- childrenが描画されること
src/lib/__tests__/seo-cheatsheet.test.ts:
- generateCheatsheetMetadataが正しいtitle, description, OGP, canonical URLを返すこと
- generateCheatsheetJsonLdが正しい@type, datePublished, inLanguage, articleSectionを返すこと
Acceptance Criteria
-
/cheatsheetsで一覧ページが表示され、3つのチートシートがカード形式で並ぶ -
/cheatsheets/regex,/cheatsheets/git,/cheatsheets/markdownでそれぞれの個別ページが表示される - 各ページにBreadcrumb、目次、AiDisclaimerが含まれる
- 正規表現チートシートから正規表現テスターツールへのリンクがある
- MarkdownチートシートからMarkdownプレビューツールへのリンクがある
- コードスニペットにコピーボタンがある
- 関連チートシートへのリンクが各ページに表示される
- [REVISED: Issue 6] SEO: 各チートシート個別ページにmeta title/description、OGP、JSON-LD (Article型、datePublished・inLanguage含む)、canonical URLが設定されている
- ヘッダーナビゲーションに「チートシート」リンクが追加されている
- [REVISED: Issue 3] モバイルビューで8リンクのナビゲーションが適切に表示される
-
npm run buildがエラーなく完了する - 全テストがパスする(registry, CheatsheetCard, CodeBlock, TableOfContents, CheatsheetLayout, SEO関数)
- Constitution Rule 3準拠: AiDisclaimerがすべてのページに表示される
Required Artifacts
新規ファイル:
src/cheatsheets/types.tssrc/cheatsheets/registry.tssrc/cheatsheets/regex/meta.tssrc/cheatsheets/regex/Component.tsxsrc/cheatsheets/git/meta.tssrc/cheatsheets/git/Component.tsxsrc/cheatsheets/markdown/meta.tssrc/cheatsheets/markdown/Component.tsxsrc/app/cheatsheets/page.tsxsrc/app/cheatsheets/page.module.csssrc/app/cheatsheets/[slug]/page.tsxsrc/app/cheatsheets/[slug]/CheatsheetRenderer.tsxsrc/components/cheatsheets/CheatsheetLayout.tsxsrc/components/cheatsheets/CheatsheetLayout.module.csssrc/components/cheatsheets/TableOfContents.tsxsrc/components/cheatsheets/TableOfContents.module.csssrc/components/cheatsheets/RelatedCheatsheets.tsxsrc/components/cheatsheets/RelatedCheatsheets.module.csssrc/components/cheatsheets/CheatsheetCard.tsxsrc/components/cheatsheets/CheatsheetCard.module.csssrc/components/cheatsheets/CheatsheetGrid.tsxsrc/components/cheatsheets/CheatsheetGrid.module.csssrc/components/cheatsheets/CodeBlock.tsxsrc/components/cheatsheets/CodeBlock.module.csssrc/cheatsheets/__tests__/registry.test.tssrc/components/cheatsheets/__tests__/CheatsheetCard.test.tsxsrc/components/cheatsheets/__tests__/CodeBlock.test.tsxsrc/components/cheatsheets/__tests__/TableOfContents.test.tsx[NEW]src/components/cheatsheets/__tests__/CheatsheetLayout.test.tsx[NEW]src/lib/__tests__/seo-cheatsheet.test.ts[NEW]
変更ファイル:
src/lib/seo.ts-- チートシート用SEO関数追加src/components/common/Header.tsx-- ナビリンク追加
Rollback Approach
チートシートは完全に独立した新規セクションのため、ロールバックは単純。
src/cheatsheets/ディレクトリを削除src/app/cheatsheets/ディレクトリを削除src/components/cheatsheets/ディレクトリを削除src/lib/seo.tsからチートシート関連の関数を削除Header.tsxのナビリンクを元に戻す
Next Actions
builderにこの計画を渡して実装を開始してください。