はじめに
お盆で久々に実家に帰りました。ひさびさの家族団らんで和気あいあいと過ごしていたのですが、ふと、自分の意見が無いことに気づきました。例えば、「秋のお墓参り行くのか」という話題で、自分はまっさきにchatGPTに行くべきかを聞こうとしたのです。自分軸が無くなっているというか、自分の頭で考えることを放棄してしまっている自分に気づき、危機感を覚えました。
思えば、明快な回答をくれるAIに依存してしまっていたように思います。仕事もcursorエージェントに依存し、日常生活もchatGPT任せであれば、「お墓参りに行くか?」という簡単な質問にも答えられないほどに思考力が劣ってしまうのも無理はありません。
このような経緯で、私は「自分の意見を持つ」トレーニングができるサービスを作りたいと思いました。
作ったもの
サービス名(仮):意見力トレーニング
1日3問のランダム質問に45秒で即答
AIが「結論の明確さ / 理由の妥当性 / 視点の多様性」をスコア化
回答履歴から過去の自分を振り返れる
技術構成
フロントエンド:Next.js 14(App Router) + TypeScript + Tailwind CSS
バックエンド & DB:Supabase(Auth / Postgres / RLS / RPC)
AI評価:OpenAI Chat Completions API
ホスティング:Vercel
認証:Next Auth
実装ポイント
・日次固定のランダム出題(Supabase RPC)
daily_setsテーブルに「ユーザー×日付×質問IDs」を保存
初回アクセス時にRPC get_or_create_daily_set()で確定
JST基準で日付を決定
create or replace function public.get_or_create_daily_set(...)
returns public.daily_sets ...
・認証(NextAuth)
ProviderにEmailProviderを設定(Magic Link)
ユーザー情報はNextAuthのsessionで管理し、Supabaseのuser_idと紐付け
セッションのないアクセスは/loginへリダイレクト
import NextAuth from "next-auth";
import EmailProvider from "next-auth/providers/email";
export default NextAuth({
providers: [
EmailProvider({ server: process.env.EMAIL_SERVER, from: process.env.EMAIL_FROM })
],
callbacks: {
async session({ session, token }) {
session.user.id = token.sub;
return session;
}
}
});
・回答とAIフィードバック
/api/answerで回答をSupabaseに保存
その直後にOpenAI APIを呼び、スコアと短評をfeedbackテーブルへ保存
出力は必ずJSONに統一し、型安全に処理
const result = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [
{ role: "system", content: "あなたは採点官です…" },
{ role: "user", content: JSON.stringify({ question, answer }) }
],
response_format: { type: "json_object" }
});
・RLS(Row Level Security)
answersやfeedbackはログインユーザーのみ参照可
service_roleキーはAPI Routesのみで使用(クライアントには渡さない)
・開発時間配分
2時間:スキーマ設計+Supabaseセットアップ(RPC含む)
1.5時間:NextAuth設定
1.5時間:UI(出題/回答/履歴)
1時間:OpenAI連携
0.5時間:Seedデータ&動作確認
ぜひ試してみてください!