12
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

世界初のクソアプリ検索エンジン「kusoogle」を作った

Last updated at Posted at 2025-12-08

本記事は クソアプリアドベントカレンダー2025 の記事です。

1. はじめに 〜 クソアプリ開発者の永遠の悩み 〜

人類は生成AIという武器を手に入れ、誰もが気軽にクソアプリを作れるようになった。私もその一人だ。
クソアプリアドベントカレンダーに参加しようと思い立った時、誰もが直面する問題がある。

「このクソアプリ、過去に誰か作ってない?」

どうせ作るならネタが被っていない斬新なクソを生み出したいものである。
「タスク管理アプリ」「目覚まし時計」「ゲームアプリ」...
過去10年分のクソアプリアドベントカレンダーには、約400件の記事が存在する。
手動で全部確認するのは現実的ではない。

「もし、類似のクソアプリを自動で検索できたら...」

自分のため、全てのクソアプリ開発者のために、「クソアプリ検索エンジン」 を作った。
このネタが被っていないことは全記事を目視で確認済みである。なので「世界初」をうたっても問題はないだろう。

完成した検索エンジンで検索しても類似のクソはなかったかどうかは、最後にリンクを掲載している。ぜひご自身で確認いただきたい。

2. 完成したアプリ

kusoogle_-_クソアプリ検索エンジン.png

kusoogle - 世界初のクソアプリ検索エンジン

3. 誰のための何をするアプリか

対象ユーザー

全てのクソアプリ開発者

何をするアプリか

  1. 過去のクソアプリ記事を自動収集

    • 2015年から続くクソアプリアドベントカレンダーの記事をQiita APIで取得
    • 日次で最新記事を自動更新(予定)
  2. 意味的類似性による検索

    • 単なるキーワードマッチングではなく、ベクトル検索 で意味的に似た記事を検索
    • 「タスク管理」と検索すると、「TODOアプリ」「スケジュール管理ツール」などもヒット
    • Qiita利用規約に則り、記事本文そのものは保持していない
  3. 類似度スコアの表示

    • 検索結果に類似度スコアを表示
    • 類似度が高い = アイデアが被っている可能性が高い

使用例

検索クエリ: "検索エンジン"
→ 類似記事: 「世界初のクソアプリ検索エンジン「kusoogle」を作った」(類似度: 0.85)
→ 判定: アイデアが被っている可能性が高い

4. 技術要素の解説

エッジファーストアーキテクチャ

  • Cloudflare Workers をフル活用
  • 低レイテンシー: エッジネットワークで実行されるため、世界中どこからでも高速
  • 無料: 個人開発プロジェクトには十分な無料枠
  • 自動スケーリング: サーバーレスで運用負荷ゼロ

システム構成:

┌─────────────────┐
│   ユーザー      │
└────────┬────────┘
         │ HTTPS
         ▼
┌─────────────────────────────────────┐
│   Cloudflare Workers (Edge)         │
│   Next.js 16 (Frontend)             │
│   - @opennextjs/cloudflare          │
│   - React Server Components         │
│   - Server Actions                  │
│   - Edge Runtime                    │
└────────┬────────────────────────────┘
         │ HTTP/HTTPS
         ▼
┌─────────────────────────────────────┐
│   Cloudflare Workers (Edge)         │
│   - Hono Framework                  │
│   - TypeScript 5.x                  │
│   ┌──────────────────────────────┐  │
│   │  Search API                  │  │
│   │  - クエリのEmbedding化        │  │
│   │  - Vectorize検索             │  │
│   │  - 説明生成(Phase 2)         │  │
│   └──────────────────────────────┘  │
│   ┌──────────────────────────────┐  │
│   │  Data Collection (Cron)      │  │
│   │  - Qiita API呼び出し         │  │
│   │  - 記事のEmbedding化         │  │
│   │  - Vectorizeへの保存         │  │
│   └──────────────────────────────┘  │
└────────┬────────────────────────────┘
         │
    ┌────┴────┬──────────────┬────────────┐
    ▼         ▼              ▼            ▼
┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│Vectorize│ │AI Workers│ │   KV     │ │  Cron    │
│(Vector  │ │(Embedding│ │(Cache)   │ │(Scheduler)│
│  DB)    │ │  Model)  │ │          │ │          │
└─────────┘ └──────────┘ └──────────┘ └──────────┘

コスト:

  • 月額0円(無料枠内で運用)
  • データ収集は日次1回のみ(予定)
  • 検索はオンデマンド

Cloudflareは無料で高速なアプリが作れて素晴らしい。
AWSだと月額数千円かかるのではないだろうか。

ベクトル検索の実装

なぜベクトル検索なのか?

単純なキーワードマッチングでは、「タスク管理」と検索しても「TODOアプリ」はヒットしない。
しかし、意味的には同じ なので、ヒットしてほしい。

ベクトル検索なら、テキストを数値ベクトル(Embedding)に変換し、意味的な類似度 を計算できる。

実装の流れ:

// # データ収集時
// 記事をEmbedding化
const articleText = `${title} ${tags} ${summary}`;
const embedding = await ai.run('@cf/baai/bge-base-en-v1.5', {
  text: articleText,
});

// Vectorizeに保存
await vectorizeIndex.upsert([{
  id: articleId,
  values: embedding,
  metadata: { title, url, tags, ... }
}]);

// ---

// # 検索時
// クエリをEmbedding化して検索
const queryEmbedding = await ai.run('@cf/baai/bge-base-en-v1.5', {
  text: query,
});
const results = await vectorizeIndex.query(queryEmbedding, {
  topK: 20, // 類似度が高い順に20件取得
});

技術スタック:

  • Cloudflare AI Workers: Embedding生成(@cf/baai/bge-base-en-v1.5、768次元)
  • Cloudflare Vectorize: エッジベースのベクトルDB
  • コサイン類似度: ベクトル間の類似度計算(0-1の範囲)

要約アプローチによる精度向上

問題:長文記事の意味が平均化される

5000文字の長文記事をそのままEmbedding化すると、重要な情報が埋もれてしまう。
「目覚ましアプリ」「タスク管理」といった具体的な検索クエリにマッチしにくい。

解決策:300文字程度に要約してからEmbedding化

// 記事本文を要約(Cloudflare WorkersAIを使用)
const summary = await summarizeArticle(article.body, ai, 300);

// 要約 + タイトル + タグでEmbedding生成
const text = `${summary} ${article.title} ${tagsText}`;
const embedding = await generateEmbedding(text, ai);

要約プロンプトの工夫:

  • 定型表現を禁止(「どのような場面で」など)
  • 汎用的な表現を禁止(「〜なアプリ」など)
  • 各記事の独自性を強調する具体的な記述を指示

これにより、意味が凝縮され、検索精度が向上 する。

クエリ拡張による検索精度向上

問題:短文クエリの検索精度が低い

「目覚まし」と検索しても、「目覚まし時計」「アラーム」「起床アプリ」などもヒットしてほしい。

解決策:クエリ拡張

// 短文クエリ(15文字以下)を意味拡張
if (query.length <= 15) {
  const expandedQuery = await expandQuery(query, ai);
}

実装:

  • Cloudflare WorkersAI(@cf/meta/llama-3.1-8b-instruct)でクエリを拡張
  • 関連技術用語や同義語を自動追加
  • 拡張されたクエリでEmbedding生成

例:

  • "目覚まし""目覚まし時計 アラーム 起床 アプリ"

5. 実際に使ってみて

どんなに革新的なクソアプリのアイデアを検索しても、類似アプリが20件ヒットする(表示を20件に絞っているので裏ではもっとヒットしている)。

人類は結局、同じクソを繰り返していた ———



そんなはずはない。
先人達のクソアプリはどれも独自のクソが際立つ素晴らしいものばかりである。

自分(クソアプリ開発者)のために真面目に役立つアプリを作ろうとしたはずが、思いがけず「クソアプリ」そのものを生み出してしまった。

6. まとめ

世界初のクソアプリ検索エンジン「kusoogle」

類似0件を達成するとお祝いメッセージが表示される仕様にした。これが表示される #奇跡のクソアプリ が誕生することを願っている。

参考)kusoogleによる、「クソアプリ検索エンジン」の 検索結果

参考資料

技術ドキュメント

関連記事

12
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?