まあ自分のアイデアではないのですが、良いアイデアだったので作ってみました。
タイトル通りですが、AIに指示をだしたらすぐ小さなツールを作らせることができるアプリです。
この記事ではしたことやハマったことを説明します。
まず、何をした?
まずはアイデアをAIに説明してMVPを作らせました。
AIでつくるとslopなところがたくさんあるので自分が指摘したり編集したりして良い感じに修正しました。
ai slopなところ
- Heroの一番上に
tracking-fullの大文字で書いてあるYOUR LITTLE SUPERPOWERSなど - UIにある無駄な説明文(当たり前のこと、技術スタックの記載)やカード
これを修正すればだいたい良いUIにはなります。これどうにかならないんですかね。
最初はデザインがVanilla CSSだったので、管理しやすいshadcn/ui、Tailwind CSSに変更しました。
仕組み
わかりにくいのでステップ式でコードの実際の流れに合わせて書き直しました。
クライアント(ブラウザ)
「ツールをつくる」や「AIで調整」から、依頼文をサーバーに送信(JSON)
- 調整のときは、元のツールの情報も一緒に送る
↓
サーバー(Cloudflare Workers)
生成を始める前のチェック
- 同じサイトからのリクエストか、形式が正しいかを確認
- 送信者の特定、使用制限の確認(と1回分の確保)
- 調整のときは、元のツールをDBから読み込む(自分のツールかも確認)
チェックが通ったら、OpenRouter に接続
- システムプロンプトで、作り方と安全ルール(外部通信やページ移動をしない、など)を指示
- ストリームで出力を少しずつ受け取るようにする
↓
OpenRouter(AI)
次の2つの関数を呼ぶ形で応答する(tool calling)
report_progress:「〜しています」という進行状況submit_tool:完成したツール(名前・説明・カテゴリ・HTML)
↓
サーバー
(生成中)受け取ったストリームをもとに、進行状況をクライアントへ1行ずつ送信
report_progressの内容と、コードを書いた量から進み具合(%)を計算
(生成終了)
- AIの出力を検証(形式のチェックと、危ないコードの機械的な検査)
- 検査で引っかかったら、理由を添えてAIに1回だけ作り直させる。それでもだめなら失敗にする
- 問題なければDBに保存(調整のときは、公開を解除して上書き)
- 失敗したときは、確保していた生成回数を返す
- 最後に、結果(ツールのデータ)をクライアントへ送信
↓
クライアント
(生成中)送られてきた進行状況を、メッセージとプログレスバーで表示
(生成終了)受け取ったツールのデータを一覧に追加し(ブラウザにも保存)、ツールを開く
- ツールのHTMLに、安全のための仕組み(CSP、防御用のスクリプト、テーマや入力内容の保存のしくみ)を加えて、ひとつの文書にまとめる
- それを、本体とは隔離された別のサイトにある実行用ページへ送る。ツールはそこで、
sandbox付きの iframe として動く - 実行用ページは、ページ移動を止める仕組みなどを先に組み込んでから、ツールを表示する
- 表示されたら、保存済みの入力内容を復元する
技術スタック
フロントからバックエンド、DBまで、ほぼCloudflareのエコシステムとTypeScriptで統一しました。(理由は後述)
フロントエンド:React + TanStack Start + Vite
Reactをベースに、フルスタックフレームワークとしてTanStack Startを採用しました。ビルドはVite。
TanStack Startを採用した理由は、Next.jsが不要で軽いからです。Next.jsにすると自分の環境ではビルドに時間がかかるし、開発サーバーは重いし、メモリも使うしでとりあえずで使えるようなものではないです。別にNext.jsにしたからといって特にメリットがなかったのでTanStack Startにしました。
ReactとViteを採用した理由は、Reactはいつも使っていてメンテナンスがしやすいというところ、ViteはTanStack Startと相性が良いので使いました。
スタイリング:Tailwind CSS + shadcn/ui
UIはTailwind CSS、ボタンなどのコンポーネントはshadcn/uiを使ってます。CSSで配色や角丸、フォントを簡単に設定できるので使いました。まあいつも使っているというのが一番の理由ですね。
実行環境とDB:Cloudflare Workers + D1
サーバーはCloudflare Workers、データベースはD1(SQLite互換)です。フロントからDBまで同じ基盤に載せられるので、デプロイやインフラ管理がシンプルになります。
Workersを採用した理由は、VPSサーバーを使わなくていいし、D1と併用することでDB操作が爆速になるからです。自分はVPSサーバーも持っているのですが、リソース的な問題でプロジェクトを移行していたところなのでWorkersにしました。
D1を採用した理由は、今さっきも言いましたがWorkersとの併用が最適だからです。
ORM:Drizzle ORM
ORMはDrizzle ORMを使っています。使った理由は自分が思う中で良いORMが他にないからです。Type-safeでいつも使っていて保守しやすいからです。
マイグレーションをするときはWranglerを使っています。
テスト:Vitest
テストはVitest。Viteとの連携が良さそうなのでこれにしました。あとはテストフレームワークをこれとBunしかしらないからです。
セキュリティ(ハマったこと)
ハマったことの一番はセキュリティです。長すぎてこの記事がセキュリティの記事になるので、別の記事に移動しました。
別記事に書いてあるのでぜひ見てください!
最後に
大々的に公開するための準備やXなどでの宣伝を今後やりたい。
一日10回まで生成できるので、みんなも使ってみてほしい。
バグがあったらXの@raic_devにぜひご報告を。


No comments yet