キーワード検索
ブログのキーワード検索機能の実装概要。検索インデックス、API、キーワード分析。
ブログに組み込まれた全文キーワード検索機能です。MiniSearchを使用し、ビルド時に生成した検索インデックスをもとに記事を検索します。
アーキテクチャ
検索機能は以下のコンポーネントで構成されています。
- 検索インデックス生成 — ビルド時にMDX記事ファイルから
search-index.jsonを生成(generate-search-index.mjs) - 検索API — Cloudflare Pages Functionによる全文検索API(
GET /api/search?q=...) - 検索ページ — クライアントサイドの検索UI(
/search/) - キーワードログ — 検索クエリをCloudflare KVに記録し、分析に活用
- キーワードビューア — ログを可視化するダッシュボードアプリ
- 開発時フォールバック — クライアントサイドMiniSearchによるローカル検索
検索インデックス
blog/scripts/generate-search-index.mjsがビルド時に記事ファイルを読み取り、search-index.jsonを生成します。生成されたファイルは2箇所に配置されます。
| 出力先 | 用途 |
|---|---|
blog/public/search-index.json | 開発環境でのクライアントサイド検索用 |
functions/pj/zpaper/api/search-data.json | 本番環境のCloudflare Pages Function用 |
各記事ドキュメントのフィールド構成は以下の通りです。
| フィールド | 説明 |
|---|---|
id | 記事の一意識別子 |
slug | 記事のURLスラッグ |
title | 記事タイトル |
description | 記事の説明文 |
tags | タグ(スペース区切り) |
createdAt | 作成日 |
excerpt | 記事本文の先頭500文字のプレーンテキスト |
インデックスはcreatedAtの降順でソートされます。
検索機能
MiniSearchの検索オプションによって以下の検索動作が有効になっています。
| 機能 | 設定値 | 説明 |
|---|---|---|
| 前方一致検索 | prefix: true | 入力途中の部分文字列でも検索結果を返す |
| あいまい検索 | fuzzy: 0.2 | タイプミスや表記揺れに対して許容度0.2でマッチングする |
フィールドごとにブースト値が設定されており、検索結果のランキングに重み付けが行われます。
| フィールド | ブースト値 |
|---|---|
title | 3.0 |
description | 2.0 |
tags | 1.5 |
excerpt | 1.0(デフォルト) |
検索結果には、マッチしたキーワードが<mark>タグでハイライトされたタイトルと抜粋が含まれます(highlighted_title、highlighted_excerpt)。
検索ページ
- パス:
/search/ - URLパラメータ:
?q=検索クエリ - 入力は300msのデバウンス付き
- URLは検索クエリと同期される
- ページロード時に入力フィールドへ自動フォーカス
キーワードログ
検索APIは、検索が実行されるたびにクエリ情報をCloudflare KVに記録します。
仕組み
検索関数(functions/pj/zpaper/api/search.ts)内で、検索結果の計算後に非同期でKVに書き込みます。
- 記録条件: 検索結果が1件以上ある場合のみ(ゼロヒットのクエリは記録しない)
- 書き込み方式: Fire-and-forget(書き込み失敗が検索レスポンスに影響しない)
- ストア名:
keyword-logs - キー形式:
<ISO-timestamp>-<6文字ランダム>(例:2026-03-01T12:34:56.789Z-a3f7kz)
各ログエントリのデータ構成は以下の通りです。
| フィールド | 説明 |
|---|---|
keyword | 検索クエリ文字列 |
timestamp | 検索実行時のISO 8601タイムスタンプ |
resultCount | 検索結果の件数 |
開発環境での挙動
開発環境(pnpm dev)ではクライアントサイドで検索が実行されるため、Cloudflare Pages Functionは呼ばれず、キーワードログは記録されません。
キーワードビューア
キーワードログを可視化するためのダッシュボードアプリです。2つの形態があります。
Webアプリ(sub-packages/keyword-viewer)
React + Viteで構築されたSPAです。
cd sub-packages/keyword-viewer
pnpm dev # http://localhost:60521 で起動
開発時はViteのプロキシ設定により、APIリクエストが本番サイト(zudo-paper.pages.dev)に転送されます。APIが利用できない場合は、シード付きのモックデータにフォールバックします。
画面構成
| パス | 画面 | 内容 |
|---|---|---|
/ | ダッシュボード | 検索総数、ユニークキーワード数、本日/今週の検索数、上位キーワードチャート、日別検索ボリュームチャート |
/keywords | キーワード一覧 | 全キーワードのテーブル表示(件数、最終検索日でソート可能) |
/calendar | カレンダー | 月別/週別の検索ボリュームをヒートマップ表示(日ごとのキーワード内訳も確認可能) |
技術スタック
React 19、React Router DOM v7、Vite 6、Tailwind CSS v4、Mermaid v11(チャート描画)。
API
- 検索:
GET /pj/zpaper/api/search?q=<query>— 検索API - キーワードログ:
GET /pj/zpaper/api/keyword-logs— キーワードログAPI