🤖

LLM以外は無料で回す。Vercel × Supabase × Inngest × Render × Claude 4.5でAI要約基盤

に公開

はじめに

技術記事を保存する。でも読まない。

あとで読む、時間があるときに読む、週末に読む。
そうやって raindrop.io にリンクが積み上がっていく。

エンジニアなら心当たりがあるはずです。

その状況をどうにかしたくて作ったのが raindary というAI要約基盤です。

  • raindrop.io に保存した記事を取得
  • 本文を抽出
  • Claude 4.5 で事実整理+要約生成
  • トーン付きで保存

ソースコードは公開しています。

https://github.com/enjoydarts/raindary

この記事では「どう作ったか」ではなく、どう設計したかを中心に書きます。

テーマは明確です。

LLM以外は無料プランで回す

AIアプリはコストが高い、という印象があります。
しかし設計を工夫すれば、ランニングコストはClaudeのトークン消費だけにできます。

設計の出発点

raindaryはRSSリーダーではありません。

記事管理は raindrop.io に完全に任せています。

raindrop.ioは単なるブックマークサービスではなく、OAuth2とREST APIを提供する外部データ基盤です。

つまり、

  • 記事URL
  • タイトル
  • タグ
  • 保存日時

をAPIで取得できる。

ここで重要なのは「一次データを持たない」という方針です。

raindaryは記事データをコピーしません。
保存するのはAIが生成した要約のみ。

これにより:

  • データ重複を防げる
  • 記事削除と同期できる
  • 設計がシンプルになる

外部サービスを信頼し、自分は付加価値層に集中する。
これが最初の設計思想です。

技術スタック全体像

現在の構成は以下です。

  • フロントエンド / 軽量API: Next.js 15(Vercel Hobby)
  • 非同期処理: Inngest Cloud(Hobby)
  • 本文抽出: FastAPI + trafilatura(Render Free)
  • データベース: Supabase PostgreSQL(Free)
  • LLM: Claude Haiku 4.5 / Claude Sonnet 4.5

ポイントは、LLM以外はすべて無料プランで構成していることです。

Vercel × Next.js 15

フロントエンドとAPIはVercel上で動いています。

プランは Hobby(無料)

Next.js 15のApp Routerを使い、

  • Raindrop OAuth受付
  • APIエンドポイント
  • ダッシュボードUI

を実装しています。

重要なのは、

Vercelで重い処理をしないこと

  • 本文抽出
  • LLM呼び出し

はすべて非同期イベントに逃がしています。

Serverlessは「軽い入り口」として使い、
重い処理は外に出す。この割り切りが重要です。

非同期設計(Inngest)

重い処理はInngest Cloudで管理しています。

Inngestはイベント駆動型のワークフローサービスです。

raindaryでは以下のイベントを使っています。

  • import.requested
  • extract.requested
  • summarize.requested

UIはイベントを投げるだけ。
実処理はすべてバックグラウンドで行われます。

Inngestを使うことで、

  • リトライ
  • 並列制御
  • エラーハンドリング

を宣言的に管理できます。

ワーカーを自前で持たなくてよいのは、個人開発では非常に大きいです。


Render(Free)で本文抽出

本文抽出にはPythonの trafilatura を使っています。

HTMLから本文だけを抽出する精度が高く、
技術ブログのような記事でも安定します。

これをFastAPIとしてRenderに常駐させています。

プランは Render Free

注意点があります。

RenderのFree Web Serviceは、

約15分間リクエストがないとスリープする

という仕様があります。

次のアクセスでコールドスタートが発生します。

しかしraindaryは非同期設計です。

  • ユーザーは待たない
  • 抽出はバックグラウンドで行う

ため、この制限は許容できます。

設計によって無料プランでも成立させています。

Claude 4.5の使い分け

LLMは2段階構成にしています。

1. 事実抽出:Claude Haiku 4.5

価格(標準API):

  • 入力 $1 / 1M tokens
  • 出力 $5 / 1M tokens

本文をそのまま文章生成に使うのではなく、
まず構造化JSONに変換します。

抽出する情報は:

  • keyPoints
  • mainClaim
  • caveats
  • techKeywords

軽量モデルで十分です。

2. 要約生成:Claude Sonnet 4.5

価格(標準API):

  • 入力 $3 / 1M tokens
  • 出力 $15 / 1M tokens

最終的な文章生成を担当します。

トーンは:

  • snarky
  • neutral
  • enthusiastic
  • casual

などを切り替え可能にしています。

なぜ2段階にするのか

Sonnetに全文を直接投げると、

  • トークン消費が増える
  • コストが増える
  • 出力が不安定になる

そこで、

  1. Haikuで圧縮
  2. Sonnetで文章生成

という構造にしています。

これは単なるコスト削減ではなく、
出力品質の安定化にもつながっています。

コストは必ず可視化する

AIアプリで一番危険なのは、

コストが見えないこと

raindaryでは api_usage テーブルを持ち、

  • input_tokens
  • output_tokens
  • cost_usd
  • model

を保存しています。

月間コストを集計できる設計です。

AIアプリは「作る」よりも「回す」ことの方が難しい。
だからこそ、コストは最初から可視化します。

Supabase Freeでのマルチユーザー設計

データベースはSupabase Freeプラン。

全テーブルに user_id を持たせ、
Row Level Security(RLS)で隔離しています。

ポリシーはシンプルです。

auth.uid() = user_id

これにより、

  • 他ユーザーのデータは見えない
  • APIバグでも漏洩しない

という設計になります。

AIアプリでもセキュリティは妥協しません。

LLM以外は無料で回る構成

現在の構成は以下です。

  • Vercel Hobby
  • Supabase Free
  • Inngest Hobby
  • Render Free
  • Claude APIのみ有料

つまり、ランニングコストはClaudeのトークン消費だけ。

この構成を成立させるために、

  • 非同期前提
  • 重処理分離
  • コールドスタート許容
  • コスト可視化

を徹底しています。

まとめ

raindaryは単なるAI要約ツールではありません。

  • 責務分離設計
  • 非同期アーキテクチャ
  • コスト最適化
  • 無料枠活用
  • RLSによる安全設計

を意識した基盤プロジェクトです。

コードはこちらにあります。

https://github.com/enjoydarts/raindary

AIアプリは派手なデモよりも、
地味な設計で差が出ると考えています。

今後はRSS日次サマライズや分析基盤への拡張も検討しています。

設計で勝ちたい人の参考になれば幸いです。

技術設計や個人開発についてはブログでも発信しています。
こちらも是非、よろしくお願いします!

https://enjoydarts.blog/

Discussion