個人投資家向けの自作株式研究アプリをNext.js + Claude Codeで作った話
はじめに
日本株を個人で買い始めてから、こんな悩みが積み重なっていきました。
- S証券のポートフォリオだと分析しにくい
- 「あのとき買った理由なんだっけ?」が残っていない
- 紙トレード(シミュレーション)を本物の取引と混ぜて管理すると把握できなくなる
- 既存のポートフォリオデータをAIに投げるとき、毎回手入力が必要でめんどくさい
「欲しいものを作ればいい」ということで、自分専用の投資リサーチWebアプリを作りました。この記事ではアーキテクチャの設計思想と、いくつかこだわった実装ポイントを紹介します。
作ったもの
投資リサーチアプリ。個人投資家のための日本株専用ツールです。
| 機能 | 説明 |
|---|---|
| ポートフォリオ管理 | 実取引の保有ポジション・実現損益をリアルタイム表示 |
| シミュレーション | 仮想資金100,000円で紙トレードできる専用ページ |
| 株価チャート | lightweight-chartsで目標株価・損切りラインを可視化 |
| リサーチノート | 銘柄ごとに追記できるメモ(AIの分析結果も保存) |
| ウォッチリスト | 気になる銘柄を登録して一覧表示 |
| ニュース | Google NewsのRSSをフィードとして表示 |
| Geminiチャット | ポートフォリオ画面に常駐するAIアドバイザーパネル |
AIを2つの層に分けた
このアプリではAIとの連携を用途に応じて2つの層で実装しています。
層1:Claude Code CLI(深い分析・DB書き込み)
PCのターミナルから使うClaude Code CLIが、Turso上のDBを直接読み書きします。
Claude Code CLI → Turso DB → ResearchNote に分析を書き込む → Web に反映
深い分析・過去ノートの参照・売買判断の記録など、腰を据えて考えるときはこちらを使います。
層2:Gemini API(画面内のクイックチャット)
Webアプリのポートフォリオページとシミュレーションページに、Gemini APIを使ったチャットパネルを常駐させています。無料枠(gemini-3-flash-preview)で動かしているため追加コストなし。
スマホブラウザ → Geminiチャットパネル → サッと相場観を聞く
PCのターミナルを開くほどでもない「ちょっと聞きたい」場面でこちらを使います。Vercelにデプロイ済みなのでスマホからもアクセスでき、外出先でも画面を開けばそのまま質問できます。
2層構成にした理由
| Claude Code CLI | Gemini チャット | |
|---|---|---|
| 用途 | 深い分析・DBへの書き込み | 素早い相場感の確認 |
| 使う場所 | PCのターミナル | ブラウザ(PC・スマホ共通) |
| コスト | Claude Proプラン内 | 無料枠 |
| DBアクセス | あり(読み書き) | なし |
「DBに残すほどでもないが聞きたい」という場面は意外と多く、Geminiチャットをインライン化したことで使用頻度が上がりました。
技術スタック
フレームワーク: Next.js 16 (App Router) + React 19
UIライブラリ: MUI v9 (Material Design 3 風テーマ)
ORM: Prisma v7
DB: Turso(SQLiteクラウド) + @prisma/adapter-libsql
ホスティング: Vercel
チャート: lightweight-charts v5
データ: yahoo-finance2 (株価・ヒストリカル)
ニュース: Google News RSS + rss-parser
AI: Claude Code CLI + Google Gemini API(無料枠)
フォント: Noto Sans JP / Inter / JetBrains Mono
Turso + Vercel へ
もともとローカルのSQLiteで開発していましたが、Turso(SQLiteのクラウドホスティング)+ Vercelへの移行は完了済みです。
移行のポイントはsrc/lib/prisma.tsだけです。PrismaがlibSQLアダプター経由でTursoに対応しているので、接続先を書き換えるだけで既存のコードはそのまま動きます。
// src/lib/prisma.ts
import { PrismaClient } from '@prisma/client'
import { PrismaLibSQL } from '@prisma/adapter-libsql'
import { createClient } from '@libsql/client'
const libsql = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN,
})
export const prisma = new PrismaClient({
adapter: new PrismaLibSQL(libsql),
})
スキーマのproviderはsqliteのまま変更不要。データ構造・Prismaの使い方・マイグレーションのフローは一切変わりません。
Claude Code CLIからも.env.localにTURSO_DATABASE_URLを設定しておけば、同じTurso上のDBに書き込めます。PCからCLIで分析した結果が、そのままスマホのブラウザに反映される状態になっています。
まとめ
- AIを2層に分けた:深い分析はClaude Code CLI、手軽な質問はGemini APIの画面内チャット
- Turso + Vercel でクラウド化し、PCでもスマホでも同じDBを参照できる
「自分が使うためのツール」なので機能を絞って作るのが意外と難しく、ついあれこれ追加したくなります。でも余計な機能を足すより、今ある機能を使いこんで判断の質を上げる方が大事だなと感じています。
