ヘルプセンター — マークダウン記事、検索、i18n
ヘルプセンターは小さな静的サイトであり、すべての記事にアクセス可能であるという1つの厳しい要件があります。サイドバー、検索、まだ翻訳されていないロケールからもアクセスできる必要があります。このモジュールを出荷したエンジニアによって作成されました。以前の実装はマーケティングサイトのヘルプセンターでした。以下のモジュールは、その要件を検証済みのプロパティとして保持しています。サイドバーはすべてのカテゴリのすべての記事を表示し、検索は入力方法に関わらずクエリをランク付けし、関連リンクが解決されるかバリデーターがビルドを失敗させます。ローダー、検索、タグスイートがそれぞれをカバーしています。記録は references/provenance.md にあります。
使用するタイミング
Next.js App Router上で、記事がリポジトリ内のマークダウンファイルであるヘルプセンター、ドキュメントセクション、ナレッジベースを構築または拡張する場合。複数ロケールの有無は問いません。
使用すべきでないタイミング
- ブログ。 日付と著者が設定され、カバー画像とローカライズされたスラッグを持つ投稿は異なるコンテンツモデルです。ホストのブログモジュールを維持してください。
- コードから生成されたドキュメント(OpenAPI、TypeDoc) — それぞれのジェネレーターを使用し、出力にリンクしてください。
- CMSをバックエンドに持つヘルプサイトで、編集者がランタイムで公開する場合。インデックス契約は引き続き適用されますが、ローダー、静的パラメータ、バリデーションが変更されます。extensions.md のCMSに関する注釈を参照してください。
- たまたまマークダウンであるマーケティングページ。 ホストのレンダラーを再利用してください。このモジュールは、多数の記事を中心としたナビゲーション、検索、ロケールモデルです。
アーキテクチャ
content/help/<[locale]/><category>/<slug>.md
│ gray-matter + 正規化
▼
getHelpIndex(locale) ── React cache(): リクエストごとに1回パース ──┐
カテゴリ · 記事 (ソート済み) · byKey · タグ · byTag · スキップ済み│
│ │
├─► ページ: ランディング / カテゴリ / タグ / 記事 ── メタデータ、JSON-LD、canonical/hreflang
├─► HelpShell ── toSummary → ナビツリー (サイドバー + ドロワー)
│ ── toSearchDoc → HelpSearch (クライアント、トークン化プレフィックス検索)
├─► helpSitemapEntries()
└─► validate:help (CI) ── 未解決の関連、順序のタイ、不正な日付、不正なスラッグ、タグのドリフト
すべてはインデックスから読み取られます。ファイルシステムに直接アクセスするものは他にありません。
重要な事実
- ファイルシステムがスキーマです。 フォルダ = カテゴリ、ファイル名 = スラッグ、フロントマターはメタデータのみです。フロントマター内の
slug/categoryはパスに対して検証され、使用されることはありません。 - サマリーのみがクライアントに渡されます。
toSummary/toSearchDocは本文を削除します。HelpArticleをクライアントコンポーネントに渡すと、すべてのページに全文が送信されます。 - 翻訳されていないページは重複として扱われます。 デフォルトロケールからレンダリングされ、ナビゲーション内の位置を維持し、注意書きを表示し、デフォルトロケールのURLに正規化され、hreflangとサイトマップからは除外されます。
- ランタイムは寛容ですが、CIは寛容ではありません。 不正な参照は無視され、欠落した順序は最後にソートされます。そして
validate:helpは作成者のためにビルドを失敗させます。 - 検索は設計上クライアントサイドです。 記事あたり約1KBで、ナビゲーション用にすでにページに含まれており、最初のキーストロークで結果が表示されます。本文検索は拡張機能です。
厳格なルール
決して折りたたみ可能なリストの高さを制限しないでください。
max-h-*+overflow-hiddenの組み合わせは、収まらないものをクリップして何も報告しません。hiddenまたは実際の折りたたみ可能なプリミティブを使用して、すべてのリンクまたは何も表示しないようにしてください。
決して
orderだけでソートしないでください。 同順位はreaddirの順序にフォールスルーします。これはファイルシステム間で異なります。タイトル、次にスラッグで同順位を解決してください。
決してバリデーションなしで
relatedを解決しないでください。 削除された参照はページ上で見えなくなります。バリデーターだけが、作成者がスラッグの名前変更を知る場所です。
決してトリミングされていないクエリを検索せず、タイトルだけで検索しないでください。 トリム、トークン化、ダイアクリティクスの折りたたみ、タグと見出しを含め、フィールドごとにランク付けしてください。
決してi18nシステムを持つホストでクロム文字列をハードコードしないでください。 すべての文字列は
HelpStringsを通過するため、ヘッダー、フッター、通知が一緒にロケールを切り替えます。
決してタグをそのスペルでキーにしないでください。 大文字小文字、ハイフン、複数形は作成者間で異なります。
tagSlugでグループ化して、すべてのバリエーションが1つのページに集まるようにし、バリデーターに変化を報告させてください。
クイックスタート
- シームコントラクトを埋め、カテゴリIDを決定してください — adaptation.md。
- コンテンツレイアウトを選択し、設定を記述してください — content-model.md。
- ローダーとフロントマターパーサーをコピーし、実際のコンテンツで即座にバリデーターを実行してください — content-loader.md。
- 文字列とパスをホストのi18nに配線してください — i18n.md。
- 3つのページ、SEOヘルパー、サイトマップエントリを追加してください — routes.md — 次にタグページとリンクチップ — tags.md。
- シェル、ナビゲーションツリー、ドロワーを構築してください — ui.md — 次にパンくずリスト、カード、リスト、レンダラーをホストのプリミティブ上に — ui-content.md。
- 検索とそのフックを導入し、ゼロ結果フックをアナリティクスに配線してください — search.md。
- 出荷されたテストを実行し、次に動作契約を確認してください:最長カテゴリが完全に到達可能であること、末尾スペースのクエリ、アクセント付きクエリ、翻訳されていないページの正規URL。
リファレンスディレクトリ
| シナリオ | トリガーキーワード | リファレンス |
|---|---|---|
| 既存アプリへの統合 | 適応、シーム、カテゴリ名変更、ホストプローブ、統合、依存関係 | adaptation.md |
| フロントマター、フォルダ、スラッグ、バリデーション | フロントマター、スラッグ、カテゴリ、順序、関連、updatedAt、featured、検証、CI | content-model.md |
| ファイルのインデックスへの読み込み | ローダー、gray-matter、キャッシュ、フォールバック、見出し、ソート、インデックス、fs | content-loader.md |
| 検索ボックスとランキング | 検索、コンボボックス、ランキング、トークン化、ダイアクリティクス、プレフィックス、キーボード、結果なし | search.md |
| タグ、タグページ、チップ、タグクラウド | タグ、タグ、タグページ、チップ、タグスラッグ、スペル、複数形、タグで閲覧 | tags.md |
| ロケール、文字列、日付、正規URL | i18n、ロケール、翻訳、フォールバック、hreflang、文字列、複数形、Intl | i18n.md |
| ページ、メタデータ、JSON-LD、サイトマップ | ルート、page.tsx、generateStaticParams、dynamicParams、notFound、canonical、TechArticle、sitemap | routes.md |
| シェル、ヘッダー、サイドバー、ドロワー | レイアウト、サイドバー、モバイルメニュー、ドロワー、折りたたみ可能、スティッキー、HelpShell | ui.md |
| パンくず、カード、リスト、レンダラー、スタイルフック | パンくず、カテゴリカード、記事リスト、react-markdown、data-help、スタイリング | ui-content.md |
| 出荷モジュールを超えて | 全文、Pagefind、TOC、フィードバック、git日付、MDX、CMS、リダイレクト | extensions.md |
| テンプレートが以前の実装と異なる理由 | 来歴、監査、台帳、意図的に保持、以前の実装の修正 | provenance.md |