AI開発収益化ラボ
PromptStock

PromptStock ができるまで — 企画から公開までの全記録

ChatGPTやClaudeを使っていて、こんな経験はありませんか?

「なんかイマイチな回答しか返ってこない…」 「プロンプトの書き方次第で変わるらしいけど、具体的にどう書けば?」

実は、同じAIでもプロンプトの質で出力の精度は劇的に変わります。 PromptStockは、その課題を解決するために生まれたプロンプトテンプレート辞典です。

この記事では、企画の背景から技術選定、実装の裏話まで、開発の全過程をお見せします。


🎯 解決したかった課題

開発のきっかけは、生成AIの「使いこなし格差」でした。

ユーザー層典型的な使い方結果
初心者「メール書いて」汎用的で使えない文面
中級者「ビジネスメールを丁寧に書いて」そこそこ使える
上級者役割・条件・出力形式を明示ほぼ完璧な出力

この差は知識の問題であり、良いテンプレートさえあれば誰でも上級者と同じ結果を得られるはずです。 そこで「目的別にすぐコピーして使えるプロンプト集」というコンセプトが生まれました。


🏗️ 技術選定 — なぜこの構成にしたのか

採用技術の全体像

技術選定理由
Next.js 15 (App Router)Server Componentsで SEO と速度を両立
TypeScript型安全性。プロンプトデータの構造を厳密に管理
PostgreSQL + Prismaリレーショナルデータ + 型安全なORM
Tailwind CSS v4CSS変数ベースのテーマ管理。ダークモード対応が容易
Claude Haiku高速・低コスト。プロンプト改善に最適
Framer Motion軽量アニメーション。カード表示をリッチに

不採用にした技術と理由

迷った選択肢もありました。正直に振り返ります。

候補不採用の理由
Elasticsearchプロンプト数が数百件規模。PostgreSQLのLIKE検索で十分
GPT-4oAI改善機能のコスト。Haikuの方が10倍以上安い
Redisいいね数キャッシュを検討したが、現時点では過剰設計
i18n (多言語化)PV獲得が最優先。日本語特化の方がSEO効果が高い

教訓: 「将来必要になるかも」で技術を入れない。必要になってから足すのが正解。


📐 データベース設計

プロンプトのデータ構造はシンプルに保ちつつ、拡張性を確保しました。

PromptStockPrompt
├── id          (主キー)
├── title       (プロンプトのタイトル)
├── content     (プロンプト本文)
├── description (説明文 — 一覧表示用)
├── category    (カテゴリ名)
├── tags        (タグ配列 — PostgreSQLのネイティブ配列)
├── isOfficial  (公式プロンプトフラグ)
├── likeCount   (いいね数 — 非正規化)
├── copyCount   (コピー数 — 非正規化)
└── createdAt   (作成日時)

なぜ likeCount を非正規化したのか

正規化するなら、いいね数は毎回 COUNT(*) で集計するのが正しい設計です。 しかし、一覧ページで8件のプロンプトそれぞれに対してCOUNTクエリを投げるのは明らかに非効率。

-- ❌ 正規化: 毎回8件分のCOUNTが走る
SELECT p.*, (SELECT COUNT(*) FROM likes WHERE prompt_id = p.id) FROM prompts p;

-- ✅ 非正規化: 1クエリで完結
SELECT * FROM prompts ORDER BY like_count DESC;

トレードオフ: いいね/取り消し時にカウントの整合性を保つ必要があるが、トランザクション内で処理すればOK。一覧の表示速度を優先した。


⚡ 機能の実装ハイライト

1. カテゴリ検索 — URLパラメータ駆動

検索とカテゴリフィルタはURLパラメータで管理しています。

/services/prompt-stock?q=メール&category=ビジネス

この設計のメリット:

  1. ブックマーク可能 — フィルタ状態をURLで共有できる
  2. SEO対応 — 検索エンジンがカテゴリページをインデックス可能
  3. Server Component互換searchParams をサーバー側で受け取れる

stateではなくURLで状態管理することで、リロードしてもフィルタが保持されます。

2. ワンクリックコピー — Clipboard API

const handleCopy = async () => {
  await navigator.clipboard.writeText(content)
  // コピー数をバックグラウンドでインクリメント
  fetch("/api/services/prompt-stock/prompts", {
    method: "PATCH",
    body: JSON.stringify({ id, action: "copy" }),
  })
}

ポイント:

  • コピー自体は即座に完了(APIレスポンスを待たない)
  • カウント更新は fire-and-forget で非同期実行
  • ユーザー体感は0ms

3. AIプロンプト改善 — ストリーミング応答

AI改善機能は、入力されたプロンプトを分析して改善版を提案する機能です。

ユーザー入力 → API (Claude Haiku) → ストリーミング応答 → リアルタイム表示

通常のAPI呼び出しだと、全文生成完了まで数秒間の空白が生まれます。 ストリーミングにすることで、文字が生成されるそばから画面に表示されるため、体感待ち時間が大幅に短縮。

AIへの指示(システムプロンプト)では、改善の5つの観点を明示しています:

観点内容
目的の明確化何を達成したいのかを具体的に
出力形式の指定箇条書き・表・コードなど
コンテキスト追加前提条件や背景情報
制約条件の明示文字数・トーン・禁止事項
具体例の追加期待する出力のサンプル

4. いいね機能 — トグル式

いいねはログインユーザー限定で、同じプロンプトへの二重いいねは自動的に「取り消し」になります。

1回目のクリック → いいね追加 (♥ 0 → ♥ 1)
2回目のクリック → いいね取り消し (♥ 1 → ♥ 0)

DB上では (promptId, userId) のユニーク制約で二重登録を防止。 存在チェック → 存在すれば削除、なければ作成、という単純なロジックです。


🎨 デザインの意思決定

ダークグラデーション・ヒーロー

PromptStockのヒーローセクションには、紺〜紫のグラデーションを採用しました。

検討案却下理由
白背景 + カラフルアクセント他サービスと差別化しにくい
全面パーティクル演出テキストの可読性が落ちる
ダークグラデーション採用: 高級感 + テキスト映え + ダークモード親和性

カードUI — 情報の優先度設計

プロンプトカードには多くの情報を詰め込む必要がありました。 「一目で何のプロンプトかわかる」を目標に、情報の優先度を整理しました。

┌─────────────────────────────────┐
│ [カテゴリ]           コピー数   │  ← 分類 + 人気度
│                                 │
│ タイトル(太字)                │  ← 最重要: 何ができるか
│ 説明文(2行まで)              │  ← 補足: もう少し詳しく
│                                 │
│ ┌─────────────────────────┐    │
│ │ プロンプト本文プレビュー │    │  ← 中身のチラ見せ
│ └─────────────────────────┘    │
│                                 │
│ [タグ1] [タグ2] [タグ3]        │  ← 関連キーワード
│                                 │
│ [コピー]  [♥ いいね]           │  ← アクション
└─────────────────────────────────┘

レスポンシブ対応

画面サイズカラム数備考
モバイル (~640px)1列カード全幅表示
タブレット (~1024px)2列程よい密度
デスクトップ (1024px~)3列一覧性を最大化

🔒 セキュリティ対策

小規模サービスでも最低限のセキュリティは必須です。

対策実装
レート制限AI改善API: 10回/分(IP単位)
入力バリデーションプロンプト本文: 3000文字上限
認証チェックいいね機能: NextAuth セッション必須
CSRF対策Next.js のビルトイン対策に依存

レート制限の実装: 外部サービス(Upstash等)は使わず、インメモリのMap + タイムスタンプで実装。VPS単体構成なのでこれで十分。スケールアウト時にRedisに切り替える想定。


📊 SEO戦略

プロンプト辞典はSEO勝負のサービスです。検索流入を最大化するための施策:

ターゲットキーワード

優先度キーワード月間検索ボリューム(推定)
ChatGPT プロンプト テンプレート5,000+
プロンプト 例文3,000+
AI プロンプト 書き方2,000+
Claude プロンプト おすすめ1,000+

技術的SEO対策

  1. Server Components: 全ページSSR。クローラーがJSを実行せずにコンテンツ取得可能
  2. generateMetadata: 全ページに個別のtitle/description設定
  3. JSON-LD: WebApplicationスキーマで構造化データを提供
  4. canonical URL: 重複コンテンツ防止
  5. サイトマップ: 動的生成で全プロンプトページを網羅

😅 苦労したポイント

開発は順調ではありませんでした。正直に振り返ります。

1. Prismaのバージョン問題

最初Prisma 7を使おうとしたところ、設定方法が大幅に変更されていて互換性問題が多発。 結局Prisma 6にダウングレードして安定動作を確保しました。

学び: 最新バージョンが常に最善とは限らない。安定性を優先すべき場面がある。

2. Next.js の Middleware 廃止

PV計測をMiddlewareで実装しようとしたら、Next.jsの新バージョンでMiddlewareの仕様が変更。 クライアントコンポーネント + APIルートの構成に切り替えました。

Before: Middleware → DB更新(❌ 動かない)
After:  Client Component → API Route → DB更新(✅)

3. ビルド時のDB接続エラー

prisma.findMany() を使うページがビルド時にプリレンダリングされ、DB接続エラーに。 全ページに export const dynamic = "force-dynamic" を追加して解決。

学び: Server Componentsでデータベースアクセスするページは、プリレンダリングの挙動に要注意。


📈 今後のロードマップ

フェーズ内容目的
Phase 1プロンプト数を50件以上に拡充コンテンツ量でSEO強化
Phase 2人気ランキング機能エンゲージメント向上
Phase 3カテゴリ拡充(画像生成・動画等)新規ユーザー獲得
Phase 4プロンプトの効果測定機能差別化・リテンション

💡 学んだこと

この開発を通じて得た教訓をまとめます。

  1. YAGNI原則は正しい — 多言語化やキャッシュなど「将来必要かも」の機能は全部後回しにした。結果、コア機能の品質に集中できた
  2. 非正規化は怖くない — いいね数・コピー数の非正規化で一覧の表示速度が劇的に改善。整合性はトランザクションで担保すれば問題ない
  3. ストリーミングUXの効果は絶大 — AI応答の体感速度が全く違う。ユーザーが「動いている」と感じられることが重要
  4. URLパラメータ駆動の設計 — フィルタ状態をstateではなくURLで管理することで、ブックマーク・共有・SEOの全てが解決した

PromptStockは「AIをもっと使いこなしたい」すべての人のためのサービスです。 ぜひPromptStockを使ってみてください