トップページへ戻る
🐡

Fugu for All の作り方ガイド

「自分のAPIキーを入れるだけでAIと話せるWebアプリ」を、ゼロから作って世界に公開するまで。

完成形を見る → fugu-for-all.vercel.app

このアプリ「Fugu for All」とは

作り方に入る前に、まず完成品そのものを紹介します。「これ、自分も作ってみたい」と思えたら、そのまま下へ読み進めてください。どう作ったのかを最初から順に解説していきます。

Fugu for All は、Sakana社の新しいAI「Fugu(複数の優秀なAIをまとめて指揮する“まとめ役AI”)」と、日本語でチャットできるWebアプリです。ブラウザでURLを開き、自分の合言葉(APIキー)を入れるだけで、すぐに会話が始められます。

🎯 1. どんな人のためのもの?

  • ITやAIに詳しくない人が対象です。専門知識はゼロでも、最先端のAIを実際に触って体験できます。
  • たとえば「AIに詳しくない取引先や同僚に、Fuguを実際に試してもらいたい」といった場面を想定しています。難しい設定は不要で、URLを渡すだけ。
  • 画面はすべて日本語。パソコンでもスマートフォンでも見やすく作っています。

💬 2. どんなことができる?

  • Fugu と自由に日本語で会話できます。旅行プランづくり、長い文章の要約、献立の相談、考えごとの整理など、用途は何でも。
  • 用途に合わせて「標準(速い)」と「最高品質(じっくり)」を選べます。
  • 何を聞けばいいか迷っても大丈夫。ワンクリックのお手本を用意してあるので、押すだけで体験が始まります。
  • 答えは箇条書きや表も見やすく整えて表示。読みやすさにこだわっています。

🧭 3. どんな点に注意して作った?

  • 「最初の体験」を最優先。キーを入手して貼り付けるまでを、迷わない2ステップに整理しました。
  • 費用を最初に正直に伝える。Fuguは有料で、キー取得にはカード登録が必要・無料枠は無い——この事実を隠さず、最初の画面ではっきり告知します。
  • 待たせても不安にさせない。最高品質モデルは答えるまで数分かかることがあるため、経過秒数や「複数のAIに相談しています…」を表示し、「やめる」ボタンも用意しました。
  • 専門用語を避け、エラーもすべてやさしい日本語で案内します。

🔒 4. どれだけ安全?

  • APIキー(合言葉)は利用者のブラウザの中にだけ保存。アプリのサーバーには保存も記録もしません。サーバーは“通すだけ”の中継役です。
  • BYOK(各自が自分の鍵を使う)方式なので、「他人に勝手に使われて自分に高額請求が来る」という事故が構造的に起きません。料金は使った本人の負担です。
  • AIの答えは「生のHTMLを実行しない」安全な方法で表示し、悪意ある出力に乗っ取られないようにしています(XSS対策)。
  • 通信まわりの安全設定(CSPなどのヘッダ)も付けています。
  • サーバーに秘密情報を一切持たないので、公開URLをそのまま誰に配っても安全です。
そして——あなたにも作れます

これだけのことをしていても、心臓部のコードはわずか数十行です。難しい部分は Next.js と Vercel AI SDK という道具が肩代わりしてくれます。「考え方」さえ掴めば、それほど詳しくなくても十分に作れます。次の章から、実際にどう作ったのかを最初から順に解説していきます。

このガイドについて

ここからは、上で紹介した「Fugu for All」を実際にどう作ったのかを解説します。目標は、同じようなAIチャットアプリを、それほど詳しくない人でも作れるようになることです。コマンドやコードは1つずつ写して進められるよう、順を追って説明します。

用語:API / APIキー

APIとは「外部のサービスと機械的にやり取りするための窓口」のこと。APIキーは、その窓口を使うための“あなた専用の合言葉”です。これが無いとAIは応答してくれません。

対象HTMLを見たことはあるが専門家ではない方。コマンドを1行ずつ写して進められれば大丈夫です。
作るものAIと話せるWebアプリ(利用者が自分のAPIキーを入れて使う方式)
使う道具Next.js(ウェブ作成の枠組み)、Vercel AI SDK(AIと話す部品)、Vercel(公開する場所)
目安時間慣れていなくても半日ほど。AI(Claudeなど)に手伝ってもらえばさらに短く。
このアプリの一番の特徴:BYOK

BYOK(Bring Your Own Key=自分の鍵を持参)方式にしました。利用者それぞれが自分のAPIキーを使うので、アプリの作者に利用料がかからず、利用者情報を預かるデータベースも要りません。とてもシンプルで安全に作れます。

0. まず全体像をつかむ

コードを書く前に、「誰が誰と話すのか」を絵にしておくと、後がぐっと楽になります。登場人物は3人だけです。

🧑‍💻
① ブラウザ利用者の画面。
キーはここに保存
🛡️
② 自分のサーバー(Next.jsの裏方)
キーを中継するだけ
🐡
③ SakanaのAI本物のFugu。
答えを返す

利用者がメッセージを送ると、①ブラウザ → ②自分のサーバー → ③SakanaのAI、と伝わり、答えが同じ道を逆にたどって返ってきます。

なぜ「②自分のサーバー」を間にはさむの?

ブラウザから直接③のAIを呼べそうに見えますが、間に自分のサーバーを置くのには理由があります。

  • つながらない問題を避ける:ブラウザから他社のサービスを直接呼ぶと、セキュリティ上の制限(CORS)でブロックされがちです。自分のサーバー経由なら回避できます。
  • エラーを日本語にできる:AIからの英語エラーを、サーバーで「カギが正しくないようです」のようにやさしく言い換えられます。
  • 鍵を守る:鍵はブラウザに保存し、サーバーは“通すだけ”で保存しません。記録も残しません。
覚えておくと一生使える考え方

「画面(フロント)」と「裏方(サーバー)」を分け、秘密の合言葉は裏方を通す。これはAIアプリに限らず、ほとんどのWebアプリで共通の作法です。

1. 準備するもの

  1. Node.js(ノードジェイエス)を入れる … ウェブ作成の土台になる実行環境です。nodejs.org から最新版を入れます。
  2. 文字を書くエディタ … VS Code が定番。無料です。
  3. Vercel(バーセル)のアカウント … 完成したアプリを無料で公開できる場所。vercel.com で登録。
  4. SakanaのAPIキーconsole.sakana.ai で取得します(後述の注意点に要注意)。
⚠ 最初のつまずきポイント:キーは有料です

Fugu のAPIキーを作るには、クレジットカードの登録と有料契約が必要で、無料お試し枠はありません(月額20ドル〜、または使った分だけの従量課金)。「無料で気軽に」とはいかない点を、利用者にも最初に正直に伝える設計にしました(後述)。

2. 土台を1コマンドで作る

ゼロからファイルを並べる必要はありません。Next.js(ネクストジェイエス)という枠組みが、1つのコマンドで土台一式を用意してくれます。

用語:Next.js / ターミナル

Next.jsは「画面」と「裏方」を1つのプロジェクトでまとめて作れる、人気の枠組みです。ターミナル(黒い画面)は、文字でパソコンに命令する場所。VS Codeのメニューから開けます。

作りたいフォルダの中で、次の1行を実行します。

ターミナル
npx create-next-app@latest . --yes --typescript --app --tailwind --eslint --src-dir --import-alias "@/*" --use-npm

これで、TypeScript(型のある安全なJavaScript)と Tailwind(デザインを楽にする道具)込みの土台ができます。続けて、AIと話すための部品を追加します。

ターミナル
npm install ai@6 @ai-sdk/react@3 @ai-sdk/openai-compatible@2 zod react-markdown remark-gfm
追加した部品役割
ai / @ai-sdk/reactVercel AI SDK。AIとの会話・流れるような表示を簡単にしてくれる主役。
@ai-sdk/openai-compatible「OpenAI互換」のAIにつなぐ部品。Fugu はこれで繋がります。
react-markdownAIの答え(箇条書きや表)を見やすく整える。

できあがるフォルダの中身は、ざっくりこんな形です(このガイドで作るファイルに印を付けました)。

fugu-for-all/ ├─ src/ │ ├─ app/ │ │ ├─ layout.tsx ← ページの土台 │ │ ├─ page.tsx ← 表示の切り替え(入力画面 ↔ チャット) │ │ └─ api/ │ │ ├─ chat/route.ts ★ AIへの中継(裏方) │ │ └─ test-key/route.ts ★ 鍵の確認(裏方) │ ├─ components/ ← 画面の部品たち │ └─ lib/ ← 共通の小道具・設定 ├─ next.config.ts ← 安全設定など └─ package.json ← 部品の一覧

3. AIにつなぐ「裏方」を作る

アプリの心臓部です。裏方は2つだけ。(A) 鍵が正しいか確認する窓口と、(B) チャットを中継する窓口です。

まず共通の設定を1か所にまとめる

接続先や、エラーの日本語訳を1ファイルにまとめておくと、後で楽です。

src/lib/sakana.ts
// 接続先やモデル名を1か所に集約(変更に強くなる)
export const SAKANA_BASE_URL = "https://api.sakana.ai/v1";

export const MODELS = {
  fugu:         { id: "fugu",       short: "標準" },      // 速い・低コスト
  "fugu-ultra": { id: "fugu-ultra", short: "最高品質" },  // 高品質だが遅い
};
export const DEFAULT_MODEL = "fugu";
src/lib/errors.ts
// AIからの「番号付きエラー」を、やさしい日本語に翻訳する
export function mapStatusToJp(status) {
  if (status === 401 || status === 403)
    return "カギ(APIキー)が正しくないようです。貼り直してみてください。";
  if (status === 402)
    return "残高が不足しているようです。Sakanaのコンソールでご確認ください。";
  if (status === 429)
    return "アクセスが集中しています。少し待ってからお試しください。";
  if (status >= 500)
    return "Sakana側で一時的な問題が起きているようです。";
  return "接続に失敗しました。APIキーや通信環境をご確認ください。";
}

(A) 鍵が正しいか確認する窓口

利用者が鍵を貼り付けたら、いきなりチャットさせる前に「この鍵、本当に使える?」を確かめます。ポイントはお金がかからない方法で確認すること。AIに文章を生成させると課金されるので、「使えるモデルの一覧をのぞくだけ」GET /v1/models)にしました。これなら無料です。

src/app/api/test-key/route.ts
import { SAKANA_BASE_URL } from "@/lib/sakana";
import { mapStatusToJp } from "@/lib/errors";

export async function POST(req) {
  const { apiKey } = await req.json();
  if (!apiKey)
    return Response.json({ ok: false, message: "APIキーを入力してください。" });

  // モデル一覧をのぞくだけ=課金されない鍵チェック
  const r = await fetch(`${SAKANA_BASE_URL}/models`, {
    headers: { Authorization: `Bearer ${apiKey}` },  // ← 合言葉を添えて送る
  });
  if (r.ok) return Response.json({ ok: true, message: "接続に成功しました。" });
  return Response.json({ ok: false, message: mapStatusToJp(r.status) });
}
用語:Authorization: Bearer

これは「持参人(Bearer)=この合言葉を持っている人を本人として扱ってください」という、合言葉の渡し方の決まり文句です。多くのAIサービスで共通です。

(B) チャットを中継する窓口(心臓部)

ここが一番の山場ですが、AI SDKのおかげで驚くほど短く書けます。やることは「利用者の鍵で接続を用意し、AIの答えを少しずつ流れるように返す」だけです。

src/app/api/chat/route.ts
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
import { convertToModelMessages, streamText } from "ai";
import { SAKANA_BASE_URL } from "@/lib/sakana";

export const maxDuration = 300;  // 最長5分まで待つ(遅いモデル対策。後述)

export async function POST(req) {
  const { messages, apiKey, model } = await req.json();

  // 利用者の鍵で「使い捨ての接続」を作る。保存も記録もしない。
  const sakana = createOpenAICompatible({
    name: "sakana",
    baseURL: SAKANA_BASE_URL,
    apiKey,  // ← 自動で「Bearer 合言葉」を付けてくれる
  });

  // AIに渡し、答えを少しずつ流す
  const result = streamText({
    model: sakana(model),
    messages: await convertToModelMessages(messages),
  });

  return result.toUIMessageStreamResponse({
    onError: (e) => "送信中にエラーが発生しました。APIキーや残高をご確認ください。",
  });
}

たったこれだけで「流れるように表示されるAIチャット」の裏方が完成します。streamText が会話を送り、toUIMessageStreamResponse が答えを少しずつ画面に流す形に整えてくれます。

なぜ「OpenAI互換」だと簡単なのか

Fugu は「OpenAI互換」という共通の作法に従っています。だから、接続先(baseURL)を変えるだけで同じ部品が使えます。これは後の「応用」章で効いてきます。

4. 画面を作る

画面は大きく2つ。(1) 鍵を入れてもらう案内画面と、(2) チャット画面です。鍵があるかどうかで自動的に切り替えます。

鍵はブラウザに保存する

鍵はサーバーに送って保存…ではなく、利用者のブラウザの中(localStorage)だけに保存します。これがBYOKの安全さの核心です。

src/lib/useApiKey.ts(要点)
// 鍵をブラウザに保存・読み出し・削除するだけの小道具
localStorage.setItem("sakana_api_key", key);   // 保存
localStorage.getItem("sakana_api_key");        // 読み出し
localStorage.removeItem("sakana_api_key");     // 削除

チャット画面の核心

AI SDK の useChat という部品が、メッセージの一覧・送信・「考え中…」の状態まで面倒を見てくれます。私たちがやるのは、毎回の送信に“利用者の鍵とモデル”をこっそり同梱することだけです。

src/components/Chat.tsx(要点)
const transport = new DefaultChatTransport({
  api: "/api/chat",                       // さっき作った裏方へ送る
  prepareSendMessagesRequest: ({ messages }) => ({
    body: { messages, apiKey, model },     // ← 鍵とモデルを毎回同梱
  }),
});

const { messages, sendMessage, status, stop } = useChat({ transport });

// 送信ボタンや「お手本」クリックでこれを呼ぶだけ
sendMessage({ text: "週末の旅行プランを立てて" });

あとは messages を画面に並べ、AIの答えは react-markdown で見やすく表示します。「考え中…」の状態(status)を使えば、待ち時間の表示や「やめる」ボタンも作れます。

非エンジニア向けに効いた工夫

対象が「ITに詳しくない人」だったので、①費用が要ることを最初に正直に告知②鍵の入手手順を①②③で図解③遅いモデルでは「複数のAIに相談中…」と経過秒数を表示して“固まったように見える”のを防ぎました。技術より、この“最初の体験”の配慮が満足度を大きく左右します。

5. 動かして確かめる

自分のパソコンで動かしてみます。

ターミナル
npm run dev

表示された http://localhost:3000 をブラウザで開けば、もう動いています。

鍵がまだ無くても確認できること

わざと間違った鍵を入れてみてください。「カギが正しくないようです」と日本語で出れば、裏方とSakanaの接続・エラー翻訳が正しく動いている証拠です。実際この方法で、本物の鍵を使う前に“配線”の大部分を確認しました。

6. 世界に公開する

手元で動いたら、Vercel に上げて、誰でも開けるURLにします。Vercelは Next.js と相性が良く、無料枠で十分です。

ターミナル
npm i -g vercel        # Vercelの道具を入れる(初回のみ)
vercel --prod --yes    # 公開! URLが表示される

初回は「ログインしますか?」と聞かれるのでブラウザで承認します。あとは数十秒で、https://〇〇.vercel.app という公開URLが手に入ります(このアプリは fugu-for-all.vercel.app)。

秘密が無いから公開URLを配って安全

鍵は各利用者のブラウザにしか無く、サーバー側に秘密情報を一切持ちません。だから公開URLをそのまま配っても安全です。

7. つまずきと学び

実際に作る中でぶつかった「ここ大事」を共有します。同じ穴を避けられます。

① 無料枠は無い、と最初に伝える

「すぐ体験」を謳いたくても、鍵の取得にカード登録が要ると、慣れない人はそこで離脱します。ごまかさず最初に正直に告知したほうが、結局は信頼されます。

② 遅いAIは「固まった」と誤解される

最高品質モデルは答えるまで1〜5分かかることがあります。何も出ないと普通の人は「壊れた」と思いリロードし、せっかくの(課金された)答えを失います。経過秒数・進捗バー・「やめる」ボタンを用意して安心感を作りました。

⚠ 上級コラム:あわや“無言で止まる”バグ

「長時間かかったら中断する」処理を、AI SDK の中断スイッチ(abortSignal)に時間切れを混ぜて実装したところ、SDKがそれを「正常な中断」と解釈して、エラー通知に届かず無言で止まる不具合になりました。

正解は、時間切れを「接続(fetch)の側」に置くこと。そうすると“本物のエラー”として扱われ、ちゃんと日本語メッセージが出ます。この問題は、複数のAIに互いのコードを批判的にレビューさせる工程で発見・修正できました。「自分の書いたものを、別の視点でわざと粗探しさせる」のは効果絶大です。

③ 鍵を守る・出力で乗っ取られない

鍵はブラウザのみ保存、サーバーは記録しない。さらにAIの答えは「生のHTMLを表示しない安全な方法」で描画し、悪意ある出力でブラウザを乗っ取られないようにしました(XSS対策)。

8. 応用:他のAIでも同じ作りで

このアプリの作りは Fugu 専用ではありません。「OpenAI互換」のAIなら、接続先(baseURL)とモデル名を差し替えるだけで、ほぼそのまま使えます。

変えるところ
SAKANA_BASE_URL別のAIサービスの接続先URLに差し替え
MODELSそのサービスのモデル名に差し替え

つまり一度この形を覚えれば、いろいろなAIで「自分専用チャットアプリ」を量産できます。

AIに作ってもらうのも近道

このアプリ自体、AIコーディング支援(Claude Code)と一緒に作りました。「Next.jsでOpenAI互換APIに繋ぐBYOKチャットを作って」と頼み、出てきたコードを1つずつ確認していけば、未経験でも十分到達できます。

まとめ:作る順番のチェックリスト

  1. 全体像を絵にする(ブラウザ → 自分のサーバー → AI)
  2. 土台を1コマンドで作る(create-next-app + 部品の追加)
  3. 裏方を2つ作る(鍵チェック + チャット中継)
  4. 画面を2つ作る(鍵の案内 + チャット)
  5. 手元で動作確認(間違った鍵で日本語エラーを確認)
  6. Vercelで公開vercel --prod
  7. 使う人の身になって気配り(費用の告知・待ち時間表示)

難しそうに見えて、心臓部のコードは数十行です。AI SDK と Next.js が大半を肩代わりしてくれるので、「考え方」さえ掴めば、それほど詳しくなくても十分作れます。ぜひ自分のアイデアで作ってみてください。