1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

個人開発のアイデアをAIで深掘りするツールを作った話

1
Posted at

個人開発のアイデアをAIで深掘りするツールを作った話 — Next.js + Supabase + Claude Code

はじめに

個人開発のアイデアって、なぜか外にいるときに思いつく。

電車の中、昼休み、散歩中。でも家に戻るころにはほとんど忘れている。かろうじてメモしても、後で見返すとコンテキストが薄くて「あれ、これ何がしたかったんだっけ」となる。

そしていざAIに相談しようとすると、アイデアが散らばっていてプロンプトをまとめるだけで時間がかかる。

この流れをなんとかしたくて IdeaPosting を作りました。

IdeaPostingとは

「お題(テーマ)」と「メモ(アイデア)」の2階層でアイデアを整理するWebアプリです。

image.png

主な機能:

  • お題 × メモ管理: テーマごとにアイデアを紐づけて整理
  • AIヒント: メモ内容をもとにClaude Haikuが深掘りのヒントを提案
  • AI前提情報: お題ごとに背景・制約をAIに渡せる(プロジェクトの文脈を記憶させる)
  • MDエクスポート: 整理したアイデアをMarkdownで出力 → そのままAIへの指示プロンプトになる
  • ステータス管理: todo / done / rejected でメモを分類
  • ドラッグ&ドロップ並び替え
  • モバイル対応(外でさっとメモできる)

技術スタック

カテゴリ 採用技術
フレームワーク Next.js 16 (App Router) / React 19 / TypeScript 5
DB Supabase (PostgreSQL + RLS)
認証 Supabase Auth (メール/パスワード)
DBクライアント @supabase/supabase-js v2 + @supabase/ssr (SSR/クライアント分離)
AI Anthropic Claude Haiku (claude-haiku-4-5-20251001) + Vercel AI SDK
スタイリング Tailwind CSS v4 + shadcn/ui (Radix UI)
ドラッグ&ドロップ @dnd-kit (core / sortable / utilities)
アイコン Lucide React
CI/CD GitHub Actions Self-hosted Runner
デプロイ Ubuntu + PM2 + Nginx + Cloudflare Tunnel

実装で面白かった点

1. ユーザーごとにAnthropicのAPIキーを管理する

「アプリ側でAPIキーを持つ」のではなく「ユーザーが自分のキーを登録して使う」設計にしました。

理由: 個人開発ツールなのでサーバー側のAPI費用を持ちたくなかった。

CREATE TABLE public.user_settings (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID UNIQUE REFERENCES auth.users(id),
  anthropic_api_key TEXT,
  updated_at TIMESTAMPTZ DEFAULT now()
);

ALTER TABLE public.user_settings ENABLE ROW LEVEL SECURITY;
CREATE POLICY "owner_only" ON public.user_settings
  FOR ALL USING (auth.uid() = user_id)
  WITH CHECK (auth.uid() = user_id);

RLSで他ユーザーのキーが見えないようにしつつ、Route Handler側でサーバーから取得して使う:

// app/api/ai-hint/route.ts
const supabase = await createServerSupabaseClient();
const { data: settings } = await supabase
  .from('user_settings')
  .select('anthropic_api_key')
  .single();

const anthropic = createAnthropic({ apiKey: settings.anthropic_api_key });
const { text } = await generateText({
  model: anthropic('claude-haiku-4-5-20251001'),
  prompt: ...,
  maxTokens: 120,
});

クライアントにAPIキーを露出させずに済む点がポイントです。

2. お題単位の「AI前提情報」

AIにヒントをもらうとき、プロジェクトの背景を毎回書くのが面倒。そこでお題ごとに前提情報を設定できる機能を追加しました。

// ヒント生成時のプロンプト
const prompt = topicContext
  ? `【前提情報】\n${topicContext}\n\n【お題】${topicTitle}\n【メモ】${content}`
  : `【お題】${topicTitle}\n【メモ】${content}`;

topics.context カラムに保存し、AIヒント・AIエクスポートの両方で参照します。

3. モバイルでのドラッグ&ドロップ対応

@dnd-kitPointerSensor だとモバイルでclickイベントが消えてしまう問題があったので、MouseSensor + TouchSensor に分けました:

const mouseSensor = useSensor(MouseSensor, { activationConstraint: { distance: 8 } });
const touchSensor = useSensor(TouchSensor, {
  activationConstraint: { delay: 250, tolerance: 5 },
});

delay: 250ms の長押しでドラッグ開始、短タップはclickとして通す設定です。

デプロイ構成

MAP-E接続の自宅サーバーにデプロイしています。外部ポート開放なしでHTTPS公開できるCloudflare Tunnelが便利でした。

外部 → Cloudflare (HTTPS) → Cloudflare Tunnel → Nginx :80 → PM2/Next.js :3000

CI/CDはGitHub ActionsのSelf-hosted Runnerで、masterマージ → 自動デプロイしています。

今後やりたいこと

  • オンボーディング改善(初回ログイン時にサンプルデータを用意)
  • フィードバック機能
  • Product Hunt への出品

おわりに

使ってみてもらえると嬉しいです: https://www.naozi.jp

感想・フィードバックはXのDMまたは記事のコメントで歓迎します。


1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?