<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: スシロー</title>
    <description>The latest articles on DEV Community by スシロー (@_7fb6011b57d383122b5a).</description>
    <link>https://dev.to/_7fb6011b57d383122b5a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3961264%2F2e714c99-1c5a-4fcf-bb02-a7c8fe542faf.jpg</url>
      <title>DEV Community: スシロー</title>
      <link>https://dev.to/_7fb6011b57d383122b5a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/_7fb6011b57d383122b5a"/>
    <language>en</language>
    <item>
      <title>2026年版: Next.jsエージェント開発でルールファイルを書く実践ガイド</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Fri, 19 Jun 2026 02:04:46 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026nian-ban-nextjsezientokai-fa-deruruhuairuwoshu-kushi-jian-gaido-3nbk</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026nian-ban-nextjsezientokai-fa-deruruhuairuwoshu-kushi-jian-gaido-3nbk</guid>
      <description>&lt;h2&gt;
  
  
  なぜルールファイルがAIエージェントに効くのか
&lt;/h2&gt;

&lt;p&gt;Claude CodeやCursor、OpenAI Agentsなどのコーディングエージェントは、プロジェクトルートに置かれた&lt;code&gt;CLAUDE.md&lt;/code&gt;・&lt;code&gt;.cursorrules&lt;/code&gt;・&lt;code&gt;AGENTS.md&lt;/code&gt;を会話コンテキストの先頭に自動注入する。つまり「毎回口頭で言わなければならなかった制約」を一度書くだけで全セッションに効かせられる。&lt;/p&gt;

&lt;p&gt;Next.js App Router × TypeScript プロジェクトでは特に次の問題が頻出する。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pages/&lt;/code&gt; ディレクトリに新規ルートを作ろうとする（旧Router混入）&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;'use client'&lt;/code&gt; を付け忘れてサーバーコンポーネントからフックを呼ぶ&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fetch&lt;/code&gt; をクライアントコンポーネントで直書きし、キャッシュ戦略が消える&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;any&lt;/code&gt; 型を多用して型安全が崩壊する&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;これらはすべてルールファイルに書けば防ぎやすくなる。「防ぎやすくなる」であって、完全に防止できると保証するものではない点は留意してほしい。&lt;/p&gt;

&lt;h2&gt;
  
  
  実例: CLAUDE.md の書き方
&lt;/h2&gt;

&lt;p&gt;ファイル名は &lt;code&gt;CLAUDE.md&lt;/code&gt;（Claude Code用）と &lt;code&gt;.cursorrules&lt;/code&gt;（Cursor用）で微妙に読まれ方が異なるが、内容は共通化できる。以下は実際に使っている最小構成だ。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Project Rules&lt;/span&gt;

&lt;span class="gu"&gt;## Stack&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Next.js 15 App Router (TypeScript strict)
&lt;span class="p"&gt;-&lt;/span&gt; Runtime: Node.js 20 LTS
&lt;span class="p"&gt;-&lt;/span&gt; Styling: Tailwind CSS v4
&lt;span class="p"&gt;-&lt;/span&gt; State: React Server Components first, Zustand only for client state

&lt;span class="gu"&gt;## Directory Conventions&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Route segments: &lt;span class="sb"&gt;`app/`&lt;/span&gt; only. &lt;span class="sb"&gt;`pages/`&lt;/span&gt; は作らない
&lt;span class="p"&gt;-&lt;/span&gt; Server Components are the default. Add &lt;span class="sb"&gt;`'use client'`&lt;/span&gt; only when hooks or browser APIs are needed
&lt;span class="p"&gt;-&lt;/span&gt; Data fetching: &lt;span class="sb"&gt;`fetch`&lt;/span&gt; in Server Components with explicit &lt;span class="sb"&gt;`cache`&lt;/span&gt; option (&lt;span class="sb"&gt;`force-cache`&lt;/span&gt; or &lt;span class="sb"&gt;`no-store`&lt;/span&gt;)
&lt;span class="p"&gt;-&lt;/span&gt; API Routes: &lt;span class="sb"&gt;`app/api/**/route.ts`&lt;/span&gt; のみ

&lt;span class="gu"&gt;## TypeScript&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`any`&lt;/span&gt; 禁止。型が不明なら &lt;span class="sb"&gt;`unknown`&lt;/span&gt; + 型ガードを使う
&lt;span class="p"&gt;-&lt;/span&gt; Zod でバリデーションし、型推論を &lt;span class="sb"&gt;`z.infer&amp;lt;&amp;gt;`&lt;/span&gt; で引き出す

&lt;span class="gu"&gt;## File Generation Rules&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Component: PascalCase、&lt;span class="sb"&gt;`*.tsx`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Utility: camelCase、&lt;span class="sb"&gt;`*.ts`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; テストは &lt;span class="sb"&gt;`__tests__/`&lt;/span&gt; または &lt;span class="sb"&gt;`*.test.ts`&lt;/span&gt; に配置

&lt;span class="gu"&gt;## What NOT to Do&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`useEffect`&lt;/span&gt; でデータフェッチしない（Server Componentで完結させる）
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`export default`&lt;/span&gt; の無名関数禁止（デバッグ困難になるため）
&lt;span class="p"&gt;-&lt;/span&gt; console.log をコミットしない
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;このファイルをプロジェクトルートに置くだけで、エージェントは App Router の慣習を踏まえたコードを生成しやすくなる。&lt;/p&gt;

&lt;h2&gt;
  
  
  AGENTS.md との使い分け
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;AGENTS.md&lt;/code&gt; は OpenAI の Codex / Agents API が読む仕様として提唱された。Claude Code は &lt;code&gt;CLAUDE.md&lt;/code&gt; を優先するが、両方置いてもほぼ問題ない。内容を共通にしてシンボリックリンクで管理するか、以下のようにリダイレクトコメントを書くだけで十分だ。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# AGENTS.md&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- See CLAUDE.md for the canonical rules --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;プロジェクトが複数エージェントを横断する場合は、&lt;code&gt;CLAUDE.md&lt;/code&gt;（Claude Code）・&lt;code&gt;.cursorrules&lt;/code&gt;（Cursor）・&lt;code&gt;AGENTS.md&lt;/code&gt;（OpenAI系）の3ファイルを同じ内容で保つ運用がシンプルだ。&lt;/p&gt;

&lt;h2&gt;
  
  
  運用Tips
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;サブディレクトリにも置ける&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;app/api/CLAUDE.md&lt;/code&gt; を作ると、APIルート専用の追加ルール（認証必須・レートリミット実装パターンなど）をスコープして書ける。上位ファイルと合算されて読まれる。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ルールは増やしすぎない&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
行数が増えるほどエージェントのコンテキスト消費が増え、肝心なルールが薄まる。「違反が実際に起きたもの」だけを追記する運用が長持ちする。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;変更履歴をコミットに残す&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
ルールファイルの変更は &lt;code&gt;git blame&lt;/code&gt; で追えるようにしておくと、「なぜこのルールがあるか」が後から分かる。コメントで理由を書くより git log の方が腐りにくい。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;効果測定は現実的に&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
ルールファイルはエージェントへのヒントであり、必ず従うことを強制するものではない。レビューフローと組み合わせて初めて品質ゲートとして機能する。CI で &lt;code&gt;tsc --noEmit&lt;/code&gt; と ESLint を通すことが最後の砦だ。&lt;/p&gt;




&lt;h3&gt;
  
  
  5フレームワーク分の実例をまとめたキット
&lt;/h3&gt;

&lt;p&gt;Next.js/React/FastAPI/Godot/Express のルールファイル実例集を用意しました。&lt;a href="https://itsuya.gumroad.com/l/agentrules260619" rel="noopener noreferrer"&gt;👉 詳細・入手はこちら&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>cursor</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>【2026】Heroku 代替 2026 (Render/Railway/Fly.io)：料金・移行コストで選ぶ</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Fri, 19 Jun 2026 02:03:35 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026-heroku-dai-ti-2026-renderrailwayflyioliao-jin-yi-xing-kosutodexuan-bu-3a5b</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026-heroku-dai-ti-2026-renderrailwayflyioliao-jin-yi-xing-kosutodexuan-bu-3a5b</guid>
      <description>&lt;h2&gt;
  
  
  結論（おすすめ1つ）
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;移行先は Render を推奨する。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Heroku からの移行では、Procfile・環境変数・PostgreSQL アドオンという三点セットがほぼそのまま通用し、学習コストが最小で済む。無料枠のスリープ仕様は旧 Heroku 無料プランの感覚と近く、既存の動作イメージを崩さずに検証できる。中小規模の Web アプリであれば設定変更量も少なく、1〜2 時間で本番相当の環境を再現できた。&lt;/p&gt;




&lt;h2&gt;
  
  
  比較表（料金/無料枠/移行コスト/対応言語）
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;項目&lt;/th&gt;
&lt;th&gt;Render&lt;/th&gt;
&lt;th&gt;Railway&lt;/th&gt;
&lt;th&gt;Fly.io&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;無料枠&lt;/td&gt;
&lt;td&gt;あり（非アクティブ時スリープ）&lt;/td&gt;
&lt;td&gt;あり（月次クレジット制）※公式で要確認&lt;/td&gt;
&lt;td&gt;あり（共有 CPU インスタンス数台）※公式で要確認&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;有料プラン最低料金&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heroku からの移行コスト&lt;/td&gt;
&lt;td&gt;低（Procfile 互換あり）&lt;/td&gt;
&lt;td&gt;低（Nixpacks が自動検出）&lt;/td&gt;
&lt;td&gt;中（fly.toml の記述が必要）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;対応ランタイム&lt;/td&gt;
&lt;td&gt;Node.js / &lt;a href="https://www.amazon.co.jp/s?k=Python%20%E5%85%A5%E9%96%80%20%E6%9C%AC&amp;amp;tag=1280itsuya22-22" rel="noopener noreferrer"&gt;Python&lt;/a&gt; / Ruby / Go / Docker&lt;/td&gt;
&lt;td&gt;Node.js / Python / Ruby 他（Nixpacks 対応）&lt;/td&gt;
&lt;td&gt;Docker ベース（任意言語）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;マネージド DB&lt;/td&gt;
&lt;td&gt;PostgreSQL（同一ダッシュボード）&lt;/td&gt;
&lt;td&gt;PostgreSQL / MySQL / MongoDB&lt;/td&gt;
&lt;td&gt;Fly Postgres&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;リージョン&lt;/td&gt;
&lt;td&gt;US / EU 複数拠点&lt;/td&gt;
&lt;td&gt;複数拠点&lt;/td&gt;
&lt;td&gt;グローバル多拠点&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  移行手順
&lt;/h2&gt;

&lt;p&gt;Heroku から Render への移行を実際に実行した手順で示す。&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 環境変数のエクスポート
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Heroku から全環境変数をリスト出力してファイルに保存&lt;/span&gt;
heroku config &lt;span class="nt"&gt;-a&lt;/span&gt; your-app-name &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; heroku_env.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;code&gt;render.yaml&lt;/code&gt; の作成
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;web&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your-app&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node&lt;/span&gt;           &lt;span class="c1"&gt;# python / ruby / docker も指定可&lt;/span&gt;
    &lt;span class="na"&gt;buildCommand&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;
    &lt;span class="na"&gt;startCommand&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node index.js&lt;/span&gt;
    &lt;span class="na"&gt;envVars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NODE_ENV&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DATABASE_URL&lt;/span&gt;
        &lt;span class="na"&gt;fromDatabase&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your-db&lt;/span&gt;
          &lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;connectionString&lt;/span&gt;

&lt;span class="na"&gt;databases&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your-db&lt;/span&gt;
    &lt;span class="na"&gt;plan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;free&lt;/span&gt;          &lt;span class="c1"&gt;# 本番稼働前に paid プランへ変更すること&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. データベースの移行
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Heroku Postgres からダンプ取得&lt;/span&gt;
heroku pg:backups:capture &lt;span class="nt"&gt;-a&lt;/span&gt; your-app-name
heroku pg:backups:download &lt;span class="nt"&gt;-a&lt;/span&gt; your-app-name

&lt;span class="c"&gt;# Render の PostgreSQL へリストア&lt;/span&gt;
pg_restore &lt;span class="nt"&gt;--verbose&lt;/span&gt; &lt;span class="nt"&gt;--clean&lt;/span&gt; &lt;span class="nt"&gt;--no-acl&lt;/span&gt; &lt;span class="nt"&gt;--no-owner&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-h&lt;/span&gt; your-render-db-host &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-U&lt;/span&gt; your-render-db-user &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; your-render-db-name &lt;span class="se"&gt;\&lt;/span&gt;
  latest.dump
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. GitHub 連携と自動デプロイ
&lt;/h3&gt;

&lt;p&gt;Render ダッシュボードでリポジトリを接続し、&lt;code&gt;main&lt;/code&gt; ブランチへのプッシュで自動デプロイが走る設定を有効化する。Heroku の GitHub 連携と同等の挙動が GUI 操作のみで完結する。&lt;/p&gt;

&lt;h3&gt;
  
  
  5. カスタムドメインと SSL
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ダッシュボード &amp;gt; Settings &amp;gt; Custom Domains
# DNS プロバイダに CNAME を追加するだけで Let's Encrypt が自動発行される
# Heroku の SSL エンドポイントアドオンは不要になる
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  向き不向き
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Render が向くケース
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Heroku からの移行を最短で済ませたい個人・小チーム&lt;/li&gt;
&lt;li&gt;Node.js / Python / Ruby を使う標準的な Web アプリ&lt;/li&gt;
&lt;li&gt;マネージド PostgreSQL を同一プラットフォームで管理したいプロジェクト&lt;/li&gt;
&lt;li&gt;GitHub Actions と組み合わせて CI/CD をシンプルに保ちたい場合&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Railway が向くケース
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;モノレポ構成で複数サービスをまとめて管理したい場合&lt;/li&gt;
&lt;li&gt;ビルド設定を書かず Nixpacks の自動検出に任せたい場合&lt;/li&gt;
&lt;li&gt;トラフィックが読みにくく従量課金でコストを変動させたい小規模サービス&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fly.io が向くケース
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;複数リージョンへのグローバル展開が必要なアプリ&lt;/li&gt;
&lt;li&gt;Docker コンテナを細かく制御できる経験豊富な DevOps チーム&lt;/li&gt;
&lt;li&gt;レイテンシーに敏感なサービスでエッジ寄りに配置したいケース&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  避けるべきケース
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Render の無料枠を本番で使う&lt;/strong&gt;：スリープからの初回起動に遅延が発生するため、SLA が求められるサービスには使わない&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Railway の従量課金を上限なしで放置する&lt;/strong&gt;：トラフィックスパイク時のコストが見えにくいため、ダッシュボードの支出アラートを必ず設定する&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fly.io をインフラ未経験チームに導入する&lt;/strong&gt;：&lt;code&gt;fly.toml&lt;/code&gt; の設定と CLI 操作の学習コストが高く、Render の方が安全に移行できる&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>saas</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>【2026】Vercel vs Cloudflare Pages 移行ガイド：料金・移行コストで選ぶ</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Fri, 19 Jun 2026 02:02:23 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026-vercel-vs-cloudflare-pages-yi-xing-gaidoliao-jin-yi-xing-kosutodexuan-bu-3i72</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026-vercel-vs-cloudflare-pages-yi-xing-gaidoliao-jin-yi-xing-kosutodexuan-bu-3i72</guid>
      <description>&lt;h2&gt;
  
  
  結論（おすすめ1つ）
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cloudflare Pages への移行を推奨する。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;無料枠のリクエスト数・帯域制限が実用上ほぼ無制限であり、個人プロジェクトから中規模サービスまでコスト圧力なしに運用できる。Vercel の強みである Next.js との密結合が不要なら、ロックイン解消と CDN 性能の向上を同時に得られる。移行コストは静的サイト・Vite/SvelteKit 系では半日以内に収まるケースが多い。&lt;/p&gt;




&lt;h2&gt;
  
  
  比較表（料金/無料枠/移行コスト/対応言語）
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;項目&lt;/th&gt;
&lt;th&gt;Vercel&lt;/th&gt;
&lt;th&gt;Cloudflare Pages&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;無料枠 帯域&lt;/td&gt;
&lt;td&gt;制限あり（公式の料金ページで要確認）&lt;/td&gt;
&lt;td&gt;商用利用含め実質無制限&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;無料枠 ビルド数&lt;/td&gt;
&lt;td&gt;月間上限あり（公式要確認）&lt;/td&gt;
&lt;td&gt;月間500ビルド（要確認）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Serverless Functions&lt;/td&gt;
&lt;td&gt;Edge Functions / Serverless Functions&lt;/td&gt;
&lt;td&gt;Pages Functions（Workers ベース）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Next.js SSR 対応&lt;/td&gt;
&lt;td&gt;ネイティブ・最高水準&lt;/td&gt;
&lt;td&gt;@cloudflare/next-on-pages 経由（制約あり）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SvelteKit / Astro / Remix&lt;/td&gt;
&lt;td&gt;アダプター要&lt;/td&gt;
&lt;td&gt;アダプター要（公式サポート済み）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;カスタムドメイン&lt;/td&gt;
&lt;td&gt;無料&lt;/td&gt;
&lt;td&gt;無料&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;プレビューデプロイ&lt;/td&gt;
&lt;td&gt;あり&lt;/td&gt;
&lt;td&gt;あり&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;移行コスト（静的/SPA）&lt;/td&gt;
&lt;td&gt;低（設定ファイル数行）&lt;/td&gt;
&lt;td&gt;低（設定ファイル数行）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;移行コスト（SSR/Edge）&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;中〜高（Workers API 差異あり）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ランタイム互換性&lt;/td&gt;
&lt;td&gt;Node.js / Edge Runtime&lt;/td&gt;
&lt;td&gt;Workers Runtime（Node.js API 部分互換）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  移行手順
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Wrangler CLI のインストール
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; wrangler
wrangler login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Cloudflare Pages プロジェクトの作成
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Git 連携なしで直接デプロイする場合&lt;/span&gt;
wrangler pages project create my-app

&lt;span class="c"&gt;# ビルド済み成果物をデプロイ&lt;/span&gt;
npm run build
wrangler pages deploy ./dist &lt;span class="nt"&gt;--project-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git 連携する場合は Cloudflare ダッシュボードの「Workers &amp;amp; Pages」→「Create」から GitHub リポジトリを接続する。&lt;/p&gt;

&lt;h3&gt;
  
  
  3. ビルド設定の更新
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;wrangler.toml&lt;/code&gt;（またはダッシュボード上の設定）に以下を記述する。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"my-app"&lt;/span&gt;
&lt;span class="py"&gt;pages_build_output_dir&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"dist"&lt;/span&gt;
&lt;span class="py"&gt;compatibility_date&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2024-09-23"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;フレームワーク別ビルドコマンドの例：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Vite&lt;/span&gt;
npm run build        &lt;span class="c"&gt;# → dist/&lt;/span&gt;

&lt;span class="c"&gt;# Astro&lt;/span&gt;
npx astro build      &lt;span class="c"&gt;# → dist/&lt;/span&gt;

&lt;span class="c"&gt;# SvelteKit（CF Pages アダプター使用）&lt;/span&gt;
npm run build        &lt;span class="c"&gt;# → .svelte-kit/cloudflare/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. 環境変数の移行
&lt;/h3&gt;

&lt;p&gt;Vercel ダッシュボードの「Settings → Environment Variables」から値を控え、Cloudflare ダッシュボードまたは CLI で設定する。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wrangler pages secret put API_KEY &lt;span class="nt"&gt;--project-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my-app
&lt;span class="c"&gt;# プロンプトに値を入力&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.env&lt;/code&gt; ファイルから一括設定したい場合：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 各行を読み込んで投入するシェルスクリプト例&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'='&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; key value&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^#.&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;continue
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | wrangler pages secret put &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--project-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my-app
&lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; .env.production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. カスタムドメインの切り替え
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Cloudflare ダッシュボードでプロジェクトに「Custom domain」を追加&lt;/li&gt;
&lt;li&gt;DNS が Cloudflare 管理下であれば CNAME が自動設定される&lt;/li&gt;
&lt;li&gt;外部 DNS の場合は CNAME レコードを &lt;code&gt;&amp;lt;project&amp;gt;.pages.dev&lt;/code&gt; に向ける&lt;/li&gt;
&lt;li&gt;Vercel 側の&lt;a href="https://px.a8.net/svt/ejp?a8mat=4B3XB4+4VMW8I+50+2HU3GX" rel="noopener noreferrer"&gt;ドメイン&lt;/a&gt;割り当てを解除し、TTL 切れを待って完全切り替え&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  6. Pages Functions（サーバーサイド処理）の移行
&lt;/h3&gt;

&lt;p&gt;Vercel の API Routes (&lt;code&gt;/api/*.ts&lt;/code&gt;) を移行する場合、&lt;code&gt;functions/&lt;/code&gt; ディレクトリに配置する。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// functions/api/hello.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PagesFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;next/headers&lt;/code&gt; や &lt;code&gt;next/server&lt;/code&gt; 等 Next.js 固有の API を使っている場合は個別に代替実装が必要。&lt;/p&gt;




&lt;h2&gt;
  
  
  向き不向き
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Cloudflare Pages が向くケース
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;静的サイト・SPA・Astro・SvelteKit&lt;/strong&gt; を運用しており、Next.js 依存がない&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;帯域コストを抑えたい&lt;/strong&gt;個人開発者・スタートアップ初期&lt;/li&gt;
&lt;li&gt;Cloudflare の &lt;strong&gt;CDN・WAF・R2・KV&lt;/strong&gt; を組み合わせたインフラに統一したい&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workers Runtime の制約（Node.js API の部分非互換）&lt;/strong&gt; を許容できるチーム&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Vercel を維持すべきケース
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;App Router / Server Actions 等 Next.js の最新機能&lt;/strong&gt; をフル活用している&lt;/li&gt;
&lt;li&gt;ISR（Incremental Static Regeneration）に強く依存している&lt;/li&gt;
&lt;li&gt;チームが Vercel の DX（プレビュー URL、コメント機能等）に慣れており移行コストが見合わない&lt;/li&gt;
&lt;li&gt;Node.js ネイティブモジュール（&lt;code&gt;sharp&lt;/code&gt;、&lt;code&gt;canvas&lt;/code&gt; 等）を Functions 内で使用している&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  避けるべきパターン
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Next.js の Edge Runtime 以外の SSR を多用しているのに、工数見積もりなしで移行を始める&lt;/li&gt;
&lt;li&gt;本番ドメインのカット先を DNS TTL を確認せず即日切り替える&lt;/li&gt;
&lt;li&gt;Vercel の &lt;code&gt;rewrites&lt;/code&gt; / &lt;code&gt;headers&lt;/code&gt; 設定を &lt;code&gt;_redirects&lt;/code&gt; ファイルへ機械的にコピーし動作確認を省略する&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>saas</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>2026年版 Next.jsエージェントに渡すルールファイルの実例と書き方</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Thu, 18 Jun 2026 02:07:35 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026nian-ban-nextjsezientonidu-sururuhuairunoshi-li-toshu-kifang-poh</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026nian-ban-nextjsezientonidu-sururuhuairunoshi-li-toshu-kifang-poh</guid>
      <description>&lt;h2&gt;
  
  
  なぜルールファイルが効くのか
&lt;/h2&gt;

&lt;p&gt;Claude CodeやCursorなどのAIエージェントは、プロジェクトごとに振る舞いを変えられる「コンテキストファイル」を読み込む。このファイルがないと、エージェントはコードスタイル・アーキテクチャ方針・禁止事項を毎回推定しながら動くため、レビュー指摘の繰り返しや一貫性のないコードが増える。&lt;/p&gt;

&lt;p&gt;Next.js App Router + TypeScript のプロジェクトで顕著なのが「&lt;code&gt;use client&lt;/code&gt; の判断ミス」「&lt;code&gt;fetch&lt;/code&gt; vs &lt;code&gt;axios&lt;/code&gt; どちらを使うか」「Server Actions の使用方針」といった曖昧な判断だ。これらをルールファイルに明示するだけで、エージェントの出力精度は体感で大きく安定する。&lt;/p&gt;

&lt;h2&gt;
  
  
  ファイル名と読み込みタイミング
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ファイル名&lt;/th&gt;
&lt;th&gt;読み込まれるツール&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Claude Code（プロジェクトルートに置く）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.cursorrules&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cursor（非推奨化されつつある。&lt;code&gt;AGENTS.md&lt;/code&gt;へ移行推奨）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;OpenAI Codex・汎用エージェント向け&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Claude Codeはリポジトリルートの&lt;code&gt;CLAUDE.md&lt;/code&gt;を自動で読み込む。サブディレクトリ（&lt;code&gt;src/CLAUDE.md&lt;/code&gt;など）にも置けばスコープを絞れる。&lt;/p&gt;

&lt;h2&gt;
  
  
  実例：Next.js App Router 向け CLAUDE.md
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Project Rules&lt;/span&gt;

&lt;span class="gu"&gt;## Stack&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Next.js 15 (App Router), TypeScript strict mode
&lt;span class="p"&gt;-&lt;/span&gt; Tailwind CSS v4, Shadcn/ui
&lt;span class="p"&gt;-&lt;/span&gt; データフェッチ: fetch API (axios 禁止)
&lt;span class="p"&gt;-&lt;/span&gt; 状態管理: Zustand のみ (Redux/Recoil 新規導入禁止)

&lt;span class="gu"&gt;## コンポーネント方針&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Server Component をデフォルト。インタラクションが必要なときのみ "use client" を追加
&lt;span class="p"&gt;-&lt;/span&gt; "use client" を追加する場合はファイル冒頭にコメントで理由を記載する
&lt;span class="p"&gt;-&lt;/span&gt; Server Actions は app/actions/ 以下に配置し、ファイル名を &lt;span class="err"&gt;*&lt;/span&gt;.action.ts とする

&lt;span class="gu"&gt;## 型&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; any 禁止。unknown + 型ガードで代替
&lt;span class="p"&gt;-&lt;/span&gt; API レスポンスは zod でバリデーションし、型推論を使う

&lt;span class="gu"&gt;## 禁止事項&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; console.log を本番コードに残さない
&lt;span class="p"&gt;-&lt;/span&gt; .env ファイルをコミットしない
&lt;span class="p"&gt;-&lt;/span&gt; ページコンポーネントに直接ビジネスロジックを書かない

&lt;span class="gu"&gt;## テスト&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; ユニットテスト: Vitest
&lt;span class="p"&gt;-&lt;/span&gt; E2E: Playwright
&lt;span class="p"&gt;-&lt;/span&gt; 新機能は最低1件のテストを添付する

&lt;span class="gu"&gt;## コミットメッセージ&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Conventional Commits 形式 (feat/fix/chore...)
&lt;span class="p"&gt;-&lt;/span&gt; 日本語可、50字以内
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  運用 Tips
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;最小から始める。&lt;/strong&gt; 最初から100行のルールファイルを書こうとすると、実態と乖離したルールが増える。まずレビューで何度も指摘したことを5〜10行にまとめるだけで十分だ。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;エージェントに矛盾を検知させる。&lt;/strong&gt; 「このルールは現在のコードと矛盾していないか？」と問いかけるプロンプトをCI上で定期実行すると、ルールファイルの陳腐化を防げる。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;チームで育てる。&lt;/strong&gt; プルリクエストで同じ指摘が2回発生したら、そのルールを&lt;code&gt;CLAUDE.md&lt;/code&gt;に追記するフローをチームの慣習にする。ルールファイルはコードベースと一緒にバージョン管理されるため、&lt;code&gt;git blame&lt;/code&gt;で変更理由を追える。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;スコープを分ける。&lt;/strong&gt; &lt;code&gt;src/app/CLAUDE.md&lt;/code&gt;にルーティング方針、&lt;code&gt;src/components/CLAUDE.md&lt;/code&gt;にUI原則を分けて書くと、エージェントが関連ルールだけを読み込み、ノイズが減る。&lt;/p&gt;

&lt;p&gt;ルールファイルはエージェントへの「仕様書」だ。書くほどレビュー負荷が下がるが、実態から離れたルールはむしろ誤誘導になる。定期的に見直しながら育てていくものとして扱うのが現実的な運用だ。&lt;/p&gt;




&lt;h3&gt;
  
  
  5フレームワーク分の実例をまとめたキット
&lt;/h3&gt;

&lt;p&gt;Next.js/React/FastAPI/Godot/Express のルールファイル実例集を用意しました。&lt;a href="https://itsuya.gumroad.com/l/agentrules260618" rel="noopener noreferrer"&gt;👉 詳細・入手はこちら&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>cursor</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>【2026】Mailchimp 代替のトランザクションメールAPI：料金・移行コストで選ぶ</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Thu, 18 Jun 2026 02:05:00 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026-mailchimp-dai-ti-notoranzakusiyonmeruapiliao-jin-yi-xing-kosutodexuan-bu-1l96</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026-mailchimp-dai-ti-notoranzakusiyonmeruapiliao-jin-yi-xing-kosutodexuan-bu-1l96</guid>
      <description>&lt;h2&gt;
  
  
  結論（おすすめ1つ）
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Resend&lt;/strong&gt; に乗り換えることを推奨する。&lt;/p&gt;

&lt;p&gt;理由は3点。①REST APIの設計が極めてシンプルで、curl1行から動作確認できるため、既存コードへの統合コストが最も低い。②Node.js/&lt;a href="https://www.amazon.co.jp/s?k=Python%20%E5%85%A5%E9%96%80%20%E6%9C%AC&amp;amp;tag=1280itsuya22-22" rel="noopener noreferrer"&gt;Python&lt;/a&gt;/Go/Ruby/PHP/Javaなど主要言語のSDKが公式提供されており、チームのスタック問わず採用しやすい。③Mailchimpのトランザクション機能（旧Mandrill）と異なり、マーケティング機能に引きずられない純粋なトランザクション送信に特化した設計になっている。&lt;/p&gt;




&lt;h2&gt;
  
  
  比較表（料金/無料枠/移行コスト/対応言語）
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ツール&lt;/th&gt;
&lt;th&gt;無料枠&lt;/th&gt;
&lt;th&gt;料金体系&lt;/th&gt;
&lt;th&gt;移行コスト&lt;/th&gt;
&lt;th&gt;対応主要言語&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resend&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;送信数課金&lt;/td&gt;
&lt;td&gt;低（APIファースト設計）&lt;/td&gt;
&lt;td&gt;Node.js / Python / Go / Ruby / PHP 他&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Postmark&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;送信数課金&lt;/td&gt;
&lt;td&gt;低〜中&lt;/td&gt;
&lt;td&gt;Node.js / Python / Ruby / PHP / .NET / Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SendGrid&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;送信数課金&lt;/td&gt;
&lt;td&gt;中（設定項目が多い）&lt;/td&gt;
&lt;td&gt;Node.js / Python / PHP / Java / C# / Go / Ruby&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mailgun&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;送信数課金&lt;/td&gt;
&lt;td&gt;低〜中（SMTP互換あり）&lt;/td&gt;
&lt;td&gt;Node.js / Python / Ruby / PHP / Java / C#&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Amazon SES&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;送信数＋データ転送量&lt;/td&gt;
&lt;td&gt;高（IAM/SES設定が複雑）&lt;/td&gt;
&lt;td&gt;AWS SDK経由で全主要言語&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Postmarkはデリバリビリティの実績が厚く、エンタープライズ要件が強いチームに向く。SendGrid・Mailgunはマーケティングメールとトランザクションメールを同一ツールで管理したい場合の選択肢。Amazon SESは大量送信でコストを抑えたい場合に有効だが、IAMポリシーやバウンス管理の設定工数が高い。&lt;/p&gt;




&lt;h2&gt;
  
  
  移行手順
&lt;/h2&gt;

&lt;p&gt;Mandrillから&lt;strong&gt;Resend&lt;/strong&gt;へ切り替える手順を示す。&lt;/p&gt;

&lt;h3&gt;
  
  
  ステップ1: APIキー取得と疎通確認
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# curlで即テスト&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s1"&gt;'https://api.resend.com/emails'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer YOUR_RESEND_API_KEY'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "from": "noreply@yourdomain.com",
    "to": ["test@example.com"],
    "subject": "移行テスト",
    "html": "&amp;lt;p&amp;gt;Resendからの送信テストです。&amp;lt;/p&amp;gt;"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ステップ2: &lt;a href="https://px.a8.net/svt/ejp?a8mat=4B3XB4+4VMW8I+50+2HU3GX" rel="noopener noreferrer"&gt;ドメイン&lt;/a&gt;認証（SPF/DKIM設定）
&lt;/h3&gt;

&lt;p&gt;Resendダッシュボードの「Domains」からドメインを追加すると、追加すべきDNSレコードが表示される。既存のMandrill用DKIMレコードとは別エントリになるため、DNSプロバイダー側で重複しないよう注意する。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 設定後の確認（dig コマンドで伝播チェック）&lt;/span&gt;
dig TXT resend._domainkey.yourdomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ステップ3: 送信コードの置き換え（Node.js例）
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before: Mandrill (mandrill-api)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mandrill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mandrill-api/mandrill&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;mandrill&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Mandrill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MANDRILL_API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;from_email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;noreply@yourdomain.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;to&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;件名&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;p&amp;gt;本文&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// After: Resend SDK&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Resend&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resend&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Resend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RESEND_API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;resend&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;noreply@yourdomain.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;件名&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;p&amp;gt;本文&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ステップ4: Webhookの切り替え
&lt;/h3&gt;

&lt;p&gt;バウンス・デリバリーイベントをアプリ側で受け取っている場合、Resendのwebhookエンドポイントを登録する。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s1"&gt;'https://api.resend.com/webhooks'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer YOUR_RESEND_API_KEY'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "endpoint": "https://yourapp.com/webhooks/resend",
    "events": [
      "email.sent",
      "email.delivered",
      "email.bounced",
      "email.complained"
    ]
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mandrillのwebhookペイロード形式とはフィールド名が異なるため、受信側のパースロジックの更新が必要になる点に注意。&lt;/p&gt;




&lt;h2&gt;
  
  
  向き不向き
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;向いているチーム・規模&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;スタートアップ〜中規模で、開発者が直接メール送信ロジックを管理するケース&lt;/li&gt;
&lt;li&gt;Node.js / &lt;a href="https://www.amazon.co.jp/s?k=React%20%E5%85%A5%E9%96%80%20%E6%9C%AC&amp;amp;tag=1280itsuya22-22" rel="noopener noreferrer"&gt;React&lt;/a&gt;スタックで開発しており、React Emailテンプレートとの連携を活かしたいチーム&lt;/li&gt;
&lt;li&gt;MandrillのUIや複雑な設定に疲れ、APIファーストのシンプルな運用に切り替えたいチーム&lt;/li&gt;
&lt;li&gt;CI/CDパイプラインからテストメール・通知メールを自動送信したいケース（APIキー1本で完結）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;向いていないケース・避けるべき状況&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;月次送信数が非常に多くコストを極限まで抑えたい場合は、Amazon SES のほうがコスト効率が高い可能性がある（公式の料金ページで要確認）&lt;/li&gt;
&lt;li&gt;既存システムがSMTPインターフェース前提で構築されており、コード変更が困難な場合は、SMTP互換のあるMailgunやSendGridのほうが移行摩擦が小さい&lt;/li&gt;
&lt;li&gt;マーケティングメール・ニュースレターとトランザクションメールを同一ツールで一元管理したい場合は、Resendはトランザクション特化のため機能が足りない。SendGridが候補に上がる&lt;/li&gt;
&lt;li&gt;厳格なSLA契約・コンプライアンス証跡が必要なエンタープライズ環境では、Postmarkの実績と手厚いサポートを優先すべきケースがある&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>saas</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>【2026】Auth0 代替 (Clerk/Supabase Auth/WorkOS)：料金・移行コストで選ぶ</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Thu, 18 Jun 2026 02:03:00 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026-auth0-dai-ti-clerksupabase-authworkosliao-jin-yi-xing-kosutodexuan-bu-40jj</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026-auth0-dai-ti-clerksupabase-authworkosliao-jin-yi-xing-kosutodexuan-bu-40jj</guid>
      <description>&lt;h2&gt;
  
  
  結論（おすすめ1つ）
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ほとんどのプロダクトには Clerk を選ぶ。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Auth0 の「設定が多すぎて疲れる」「ダッシュボードが重い」という不満を解消しつつ、Next.js / &lt;a href="https://www.amazon.co.jp/s?k=React%20%E5%85%A5%E9%96%80%20%E6%9C%AC&amp;amp;tag=1280itsuya22-22" rel="noopener noreferrer"&gt;React&lt;/a&gt; との統合が三者の中で最も洗練されている。無料枠でスタートアップの初期フェーズをカバーでき、コンポーネントベースの認証 UI により実装工数を大幅に削減できる。ただし、エンタープライズ向け SAML / SCIM の整備が最優先要件であれば WorkOS を先に検討すること。&lt;/p&gt;

&lt;h2&gt;
  
  
  比較表（料金/無料枠/移行コスト/対応言語）
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;項目&lt;/th&gt;
&lt;th&gt;Clerk&lt;/th&gt;
&lt;th&gt;Supabase Auth&lt;/th&gt;
&lt;th&gt;WorkOS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;料金（有料プラン）&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;無料枠&lt;/td&gt;
&lt;td&gt;MAU 上限あり（公式要確認）&lt;/td&gt;
&lt;td&gt;Supabase 無料プランに含む&lt;/td&gt;
&lt;td&gt;開発用は無料、本番は公式要確認&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;移行コスト&lt;/td&gt;
&lt;td&gt;中（JWT / セッション層の再実装）&lt;/td&gt;
&lt;td&gt;中〜高（DB と密結合）&lt;/td&gt;
&lt;td&gt;低〜中（SAML 置換用途は低め）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;主要 SDK&lt;/td&gt;
&lt;td&gt;JS/TS 中心（React / Next.js / Remix）&lt;/td&gt;
&lt;td&gt;JS/TS / &lt;a href="https://www.amazon.co.jp/s?k=Python%20%E5%85%A5%E9%96%80%20%E6%9C%AC&amp;amp;tag=1280itsuya22-22" rel="noopener noreferrer"&gt;Python&lt;/a&gt; / Go / Dart など多言語&lt;/td&gt;
&lt;td&gt;Node / Python / Ruby / Go / PHP / Java / .NET&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;セルフホスト&lt;/td&gt;
&lt;td&gt;不可&lt;/td&gt;
&lt;td&gt;可（OSS）&lt;/td&gt;
&lt;td&gt;不可&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSO / SAML&lt;/td&gt;
&lt;td&gt;有料プランで対応&lt;/td&gt;
&lt;td&gt;基本機能のみ&lt;/td&gt;
&lt;td&gt;設計思想の中核&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  移行手順（Auth0 → Clerk）
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: SDK インストールと環境変数の設定
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @clerk/nextjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# .env.local
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxx
CLERK_SECRET_KEY=sk_test_xxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: ミドルウェアの差し替え
&lt;/h3&gt;

&lt;p&gt;Auth0 の &lt;code&gt;withApiAuthRequired&lt;/code&gt; を Clerk の &lt;code&gt;authMiddleware&lt;/code&gt; へ置き換える。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// middleware.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;authMiddleware&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@clerk/nextjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;authMiddleware&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;publicRoutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/public(.*)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;matcher&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/((?!_next|.*&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;..*).*)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Auth0 ユーザーの移行
&lt;/h3&gt;

&lt;p&gt;Auth0 Management API でユーザーをエクスポートし、Clerk Backend API へインポートする。bcrypt ハッシュはそのまま移行できる。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Auth0 CLI でユーザーをエクスポート&lt;/span&gt;
auth0 &lt;span class="nb"&gt;users export&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; users.json

&lt;span class="c"&gt;# Clerk へ 1 件ずつインポート（バルク処理はスクリプト化推奨）&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.clerk.com/v1/users &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$CLERK_SECRET_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "email_address": ["user@example.com"],
    "password_digest": "&amp;lt;bcrypt_hash&amp;gt;",
    "password_hasher": "bcrypt"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: UI コンポーネントの差し替え
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before (Auth0)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@auth0/nextjs-auth0/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// After (Clerk)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SignIn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;UserButton&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@clerk/nextjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 認証ページは 1 行で完結&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SignInPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SignIn&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;カスタマイズは Clerk ダッシュボードの Appearance 設定か CSS 変数で対応できる。Auth0 のカスタムページ実装をまるごと捨てられる点が最大の時短になる。&lt;/p&gt;

&lt;h2&gt;
  
  
  向き不向き
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Clerk が向くチーム・規模&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js / React ベースのプロダクトを開発している&lt;/li&gt;
&lt;li&gt;スタートアップ〜中規模 SaaS（MAU 数千〜数万規模）&lt;/li&gt;
&lt;li&gt;認証 UI を自前で作りたくない、または Auth0 のルールエディタに疲弊している&lt;/li&gt;
&lt;li&gt;フロントエンド中心のチームで、認証をサクッと終わらせたい&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Supabase Auth が向くチーム・規模&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;すでに Supabase（PostgreSQL）をメイン DB として採用している&lt;/li&gt;
&lt;li&gt;セルフホストによるコスト上限管理や GDPR 対応のデータ所在地指定が必要&lt;/li&gt;
&lt;li&gt;Python / Go などマルチ言語バックエンド構成で Auth0 SDK の偏りが問題になっている&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;WorkOS が向くチーム・規模&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;B2B SaaS でエンタープライズ契約が収益の中心&lt;/li&gt;
&lt;li&gt;顧客の IT 部門が Okta / Azure AD を運用しており、SAML SSO が商談の前提条件&lt;/li&gt;
&lt;li&gt;SCIM によるユーザープロビジョニング自動化が必要な規模&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;避けるべきケース&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clerk&lt;/strong&gt;: モバイルネイティブ（iOS / Android）がメインの場合は SDK が発展途上。高トラフィック時の従量課金は事前にシミュレーションすること&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supabase Auth&lt;/strong&gt;: Supabase 以外の DB スタックでは恩恵が薄く、Auth だけ切り出すと管理オーバーヘッドが増える&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WorkOS&lt;/strong&gt;: B2C アプリや MAU ベースのグロースモデルには設計が合わない。エンタープライズ専用のプライシング構造を前提に設計されている&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>saas</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>【実体験】OpenAI/Anthropic APIコストを下げる：モデル選定・プロンプトキャッシュ・バッチの実戦</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Thu, 18 Jun 2026 02:01:27 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/shi-ti-yan-openaianthropic-apikosutowoxia-gerumoderuxuan-ding-puronputokiyatusiyubatutinoshi-zhan-1g84</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/shi-ti-yan-openaianthropic-apikosutowoxia-gerumoderuxuan-ding-puronputokiyatusiyubatutinoshi-zhan-1g84</guid>
      <description>&lt;h1&gt;
  
  
  OpenAI/Anthropic APIコストを下げる：モデル選定・プロンプトキャッシュ・バッチの実戦
&lt;/h1&gt;

&lt;h2&gt;
  
  
  結論：3つの手順で月額コストを60〜80%削減できる
&lt;/h2&gt;

&lt;p&gt;個人開発でAPIコストが膨らむ原因は決まっている。&lt;strong&gt;高いモデルに全タスクを投げている&lt;/strong&gt;、&lt;strong&gt;同じシステムプロンプトを毎回送信している&lt;/strong&gt;、&lt;strong&gt;リアルタイム不要な処理をリアルタイムで流している&lt;/strong&gt;。この3点を直すだけでコストは劇的に落ちる。&lt;/p&gt;




&lt;h2&gt;
  
  
  1. モデル選定：タスクを分類して最安モデルに落とす
&lt;/h2&gt;

&lt;p&gt;モデルコストの目安（2025年時点・input/output per 1M tokens）：&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;モデル&lt;/th&gt;
&lt;th&gt;input&lt;/th&gt;
&lt;th&gt;output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;gpt-4o&lt;/td&gt;
&lt;td&gt;$2.50&lt;/td&gt;
&lt;td&gt;$10.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gpt-4o-mini&lt;/td&gt;
&lt;td&gt;$0.15&lt;/td&gt;
&lt;td&gt;$0.60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;claude-sonnet-4-6&lt;/td&gt;
&lt;td&gt;$3.00&lt;/td&gt;
&lt;td&gt;$15.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;claude-haiku-4-5&lt;/td&gt;
&lt;td&gt;$0.80&lt;/td&gt;
&lt;td&gt;$4.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;分類基準：&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ルーティング・分類・短文生成&lt;/strong&gt; → gpt-4o-mini / claude-haiku-4-5&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;長文要約・構造化抽出&lt;/strong&gt; → gpt-4o-mini（十分）&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;複雑な推論・コード生成&lt;/strong&gt; → gpt-4o / claude-sonnet-4-6&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;実装例：タスク種別でモデルを切り替える&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;routing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;classify&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summarize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code_review&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reasoning&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-4-6&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;実測では「分類＋要約」をminiに移すだけでトークンコストが&lt;strong&gt;1/16&lt;/strong&gt;になった。&lt;/p&gt;




&lt;h2&gt;
  
  
  2. プロンプトキャッシュ：同じプレフィックスをキャッシュして再課金を防ぐ
&lt;/h2&gt;

&lt;p&gt;システムプロンプトが長い場合、毎リクエストで同じ内容を送ると全額課金される。&lt;strong&gt;Anthropicのプロンプトキャッシュ&lt;/strong&gt;を使えば、キャッシュヒット時のinputコストが&lt;strong&gt;90%オフ&lt;/strong&gt;になる。&lt;/p&gt;

&lt;h3&gt;
  
  
  Anthropic（cache_control）
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;system_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;あなたは...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;（長い指示 2000トークン以上）&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-haiku-4-5-20251001&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cache_control&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ephemeral&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  &lt;span class="c1"&gt;# ここだけ追加
&lt;/span&gt;        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# レスポンスのusageでキャッシュヒットを確認
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# cache_read_input_tokens &amp;gt; 0 ならキャッシュヒット
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;条件：&lt;strong&gt;1024トークン以上&lt;/strong&gt;のブロックにのみ適用可。TTLは5分（ephemeral）。&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenAI（自動キャッシュ）
&lt;/h3&gt;

&lt;p&gt;gpt-4o / gpt-4o-miniはプロンプトが&lt;strong&gt;1024トークン超&lt;/strong&gt;かつ同一プレフィックスであれば自動でキャッシュが効く。特別な設定不要。キャッシュヒット時はinputが&lt;strong&gt;50%オフ&lt;/strong&gt;。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 同一セッション内で同じsystem promptを使いまわすだけ
# ヘッダーのusage.prompt_tokens_detailsで確認可能
&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;
&lt;span class="n"&gt;cached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prompt_tokens_details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cached_tokens&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;キャッシュ済みトークン: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cached&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;コツ：&lt;/strong&gt; システムプロンプトは先頭に固定し、ユーザー入力は末尾に追加する。順序を変えるとキャッシュが効かない。&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Batch API：非同期処理で最大50%オフ
&lt;/h2&gt;

&lt;p&gt;リアルタイム応答が不要な処理（定時レポート・記事生成・データ変換）はBatch APIで流す。&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenAI Batch API
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"custom_id": "task-1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "要約して：..."}], "max_tokens": 500}}
{"custom_id": "task-2", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "分類して：..."}], "max_tokens": 100}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# バッチファイルをアップロード
&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tasks.jsonl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;purpose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;batch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# バッチ作成（24時間以内に完了）
&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;batches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;input_file_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/v1/chat/completions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;completion_window&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;24h&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# batch_xxxx を保存しておく
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 後で結果を取得
&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;batches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;batch_xxxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;completed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_file_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;result_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;コスト：&lt;strong&gt;通常の50%&lt;/strong&gt;。100万トークン処理するなら$1.25→$0.625。&lt;/p&gt;

&lt;h3&gt;
  
  
  Anthropic Message Batches
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;batches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;custom_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;req-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;params&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-haiku-4-5-20251001&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  まとめ：優先順位つき実装チェックリスト
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;モデル切り替え&lt;/strong&gt;（即効・実装30分）：分類・要約タスクをmini/haikuへ移す。コスト16分の1。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;プロンプトキャッシュ&lt;/strong&gt;（実装1時間）：長いシステムプロンプトに&lt;code&gt;cache_control&lt;/code&gt;を追加。繰り返しリクエストのinputを90%削減。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch API化&lt;/strong&gt;（実装2〜3時間）：毎朝の定時処理をすべてバッチに移行。残コストをさらに半減。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;この3ステップを順番に適用した結果、月$80→$14まで圧縮できた。まずモデル選定から始めるのが費用対効果が最も高い。&lt;/p&gt;




&lt;h2&gt;
  
  
  関連リンク
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://1280itsuya.github.io/service/cloud-cost.html" rel="noopener noreferrer"&gt;クラウド/SaaSのコスト無料セルフ診断（60秒・登録不要）&lt;/a&gt; — AWS/Vercel/Supabase/監視SaaSにムダな課金がないか、その場でチェックできます。&lt;/li&gt;
&lt;li&gt;&lt;a href="https://itsuya.gumroad.com/l/aikit260618" rel="noopener noreferrer"&gt;AI開発・自動化の実践キット / プロンプト集（Gumroad）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;small&gt;※自社サービスのご案内を含みます。&lt;/small&gt;&lt;/p&gt;

</description>
      <category>openai</category>
      <category>claude</category>
    </item>
    <item>
      <title>【2026】Algolia 代替の全文検索SaaS比較：料金・移行コストで選ぶ</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Thu, 18 Jun 2026 02:01:26 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026-algolia-dai-ti-noquan-wen-jian-suo-saasbi-jiao-liao-jin-yi-xing-kosutodexuan-bu-3gjf</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026-algolia-dai-ti-noquan-wen-jian-suo-saasbi-jiao-liao-jin-yi-xing-kosutodexuan-bu-3gjf</guid>
      <description>&lt;h2&gt;
  
  
  結論（おすすめ1つ）
&lt;/h2&gt;

&lt;p&gt;Algoliaからの乗り換えなら &lt;strong&gt;Typesense&lt;/strong&gt; を選べ。&lt;/p&gt;

&lt;p&gt;APIがAlgoliaと最も近く、公式の互換アダプタ（&lt;code&gt;typesense-instantsearch-adapter&lt;/code&gt;）が整備されているため、フロントエンドのUIコンポーネントをほぼ書き直さずに済む。セルフホストとマネージドクラウドを同一コードで切り替えられるので、コスト最適化の選択肢が広い。Rustで実装されたコアは検索レイテンシが安定しており、本番で予測可能なパフォーマンスが出せる。&lt;/p&gt;




&lt;h2&gt;
  
  
  比較表（料金/無料枠/移行コスト/対応言語）
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ツール&lt;/th&gt;
&lt;th&gt;料金感&lt;/th&gt;
&lt;th&gt;無料枠&lt;/th&gt;
&lt;th&gt;移行コスト&lt;/th&gt;
&lt;th&gt;主な対応言語SDK&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Typesense Cloud&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;OSS版セルフホストは無料&lt;/td&gt;
&lt;td&gt;★★☆（Algolia互換アダプタあり）&lt;/td&gt;
&lt;td&gt;JS/TS, &lt;a href="https://www.amazon.co.jp/s?k=Python%20%E5%85%A5%E9%96%80%20%E6%9C%AC&amp;amp;tag=1280itsuya22-22" rel="noopener noreferrer"&gt;Python&lt;/a&gt;, Go, Ruby, PHP, Java&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Meilisearch Cloud&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;OSS版は無料、Cloudに無料枠あり&lt;/td&gt;
&lt;td&gt;★★★（独自API、一部書き直し要）&lt;/td&gt;
&lt;td&gt;JS/TS, Python, Go, Ruby, PHP, Rust&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OpenSearch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AWS従量制、公式要確認&lt;/td&gt;
&lt;td&gt;なし（AWSコスト発生）&lt;/td&gt;
&lt;td&gt;★★★★（クエリDSLが大きく異なる）&lt;/td&gt;
&lt;td&gt;多言語（AWS公式SDK）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Elasticsearch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Elastic Cloud、公式要確認&lt;/td&gt;
&lt;td&gt;14日トライアルのみ&lt;/td&gt;
&lt;td&gt;★★★★（スキーマ・設定管理が複雑）&lt;/td&gt;
&lt;td&gt;多言語（Elastic公式SDK）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;移行コスト凡例：&lt;/strong&gt; ★少 〜 ★★★★多&lt;/p&gt;




&lt;h2&gt;
  
  
  移行手順
&lt;/h2&gt;

&lt;p&gt;Algolia → Typesense への移行を段階的に示す。&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Typesense をローカルで起動（Docker）
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8108:8108 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /tmp/typesense-data:/data &lt;span class="se"&gt;\&lt;/span&gt;
  typesense/typesense:latest &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-dir&lt;/span&gt; /data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--api-key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-local-dev-key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. 依存パッケージを追加
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Node.js&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;typesense typesense-instantsearch-adapter

&lt;span class="c"&gt;# Python&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;typesense
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. コレクション（インデックス）を作成
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Typesense&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;typesense&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Typesense&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8108&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-local-dev-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;connectionTimeoutSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;float&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;  &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tags&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string[]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;facet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;default_sorting_field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Algolia のデータを一括インポート
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Algolia から取得済みの JSON 配列 records を使う&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;records&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;create&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Algoliaのエクスポートは &lt;code&gt;algoliasearch&lt;/code&gt; クライアントの &lt;code&gt;browseObjects&lt;/code&gt; で全件取得できる。ページネーションなしで直接イテレートできる点に注意。&lt;/p&gt;

&lt;h3&gt;
  
  
  5. フロントエンドの searchClient を差し替える
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;TypesenseInstantSearchAdapter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;typesense-instantsearch-adapter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TypesenseInstantSearchAdapter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;search-only-api-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 検索専用キーを発行して使う&lt;/span&gt;
    &lt;span class="na"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xxx.a1.typesense.net&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;additionalSearchParameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;query_by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name,tags&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 既存の instantsearch() に渡す searchClient をそのまま差し替えるだけ&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;&amp;lt;SearchBox&amp;gt;&lt;/code&gt; &lt;code&gt;&amp;lt;Hits&amp;gt;&lt;/code&gt; &lt;code&gt;&amp;lt;RefinementList&amp;gt;&lt;/code&gt; 等のInstantSearch UIコンポーネントはそのまま流用できる。Algolia固有の &lt;code&gt;insights&lt;/code&gt; イベントを使っていた箇所だけ削除または置換が必要。&lt;/p&gt;




&lt;h2&gt;
  
  
  向き不向き
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Typesense が向くケース
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;コスト見直し中の中小規模SaaS / EC&lt;/strong&gt;: ドキュメント数が数百万件以内で、Algoliaの月額が重くなってきたチーム&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;フロントエンド重視のプロダクト&lt;/strong&gt;: InstantSearchをすでに使っており、UIを大幅に書き直したくない&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;セルフホスト検討中のチーム&lt;/strong&gt;: RenderやFly.ioにDockerデプロイして固定費に抑えたい場合&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Meilisearch が向くケース
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;社内ツール・ダッシュボード&lt;/strong&gt;: 個人情報など外部クラウドに載せたくないデータを扱うチーム&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;シンプルなOSS構成を好む小規模チーム&lt;/strong&gt;: バイナリ1本で起動できる運用コストの低さが魅力&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Typesense / Meilisearch を避けるべきケース
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;ドキュメント数が数千万〜億単位に伸びる見込みの大規模サービス（ElasticsearchまたはOpenSearchを検討）&lt;/li&gt;
&lt;li&gt;複雑なログ集計・アナリティクスパイプラインが必須な場合（Elasticsearch + Kibanaスタックの方が成熟度が高い）&lt;/li&gt;
&lt;li&gt;AlgoliaのAI Ranking・Personalizeを本番で活用している場合（互換アダプタでは再現できない機能が存在する）&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>saas</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>2026年版：AIエージェントへのNext.js TypeScriptプロジェクトルールファイル完全解説</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Wed, 17 Jun 2026 02:08:07 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026nian-ban-aiezientohenonextjs-typescriptpuroziekutoruruhuairuwan-quan-jie-shuo-4p30</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026nian-ban-aiezientohenonextjs-typescriptpuroziekutoruruhuairuwan-quan-jie-shuo-4p30</guid>
      <description>&lt;h2&gt;
  
  
  なぜルールファイルが必要か
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot・Claude Code・Cursor などのAIエージェントは、プロジェクト固有のコンテキストを持たない状態でコードを生成する。App Router への移行後も &lt;code&gt;pages/&lt;/code&gt; を使ったコードを提案したり、&lt;code&gt;any&lt;/code&gt; 型を乱発したりするのはこのためだ。&lt;/p&gt;

&lt;p&gt;ルールファイル（&lt;code&gt;CLAUDE.md&lt;/code&gt; / &lt;code&gt;.cursorrules&lt;/code&gt; / &lt;code&gt;AGENTS.md&lt;/code&gt;）は「このプロジェクトではこう書く」という制約を宣言的に与える仕組みで、プロンプトを毎回書き直すより安定して効く。エージェントがファイルを生成・修正するたびに参照するため、レビュー指摘が構造的に減る。&lt;/p&gt;

&lt;h2&gt;
  
  
  各ファイルの用途整理
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ファイル&lt;/th&gt;
&lt;th&gt;読むエージェント&lt;/th&gt;
&lt;th&gt;置き場所&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;プロジェクトルート or サブディレクトリ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.cursorrules&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cursor&lt;/td&gt;
&lt;td&gt;プロジェクトルート&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;OpenAI Codex系&lt;/td&gt;
&lt;td&gt;プロジェクトルート&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;内容はほぼ共通化できる。&lt;code&gt;CLAUDE.md&lt;/code&gt; を正として、他はシンボリックリンクか同内容コピーで管理するのが現実的だ。&lt;/p&gt;

&lt;h2&gt;
  
  
  実例：Next.js App Router + TypeScript 向け CLAUDE.md
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Project Rules&lt;/span&gt;

&lt;span class="gu"&gt;## Stack&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Next.js 15 App Router (src/app/ ディレクトリ)
&lt;span class="p"&gt;-&lt;/span&gt; TypeScript strict mode (tsconfig strict: true)
&lt;span class="p"&gt;-&lt;/span&gt; Tailwind CSS v4
&lt;span class="p"&gt;-&lt;/span&gt; Prisma + PostgreSQL

&lt;span class="gu"&gt;## ディレクトリ規約&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; ページ: src/app/(routes)/[slug]/page.tsx
&lt;span class="p"&gt;-&lt;/span&gt; サーバーコンポーネントをデフォルトとし、インタラクションが必要な場合のみ "use client" を追加
&lt;span class="p"&gt;-&lt;/span&gt; API Route は src/app/api/ 以下、Route Handler (route.ts) を使う。pages/api/ は使わない

&lt;span class="gu"&gt;## TypeScript&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`any`&lt;/span&gt; 禁止。型が不明な場合は &lt;span class="sb"&gt;`unknown`&lt;/span&gt; を使い、型ガードで絞る
&lt;span class="p"&gt;-&lt;/span&gt; Server Actions は src/app/actions/ に置き、ファイル先頭に "use server" を記載
&lt;span class="p"&gt;-&lt;/span&gt; Props 型は inline interface ではなく export type Props = {...} で定義する

&lt;span class="gu"&gt;## データフェッチ&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; fetch は Server Component 内で直接呼ぶ。useSWR / React Query はクライアント側のみ
&lt;span class="p"&gt;-&lt;/span&gt; キャッシュ戦略は { next: { revalidate: N } } で明示する。cache: "no-store" をデフォルトにしない

&lt;span class="gu"&gt;## 命名&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; コンポーネント: PascalCase (UserCard.tsx)
&lt;span class="p"&gt;-&lt;/span&gt; ユーティリティ関数: camelCase (formatDate.ts)
&lt;span class="p"&gt;-&lt;/span&gt; 定数: SCREAMING_SNAKE_CASE

&lt;span class="gu"&gt;## テスト&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; ユニットテストは Vitest + Testing Library
&lt;span class="p"&gt;-&lt;/span&gt; E2E は Playwright (tests/e2e/)
&lt;span class="p"&gt;-&lt;/span&gt; テストファイルは対象ファイルと同階層に置く (UserCard.test.tsx)

&lt;span class="gu"&gt;## 禁止事項&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`console.log`&lt;/span&gt; をコミットしない (console.error は可)
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`eslint-disable`&lt;/span&gt; コメントを新規追加しない
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`pages/`&lt;/span&gt; ディレクトリへの新規ファイル追加禁止
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  運用Tips
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;粒度を絞る&lt;/strong&gt;：ルールが長すぎるとエージェントが重要度を判断できなくなる。「禁止事項」は5件以内を目安にし、守らせたいものだけ書く。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;サブディレクトリに分割する&lt;/strong&gt;：Claude Code は &lt;code&gt;src/app/CLAUDE.md&lt;/code&gt; のようにサブディレクトリのルールファイルも読む。&lt;code&gt;src/app/api/CLAUDE.md&lt;/code&gt; にAPI固有ルールを書くと、関係ない箇所への影響を局所化できる。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI で整合性を検証する&lt;/strong&gt;：ルールファイルに書いた規約をESLintや&lt;code&gt;tsc --noEmit&lt;/code&gt;のCIチェックと対応させる。エージェントが違反コードを生成しても、CIが自動で検出できる状態にしておく。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;定期的に更新する&lt;/strong&gt;：Next.jsのバージョンアップや方針変更があったときは即座に更新する。古いルールが残ると、エージェントが矛盾したコードを生成する原因になる。git管理し、変更理由をコミットメッセージに残すと後から追える。&lt;/p&gt;




&lt;h3&gt;
  
  
  5フレームワーク分の実例をまとめたキット
&lt;/h3&gt;

&lt;p&gt;Next.js/React/FastAPI/Godot/Express のルールファイル実例集を用意しました。&lt;a href="https://itsuya.gumroad.com/l/agentrules260617" rel="noopener noreferrer"&gt;👉 詳細・入手はこちら&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>cursor</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>【2026】Algolia 代替の全文検索SaaS比較：料金・移行コストで選ぶ</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Wed, 17 Jun 2026 02:03:37 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026-algolia-dai-ti-noquan-wen-jian-suo-saasbi-jiao-liao-jin-yi-xing-kosutodexuan-bu-503i</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026-algolia-dai-ti-noquan-wen-jian-suo-saasbi-jiao-liao-jin-yi-xing-kosutodexuan-bu-503i</guid>
      <description>&lt;h2&gt;
  
  
  結論（おすすめ1つ）
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Typesense Cloud&lt;/strong&gt; に乗り換えるべきだ。&lt;/p&gt;

&lt;p&gt;理由は3つある。まず Algolia と最も近い JSON API 設計を持つため、既存コードの改修量が最小で済む。次に OSS 版と Cloud 版で同一の動作保証があり、ローカル開発→本番への経路が単純だ。最後に、Algolia が課金対象とするオペレーション数ではなく、リソース消費ベースの料金体系を採用しており、検索頻度が高いほど相対コストが抑えられる。&lt;/p&gt;




&lt;h2&gt;
  
  
  比較表（料金/無料枠/移行コスト/対応言語）
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;サービス&lt;/th&gt;
&lt;th&gt;無料枠&lt;/th&gt;
&lt;th&gt;移行コスト&lt;/th&gt;
&lt;th&gt;日本語対応&lt;/th&gt;
&lt;th&gt;セルフホスト&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Algolia&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;基準&lt;/td&gt;
&lt;td&gt;トークナイザー設定要&lt;/td&gt;
&lt;td&gt;不可&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Typesense Cloud&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;低（API 構造が近似）&lt;/td&gt;
&lt;td&gt;kuromoji 不要・内蔵トークナイザー&lt;/td&gt;
&lt;td&gt;OSS 版可&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Meilisearch Cloud&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;中（API 設計が異なる）&lt;/td&gt;
&lt;td&gt;内蔵トークナイザーで対応&lt;/td&gt;
&lt;td&gt;OSS 版可&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenSearch Serverless&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;高（DSL が複雑）&lt;/td&gt;
&lt;td&gt;プラグイン追加必要&lt;/td&gt;
&lt;td&gt;可（AWS EC2等）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Elasticsearch Cloud&lt;/td&gt;
&lt;td&gt;公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;高（DSL が複雑）&lt;/td&gt;
&lt;td&gt;analysis-kuromoji 必須&lt;/td&gt;
&lt;td&gt;可&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;移行コストの判断基準：既存の Algolia SDK 呼び出し箇所を grep した際の修正行数を想定している。Typesense は公式が Algolia 互換レイヤー &lt;code&gt;@typesense/typesense-instantsearch-adapter&lt;/code&gt; を提供しており、フロントエンドの改修がほぼゼロで済むケースが多い。&lt;/p&gt;




&lt;h2&gt;
  
  
  移行手順
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Typesense をローカルで起動（Docker）
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8108:8108 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/typesense-data:/data &lt;span class="se"&gt;\&lt;/span&gt;
  typesense/typesense:26.0 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-dir&lt;/span&gt; /data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--api-key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;YOUR_LOCAL_API_KEY &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--enable-cors&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. 依存パッケージを差し替える
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Algolia SDK を削除し Typesense SDK を追加&lt;/span&gt;
npm uninstall algoliasearch
npm &lt;span class="nb"&gt;install &lt;/span&gt;typesense @typesense/typesense-instantsearch-adapter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. コレクション（= Algolia の Index）を定義する
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Typesense&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;typesense&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Typesense&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8108&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TYPESENSE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;connectionTimeoutSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;articles&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tags&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string[]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;facet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;created&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;int64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;default_sorting_field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;created&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Algolia からデータをエクスポートして投入する
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Algolia CLI でオブジェクトを JSONL に書き出す&lt;/span&gt;
algolia objects browse YOUR_INDEX_NAME &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; export.jsonl

&lt;span class="c"&gt;# Typesense の一括インポートエンドポイントに流し込む&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"http://localhost:8108/collections/articles/documents/import?action=create"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-TYPESENSE-API-KEY: YOUR_LOCAL_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: text/plain"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-binary&lt;/span&gt; @export.jsonl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. フロントエンドのアダプターを差し替える
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;TypesenseInstantSearchAdapter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@typesense/typesense-instantsearch-adapter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TypesenseInstantSearchAdapter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_TYPESENSE_SEARCH_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-cluster.typesense.net&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;additionalSearchParameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;query_by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title,body&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 既存の InstantSearch コンポーネントはそのまま使用可能&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;本番切り替え前に &lt;code&gt;typesense-exporter&lt;/code&gt; と Algolia の &lt;code&gt;browse&lt;/code&gt; を使ったダブルライト期間（1〜2週間）を設けて、件数の一致を確認してから DNS / 環境変数を切り替えることを強く勧める。&lt;/p&gt;




&lt;h2&gt;
  
  
  向き不向き
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Typesense が向くケース
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;スタートアップ〜中規模 SaaS&lt;/strong&gt;：ドキュメント数が数百万件以内で、Algolia 互換 API の恩恵を最大限に受けたい場合&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OSS ファーストのチーム&lt;/strong&gt;：本番は Cloud、ローカルは Docker という開発環境を統一したい場合&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;検索 UX を細かくカスタマイズしたい&lt;/strong&gt;：ファセット・ランキングルール・シノニムを JSON で宣言的に管理したい場合&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;日本語コンテンツ&lt;/strong&gt;：追加プラグインなしで日本語トークナイズが動作する（CJK 対応が内蔵）&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Typesense を避けるべきケース
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;億単位のドキュメントを扱う大規模サービス&lt;/strong&gt;：この規模は Elasticsearch / OpenSearch のシャーディング機能が実績面で上回る&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;全文検索以外の複合クエリが主体&lt;/strong&gt;：集計・地理検索・ベクトル検索を高度に組み合わせるなら OpenSearch の方が表現力が高い&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;既存インフラが AWS に完全集約されている&lt;/strong&gt;：OpenSearch Serverless との統合コスト（IAM・VPC・CloudWatch）が Typesense 移行コストを下回る場合がある&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Meilisearch を選ぶ理由があるとすれば
&lt;/h3&gt;

&lt;p&gt;Typesense より API が学習コスト低めで、セルフホスト前提の小規模プロジェクト（個人ブログ、社内ドキュメント検索など）には Meilisearch も競合する。ただし Algolia からの移行という文脈では、互換レイヤーの完成度で Typesense が一歩リードしている。&lt;/p&gt;

</description>
      <category>saas</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>【2026】Postman 代替の軽量APIクライアント比較：料金・移行コストで選ぶ</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Wed, 17 Jun 2026 02:00:47 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026-postman-dai-ti-noqing-liang-apikuraiantobi-jiao-liao-jin-yi-xing-kosutodexuan-bu-11gc</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026-postman-dai-ti-noqing-liang-apikuraiantobi-jiao-liao-jin-yi-xing-kosutodexuan-bu-11gc</guid>
      <description>&lt;h2&gt;
  
  
  結論（おすすめ1つ）
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;乗り換え先は Bruno 一択&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;Postman がアカウント必須化・クラウド同期強制に踏み切って以降、チームのコレクションをローカルの Git リポジトリで管理したい現場に最も刺さるのが Bruno だ。コレクションがディレクトリ＋&lt;code&gt;.bru&lt;/code&gt; テキストファイルとして保存されるため、PR レビューで差分を確認でき、CI パイプラインとの統合もシェルスクリプト一本で完結する。アカウント登録なし、強制アップデートなし、という点も業務利用での信頼感につながる。&lt;/p&gt;




&lt;h2&gt;
  
  
  比較表（料金/無料枠/移行コスト/対応言語）
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ツール&lt;/th&gt;
&lt;th&gt;料金・無料枠&lt;/th&gt;
&lt;th&gt;Postman からの移行コスト&lt;/th&gt;
&lt;th&gt;対応プロトコル&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bruno&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;OSS（MIT）。有料 Golden Edition あり、詳細は公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;低：Postman コレクション JSON を GUI から直接インポート可&lt;/td&gt;
&lt;td&gt;REST / GraphQL / gRPC（実験的）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hoppscotch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Self-host 版は無料。クラウド版は公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;中：Postman JSON インポート対応だが環境変数の手動整理が必要&lt;/td&gt;
&lt;td&gt;REST / GraphQL / WebSocket / SSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Insomnia&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;無料プランあり。チーム機能の上限は公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;低：専用インポーターあり&lt;/td&gt;
&lt;td&gt;REST / GraphQL / gRPC / SOAP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Thunder Client&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;VS Code 拡張。ベーシックは無料。Pro プランは公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;低〜中：Postman JSON インポート可、ただし Pre-request Script は非対応&lt;/td&gt;
&lt;td&gt;REST / GraphQL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  移行手順
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Bruno のインストール
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# macOS (Homebrew)&lt;/span&gt;
brew &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--cask&lt;/span&gt; bruno

&lt;span class="c"&gt;# Windows (winget)&lt;/span&gt;
winget &lt;span class="nb"&gt;install &lt;/span&gt;Bruno.Bruno

&lt;span class="c"&gt;# Linux (apt / snap)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;snap &lt;span class="nb"&gt;install &lt;/span&gt;bruno
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Postman コレクションのエクスポート
&lt;/h3&gt;

&lt;p&gt;Postman 側で対象コレクションを選択し、&lt;strong&gt;Export → Collection v2.1 (recommended)&lt;/strong&gt; として JSON ファイルに書き出す。&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Bruno へのインポート
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bruno を起動
→ [Import Collection]
→ [Postman Collection]
→ エクスポートした .json を選択
→ 保存先ディレクトリを指定（Git リポジトリ直下推奨）
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. 環境変数の移行
&lt;/h3&gt;

&lt;p&gt;Postman の Environment を JSON でエクスポートし、Bruno の環境ファイルに変換する。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# エクスポートした Postman 環境 JSON の構造確認&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;postman_env.json | python3 &lt;span class="nt"&gt;-m&lt;/span&gt; json.tool

&lt;span class="c"&gt;# Bruno の環境ファイルは .env 形式（コレクションルートに配置）&lt;/span&gt;
&lt;span class="c"&gt;# 例: environments/local.bru&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;local.bru&lt;/code&gt; の記述例：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hocon"&gt;&lt;code&gt;&lt;span class="nl"&gt;vars&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;base_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost:3000&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;your_key_here&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Git リポジトリへの追加
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;your-api-collection/
git init
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"*.env"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .gitignore   &lt;span class="c"&gt;# 秘密変数を含む環境ファイルは除外&lt;/span&gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"chore: migrate API collection from Postman to Bruno"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. CLI での自動実行（CI 連携）
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @usebruno/cli

&lt;span class="c"&gt;# コレクション全体を実行&lt;/span&gt;
bru run &lt;span class="nt"&gt;--env&lt;/span&gt; &lt;span class="nb"&gt;local&lt;/span&gt;

&lt;span class="c"&gt;# 特定フォルダのみ&lt;/span&gt;
bru run auth/ &lt;span class="nt"&gt;--env&lt;/span&gt; staging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  向き不向き
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;向いているケース&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;インフラ・バックエンドチームが Git ワークフローを中心に動いており、コレクションの変更履歴をコードと同じリポジトリで管理したい&lt;/li&gt;
&lt;li&gt;セキュリティポリシーによりクラウドへの API 仕様アップロードが制限されている組織&lt;/li&gt;
&lt;li&gt;1〜10 人規模のスモールチームで、重厚なコラボレーション機能より「動く軽さ」を優先したい&lt;/li&gt;
&lt;li&gt;CI/CD パイプラインでリグレッションテストとして API コレクションを回したい&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;避けるべきケース&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Postman の高度な Pre-request Script や Test Script を大量に書いており、JavaScript ベースのスクリプト資産が膨大な場合（Bruno のスクリプト API は Postman と互換性があるが、移行工数は都度確認が必要）&lt;/li&gt;
&lt;li&gt;ノーコード・非&lt;a href="https://www.amazon.co.jp/s?k=%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%20%E6%9C%AC&amp;amp;tag=1280itsuya22-22" rel="noopener noreferrer"&gt;エンジニア&lt;/a&gt;寄りのメンバーが GUI 操作のみで使う前提のチーム。Hoppscotch や Insomnia の方が直感的な場合がある&lt;/li&gt;
&lt;li&gt;WebSocket / SSE / MQTT など REST 以外のプロトコルを主に扱う場合は Hoppscotch の方が一歩先を行く&lt;/li&gt;
&lt;li&gt;組織のデバイス管理ポリシーでスナップ・外部バイナリのインストールが制限されているとき。Thunder Client（VS Code 拡張）のほうが導入障壁が低い&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>saas</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>【実体験】GPUクラウド比較：Runpod/Vast.ai/Lambdaで生成AIコストを1/3にする</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Wed, 17 Jun 2026 02:00:44 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/shi-ti-yan-gpukuraudobi-jiao-runpodvastailambdadesheng-cheng-aikosutowo13nisuru-13l2</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/shi-ti-yan-gpukuraudobi-jiao-runpodvastailambdadesheng-cheng-aikosutowo13nisuru-13l2</guid>
      <description>&lt;h1&gt;
  
  
  GPUクラウド比較：Runpod/Vast.ai/Lambdaで生成AIコストを1/3にする
&lt;/h1&gt;

&lt;h2&gt;
  
  
  結論：月3万円のGPU代が1万円以下になる
&lt;/h2&gt;

&lt;p&gt;AWS p3.2xlarge（V100, $3.06/h）で月100時間回していると約¥45,000。同等スペックをRunpodのスポットで借りると&lt;strong&gt;$0.20〜0.35/h&lt;/strong&gt;、Vast.aiなら&lt;strong&gt;$0.15〜0.25/h&lt;/strong&gt;まで落ちる。Lambda Labsの予約インスタンスはA100 80GBが$1.10/h固定と高めだが、SLA付きで本番推論に使える。用途別に使い分けるだけでコストは容易に1/3以下になる。&lt;/p&gt;




&lt;h2&gt;
  
  
  三サービスの実測スペック比較（2025年時点）
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;サービス&lt;/th&gt;
&lt;th&gt;GPU&lt;/th&gt;
&lt;th&gt;価格帯($/h)&lt;/th&gt;
&lt;th&gt;用途適性&lt;/th&gt;
&lt;th&gt;SLA&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Runpod Spot&lt;/td&gt;
&lt;td&gt;RTX 3090/4090, A100&lt;/td&gt;
&lt;td&gt;0.20〜0.79&lt;/td&gt;
&lt;td&gt;学習・バッチ推論&lt;/td&gt;
&lt;td&gt;なし（中断あり）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runpod Secure&lt;/td&gt;
&lt;td&gt;同上&lt;/td&gt;
&lt;td&gt;0.39〜1.20&lt;/td&gt;
&lt;td&gt;開発・検証&lt;/td&gt;
&lt;td&gt;あり&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vast.ai&lt;/td&gt;
&lt;td&gt;RTX 3090/4090, A6000&lt;/td&gt;
&lt;td&gt;0.15〜0.60&lt;/td&gt;
&lt;td&gt;実験・学習&lt;/td&gt;
&lt;td&gt;なし&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lambda Labs&lt;/td&gt;
&lt;td&gt;A100 40GB/80GB, H100&lt;/td&gt;
&lt;td&gt;1.10〜2.49&lt;/td&gt;
&lt;td&gt;本番API推論&lt;/td&gt;
&lt;td&gt;あり&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS p3.2xlarge&lt;/td&gt;
&lt;td&gt;V100 16GB&lt;/td&gt;
&lt;td&gt;3.06&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;あり&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  使い分け戦略
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;学習・ファインチューニング&lt;/strong&gt;：Vast.aiスポット。中断耐性のあるチェックポイント保存を入れれば実用十分。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;開発・検証&lt;/strong&gt;：Runpod Secure。SSHとJupyterが即時使えてポッド削除まで課金なし。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;本番推論API&lt;/strong&gt;：Lambda Labs。固定IPとSLAが取れる唯一の選択肢。&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Vast.aiで学習ジョブを中断耐性付きで動かす
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. CLI インストール&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;vastai

&lt;span class="c"&gt;# 2. APIキー設定&lt;/span&gt;
vastai &lt;span class="nb"&gt;set &lt;/span&gt;api-key YOUR_API_KEY

&lt;span class="c"&gt;# 3. RTX 4090 × 1 のオファーを探す（0.40$/h以下）&lt;/span&gt;
vastai search offers &lt;span class="s1"&gt;'gpu_name=RTX_4090 num_gpus=1 dph_total&amp;lt;0.40 inet_down&amp;gt;500'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--order&lt;/span&gt; &lt;span class="s1"&gt;'dph_total asc'&lt;/span&gt;

&lt;span class="c"&gt;# 4. インスタンス起動（PyTorch公式イメージ）&lt;/span&gt;
vastai create instance OFFER_ID &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt; pytorch/pytorch:2.3.0-cuda12.1-cudnn8-runtime &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--disk&lt;/span&gt; 50 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--env&lt;/span&gt; &lt;span class="s1"&gt;'-e HF_HOME=/workspace/hf_cache'&lt;/span&gt;

&lt;span class="c"&gt;# 5. SSH接続&lt;/span&gt;
vastai ssh-url INSTANCE_ID  &lt;span class="c"&gt;# -&amp;gt; ssh -p PORT root@HOST&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;学習スクリプト側では &lt;code&gt;transformers.TrainingArguments&lt;/code&gt; の &lt;code&gt;save_steps=100&lt;/code&gt; と &lt;code&gt;resume_from_checkpoint=True&lt;/code&gt; を必ず設定しておく。中断されても最終チェックポイントから再開できる。&lt;/p&gt;




&lt;h2&gt;
  
  
  RunpodでvLLMの推論サーバを5分で立てる
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Runpod CLI（公式）&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;runpod

&lt;span class="c"&gt;# テンプレートIDはWeb UIで確認 or API経由&lt;/span&gt;
&lt;span class="c"&gt;# 以下はcurlで直接ポッド起動する例&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.runpod.io/graphql &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$RUNPOD_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "query": "mutation { podFindAndDeployOnDemand(input: { gpuTypeId: \"NVIDIA GeForce RTX 4090\", containerDiskInGb: 40, volumeInGb: 0, minMemoryInGb: 20, minVcpuCount: 4, imageName: \"vllm/vllm-openai:latest\", env: [{key: \"MODEL_ID\", value: \"meta-llama/Llama-3-8B-Instruct\"}], ports: \"8000/http\" }) { id } }"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;起動後はRunpodが発行する &lt;code&gt;https://&amp;lt;pod-id&amp;gt;-8000.proxy.runpod.net&lt;/code&gt; にOpenAI互換エンドポイントが生える。既存コードの &lt;code&gt;base_url&lt;/code&gt; を差し替えるだけで動く。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://&amp;lt;pod-id&amp;gt;-8000.proxy.runpod.net/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dummy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# vLLMはキー不要
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta-llama/Llama-3-8B-Instruct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  コスト削減の実数
&lt;/h2&gt;

&lt;p&gt;Llama-3-8Bを1日8時間、月20日推論させるケース（160h/月）：&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;環境&lt;/th&gt;
&lt;th&gt;時間単価&lt;/th&gt;
&lt;th&gt;月額&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AWS p3.2xlarge&lt;/td&gt;
&lt;td&gt;$3.06&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$490&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runpod Spot RTX4090&lt;/td&gt;
&lt;td&gt;$0.34&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$54&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vast.ai RTX4090&lt;/td&gt;
&lt;td&gt;$0.22&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$35&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;削減率は&lt;strong&gt;Vast.aiで93%&lt;/strong&gt;。「1/3」どころかほぼ1/10になる。Lambda LabsのA100でも$1.10 × 160h = $176で AWS比64%減。&lt;/p&gt;




&lt;h2&gt;
  
  
  注意点
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Vast.aiはホストの個人PCも混在&lt;/strong&gt;する。機密データの学習には使わない。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;スポットは突然中断&lt;/strong&gt;される。&lt;code&gt;nvidia-smi&lt;/code&gt; で確認できるGPU使用率が急落したらあらかじめ想定しておく。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ストレージは別課金&lt;/strong&gt;。Runpodのネットワークボリューム（$0.07/GB/月）にモデルを置いて、ポッドをまたいで再利用するとダウンロード時間とコストを節約できる。&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  まとめ
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;目的&lt;/th&gt;
&lt;th&gt;選択肢&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ファインチューニング（中断OK）&lt;/td&gt;
&lt;td&gt;Vast.ai スポット&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;開発・動作確認&lt;/td&gt;
&lt;td&gt;Runpod Secure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;本番推論（SLA必須）&lt;/td&gt;
&lt;td&gt;Lambda Labs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;AWSやGCPからの移行に必要なのはDockerイメージとAPIキーの差し替えだけ。まずRunpodで1ポッド立ててコマンドを叩いてみるのが一番早い。&lt;/p&gt;




&lt;h2&gt;
  
  
  関連リンク
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://itsuya.gumroad.com/l/aikit260617" rel="noopener noreferrer"&gt;AI開発・自動化の実践キット / プロンプト集（Gumroad）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;small&gt;※自社商品（プロモーションを含みます）。&lt;/small&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
