<?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】Datadog 代替の低価格監視SaaS：料金・移行コストで選ぶ</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Sun, 05 Jul 2026 02:03:43 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026-datadog-dai-ti-nodi-jia-ge-jian-shi-saasliao-jin-yi-xing-kosutodexuan-bu-20mo</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026-datadog-dai-ti-nodi-jia-ge-jian-shi-saasliao-jin-yi-xing-kosutodexuan-bu-20mo</guid>
      <description>&lt;h2&gt;
  
  
  結論（おすすめ1つ）
&lt;/h2&gt;

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

&lt;p&gt;Prometheus/Loki/Tempoのエコシステムをそのまま使えるため、既存のインフラ資産を捨てずに済む。無料枠が実用範囲に収まっており、小〜中規模サービスならコストゼロで本番運用できる。エージェント互換性が高く、Datadogエージェントのドロップイン代替として機能するため移行コストが低い。&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;Grafana Cloud&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;メトリクス/ログ/トレース量従量&lt;/td&gt;
&lt;td&gt;あり（公式の料金ページで要確認）&lt;/td&gt;
&lt;td&gt;低：Prometheusエクスポーター流用可&lt;/td&gt;
&lt;td&gt;Go/&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;/JS/Java/Ruby/.NET 他&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;New Relic&lt;/strong&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;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SigNoz&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;セルフホスト無料／クラウド従量&lt;/td&gt;
&lt;td&gt;セルフホストは実質無制限&lt;/td&gt;
&lt;td&gt;中：OpenTelemetryへの書き換えが必要&lt;/td&gt;
&lt;td&gt;OpenTelemetry対応言語すべて&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Better Stack&lt;/strong&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;ログ中心、APMは限定的&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Datadog（参考）&lt;/strong&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;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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

&lt;p&gt;Grafana Cloud への移行を例に示す。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1：Grafana Cloud アカウント作成・スタックURL取得&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Grafana Cloud のダッシュボードにログインし、スタックの &lt;code&gt;PROMETHEUS_URL&lt;/code&gt;・&lt;code&gt;LOKI_URL&lt;/code&gt;・&lt;code&gt;API_KEY&lt;/code&gt; を控える。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2：Grafana Alloy（旧 Grafana Agent）をインストール&lt;/strong&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;# Linux (systemd)&lt;/span&gt;
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://apt.grafana.com/gpg.key | &lt;span class="nb"&gt;sudo &lt;/span&gt;gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; /etc/apt/keyrings/grafana.gpg

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [signed-by=/etc/apt/keyrings/grafana.gpg] &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  https://apt.grafana.com stable main"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/grafana.list

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; alloy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3：設定ファイルを記述&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# /etc/alloy/config.alloy&lt;/span&gt;

&lt;span class="nx"&gt;prometheus&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remote_write&lt;/span&gt; &lt;span class="s2"&gt;"grafana_cloud"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;endpoint&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;url&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="s2"&gt;"PROMETHEUS_URL"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;basic_auth&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;username&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="s2"&gt;"GRAFANA_INSTANCE_ID"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;password&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="s2"&gt;"GRAFANA_API_KEY"&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="nx"&gt;prometheus&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrape&lt;/span&gt; &lt;span class="s2"&gt;"local"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;targets&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="s2"&gt;"__address__"&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"localhost:9090"&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
  &lt;span class="nx"&gt;forward_to&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prometheus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remote_write&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grafana_cloud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;loki&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt; &lt;span class="s2"&gt;"grafana_cloud"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;endpoint&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;url&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="s2"&gt;"LOKI_URL"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;basic_auth&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;username&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="s2"&gt;"GRAFANA_INSTANCE_ID"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;password&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="s2"&gt;"GRAFANA_API_KEY"&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="nx"&gt;loki&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="s2"&gt;"app_logs"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;targets&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="nx"&gt;__path__&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/var/log/app/*.log"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;job&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;forward_to&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loki&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grafana_cloud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;receiver&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;strong&gt;Step 4：サービス起動と疎通確認&lt;/strong&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="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;alloy &lt;span class="nt"&gt;--now&lt;/span&gt;

&lt;span class="c"&gt;# Grafana Cloud 上でメトリクスが届いているか確認&lt;/span&gt;
&lt;span class="c"&gt;# Explore → Metrics → {job="app"} で検索&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5：Datadog エージェントの停止&lt;/strong&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="nb"&gt;sudo &lt;/span&gt;systemctl stop datadog-agent
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl disable datadog-agent
&lt;span class="c"&gt;# 完全アンインストールする場合&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get remove &lt;span class="nt"&gt;--purge&lt;/span&gt; datadog-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 6：既存ダッシュボードの移行&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;DatadogのダッシュボードJSONをエクスポートし、&lt;code&gt;dd-to-grafana&lt;/code&gt; などのOSSコンバーターを通すか、Grafana上で手動再現する。アラートルールはPromQL/LogQLで書き直す必要がある。&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;すでにPrometheus/Grafanaスタックを自前運用しているチーム：設定の大半を流用できる&lt;/li&gt;
&lt;li&gt;OpenTelemetry対応を進めているチーム：ベンダーロックを避けつつSaaSの運用負荷ゼロを両立できる&lt;/li&gt;
&lt;li&gt;ログ・メトリクス・トレースを一元管理したいが、Datadogの請求が予測困難で困っているチーム&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;APMのコードレベル可視化（関数単位のフレームグラフなど）をGUI上で深掘りしたい場合：Datadogのような深度には及ばない&lt;/li&gt;
&lt;li&gt;Kubernetes大規模クラスタ（数百ノード超）をフルマネージドで監視したい場合：無料枠をすぐ超え、コストシミュレーションを先に行う必要がある&lt;/li&gt;
&lt;li&gt;セキュリティ監査ログ（SIEM相当）を同一プラットフォームで完結させたいチーム：専用SIEMとの併用が現実的&lt;/li&gt;
&lt;li&gt;エンジニアリソースが逼迫しており、移行作業に1〜2スプリントも割けないチーム：移行コストが低いとはいえ、ゼロではない&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>saas</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>【2026】Mailchimp 代替のトランザクションメールAPI：料金・移行コストで選ぶ</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Sun, 05 Jul 2026 02:02:22 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026-mailchimp-dai-ti-notoranzakusiyonmeruapiliao-jin-yi-xing-kosutodexuan-bu-2djj</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026-mailchimp-dai-ti-notoranzakusiyonmeruapiliao-jin-yi-xing-kosutodexuan-bu-2djj</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;&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; Email との統合が標準で、&lt;a href="https://www.amazon.co.jp/s?k=TypeScript%20%E6%9C%AC&amp;amp;tag=1280itsuya22-22" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt; 型定義がファーストクラス対応であるため、現代的なスタック（Next.js / Node.js）と最も摩擦なく繋がる。SMTP リレーではなく HTTP API 単一エンドポイントで完結するため、Mailchimp の複雑な設定を捨てて 30 分以内に本番送信まで到達できた。DKIM・SPF の DNS 設定も管理画面で自動生成されるので、メール到達率の確保を自分でゼロから調べる必要がない。&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;低：HTTP API のみ&lt;/td&gt;
&lt;td&gt;Node / &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 / Elixir など公式 SDK 多数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Postmark&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;あり（テスト用クレジット）&lt;/td&gt;
&lt;td&gt;送信数従量課金（公式要確認）&lt;/td&gt;
&lt;td&gt;低〜中：SMTP と API 両対応&lt;/td&gt;
&lt;td&gt;Node / PHP / Ruby / Python / .NET / Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SendGrid&lt;/strong&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;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mailgun&lt;/strong&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;Node / Python / PHP / Ruby / Java&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AWS SES&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;無料枠あり（EC2 経由に条件）&lt;/td&gt;
&lt;td&gt;最安水準（公式要確認）&lt;/td&gt;
&lt;td&gt;高：IAM / バウンス処理を自前実装&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;Mailchimp Transactional（旧 Mandrill）は Mailchimp 本体との強制バンドルが最大の痛点だった。上記の代替はいずれも単独契約できる。&lt;/p&gt;




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

&lt;p&gt;ここでは Resend への移行を例示する。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: SDK インストール&lt;/strong&gt;&lt;br&gt;
&lt;/p&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;resend
&lt;span class="c"&gt;# Python の場合&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;resend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: API キー取得と環境変数設定&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Resend ダッシュボード → API Keys → Create API Key でキーを発行する。&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;# .env&lt;/span&gt;
&lt;span class="nv"&gt;RESEND_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;re_xxxxxxxxxxxxxxxxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: 送信ドメインの DNS 設定&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ダッシュボード → Domains → Add Domain でドメインを追加すると、以下の形式のレコードが表示される。これを DNS プロバイダへ登録する。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TXT  resend._domainkey.example.com  "v=DKIM1; k=rsa; p=..."
TXT  example.com                    "v=spf1 include:amazonses.com ~all"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;検証完了まで数分〜数時間かかる。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: 最小送信コード（Node.js）&lt;/strong&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="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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendTransactional&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&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;no-reply@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;to&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="s2"&gt;`注文確認 #&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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="s2"&gt;`&amp;lt;p&amp;gt;ご注文ありがとうございます。注文番号: &amp;lt;strong&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&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;strong&gt;Step 5: Mailchimp Transactional からの切り替え&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;旧コードで &lt;code&gt;mailchimp_transactional.ApiClient&lt;/code&gt; を呼んでいた箇所を上記関数に置換する。テンプレート ID による呼び出しを使っていた場合は、React Email または通常の HTML 文字列テンプレートへ変換する。&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="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;"mailchimp_transactional&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;mandrill"&lt;/span&gt; src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 6: バウンス・Webhook 設定&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ダッシュボード → Webhooks → Add Endpoint でバウンスや配信失敗イベントを自前 API エンドポイントへ転送するよう設定する。Mailchimp 側の 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;TypeScript / Node.js または Python ファーストのスタックで開発している小〜中規模チーム&lt;/li&gt;
&lt;li&gt;React Email でメールテンプレートをコンポーネント化したい場合（Resend が最適）&lt;/li&gt;
&lt;li&gt;Mailchimp の月額コストを削りたい、かつトランザクション送信に特化したい場合&lt;/li&gt;
&lt;li&gt;SES を使いたいが IAM 管理やバウンス処理の自前実装工数を払いたくない場合（Resend/Postmark が SES 上で動く構成を取ることもある）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;避けるべきケース・注意点&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;大量の既存 Mandrill テンプレート（Handlebars 形式）をそのまま移植したい場合：変換工数がかかる。SendGrid の Dynamic Templates の方が構文が近い&lt;/li&gt;
&lt;li&gt;送信数が月数百万通を超える規模で単価を極限まで下げたい場合：AWS SES の直接利用が費用面では有利だが、バウンス処理・レピュテーション管理を自前で担う覚悟が必要&lt;/li&gt;
&lt;li&gt;.NET / Java がメインで公式 SDK の成熟度を重視する場合：SendGrid または Postmark の方が実績が長い&lt;/li&gt;
&lt;li&gt;SMTP リレーを既存インフラ（レガシー PHP など）から変えられない場合：Resend より Postmark や Mailgun の SMTP エンドポイントを使う方が移行コストが低い&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>Sun, 05 Jul 2026 02:01:26 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026-auth0-dai-ti-clerksupabase-authworkosliao-jin-yi-xing-kosutodexuan-bu-3coa</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026-auth0-dai-ti-clerksupabase-authworkosliao-jin-yi-xing-kosutodexuan-bu-3coa</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 からの移行先として、大半の SPA／Next.js プロジェクトには &lt;strong&gt;Clerk&lt;/strong&gt; が最もコストパフォーマンスが高い。理由は三点：① UI コンポーネントが同梱されており認証フローをほぼゼロ実装で置き換えられる、② JWT／Session Token の切り替えが設定一つで完結する、③ Auth0 の「Organizations」に相当するマルチテナント機能が標準搭載されている。WorkOS は SSO／SAML が最優先の B2B 向け、Supabase Auth は Supabase の DB を既に使っている場合に限り有利な選択肢だ。&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;Auth0&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;無料枠 MAU&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;/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;/td&gt;
&lt;td&gt;―&lt;/td&gt;
&lt;td&gt;低〜中（SDK入替＋JWT検証変更）&lt;/td&gt;
&lt;td&gt;中（GoTrue API の理解が必要）&lt;/td&gt;
&lt;td&gt;中〜高（SSO設定が前提）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SDK の充実度&lt;/td&gt;
&lt;td&gt;◎&lt;/td&gt;
&lt;td&gt;◎（&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;/Next.js/Remix 中心）&lt;/td&gt;
&lt;td&gt;○（Supabase JS 中心）&lt;/td&gt;
&lt;td&gt;○（Node/Go 中心）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;対応言語&lt;/td&gt;
&lt;td&gt;Node/&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/Java 等&lt;/td&gt;
&lt;td&gt;JS/TS（他は REST API）&lt;/td&gt;
&lt;td&gt;JS/TS/Dart/Python 等&lt;/td&gt;
&lt;td&gt;Node/Python/Go/Ruby 等&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;マルチテナント&lt;/td&gt;
&lt;td&gt;有（Organizations）&lt;/td&gt;
&lt;td&gt;有（Organizations）&lt;/td&gt;
&lt;td&gt;要自前実装&lt;/td&gt;
&lt;td&gt;有（Enterprise SSO 中心）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;エンタープライズ SSO&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;/td&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;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;料金は変動が激しいため、&lt;strong&gt;各サービスの公式料金ページで必ず最新値を確認すること。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




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

&lt;p&gt;Auth0 → Clerk への移行を例に、実際に動くコマンドと設定を示す。&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1：Clerk アプリを作成して API キーを取得
&lt;/h3&gt;

&lt;p&gt;Clerk ダッシュボード（clerk.com）でアプリを新規作成し、Publishable Key と Secret Key を取得する。&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2：SDK を入れ替える
&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;# Next.js の場合&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; @clerk/nextjs

&lt;span class="c"&gt;# 既存の Auth0 パッケージを削除&lt;/span&gt;
npm uninstall @auth0/nextjs-auth0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3：環境変数を差し替える
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;.env.local&lt;/code&gt; を以下のように更新する。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 削除する Auth0 変数
# AUTH0_SECRET=...
# AUTH0_ISSUER_BASE_URL=...
# AUTH0_CLIENT_ID=...
# AUTH0_CLIENT_SECRET=...

# 追加する Clerk 変数
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_live_xxxxxxxxxx
CLERK_SECRET_KEY=sk_live_xxxxxxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4：ミドルウェアを置き換える
&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;// 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;clerkMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createRouteMatcher&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;@clerk/nextjs/server&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;isPublicRoute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRouteMatcher&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/sign-in(.*)&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="s1"&gt;/sign-up(.*)&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;clerkMiddleware&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;isPublicRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;protect&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="s1"&gt;/((?!_next|[^?]*&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico)).*)&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="s1"&gt;/(api|trpc)(.*)&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;h3&gt;
  
  
  Step 5：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="s1"&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;UserButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SignInButton&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;@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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isSignedIn&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useUser&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;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isSignedIn&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserButton&lt;/span&gt; &lt;span class="na"&gt;afterSignOutUrl&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SignInButton&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;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 6：既存ユーザーをインポートする
&lt;/h3&gt;

&lt;p&gt;Auth0 の Management API でユーザーリストをエクスポートし、Clerk の Backend API でインポートする。Auth0 はパスワードハッシュをエクスポートできないため、&lt;strong&gt;初回ログイン時にパスワードリセットを促すフローを実装する&lt;/strong&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;# Auth0 Management API でユーザーをエクスポート（要 Management API トークン）&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET &lt;span class="s2"&gt;"https://YOUR_DOMAIN.auth0.com/api/v2/users"&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;$AUTH0_MGMT_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; users_export.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clerk Backend API でユーザーをインポート（Node スクリプト例）&lt;/span&gt;
node scripts/import_users_to_clerk.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js／React 中心のチーム&lt;/strong&gt;：公式コンポーネントをそのまま使えるため実装工数が最小で済む。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1〜20 名規模のスタートアップ&lt;/strong&gt;：Auth0 の設定複雑さに疲れており、すぐに動かしたい場合。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;マルチテナント SaaS を構築している&lt;/strong&gt;：Organizations が標準搭載されており追加実装が少ない。&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Supabase の PostgreSQL を既に使っている&lt;/strong&gt;：Row Level Security と Auth を一体化できるため二重管理が不要になる。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;セルフホストが必要なプロジェクト&lt;/strong&gt;：Auth0・Clerk・WorkOS はすべてクラウド専用だが、Supabase はセルフホスト可能。&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;エンタープライズ顧客への SAML／OIDC SSO が必須の B2B SaaS&lt;/strong&gt;：この用途に特化しており、管理 UI が最も整っている。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active Directory 連携（SCIM）が要件&lt;/strong&gt;：ディレクトリ同期の実装コストが他と比べて大幅に低い。&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clerk&lt;/strong&gt;：iOS／Android ネイティブアプリが主体のプロジェクトには SDK の厚みが不足することがある。REST API 経由での実装は可能だが、Auth0 のモバイル SDK と比べると薄い。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supabase Auth&lt;/strong&gt;：Supabase の DB や Storage を使わず Auth 単体だけを採用するのはオーバーヘッドが大きい。認証専用なら Clerk の方が素直に使える。&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>I ran Claude Code unattended for months. Here's the 10-chapter book of everything that broke (and worked)</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Sat, 04 Jul 2026 14:42:31 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/i-ran-claude-code-unattended-for-months-heres-the-10-chapter-book-of-everything-that-broke-and-59mg</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/i-ran-claude-code-unattended-for-months-heres-the-10-chapter-book-of-everything-that-broke-and-59mg</guid>
      <description>&lt;p&gt;I've been running Claude Code as a daily unattended worker for months — generating articles, rebuilding an 800+ page static site, updating ML prediction sites — all fired by Task Scheduler every morning with nobody at the keyboard.&lt;/p&gt;

&lt;p&gt;I put everything I learned into a 10-chapter ebook: &lt;strong&gt;Practical Claude Code — Development, Automation, and Unattended Operation with the CLI Agent&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's inside
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Install to first productive session (including Windows-specific gotchas)&lt;/li&gt;
&lt;li&gt;CLAUDE.md / settings.json / hooks configs you can drop in as-is&lt;/li&gt;
&lt;li&gt;Designing headless pipelines with &lt;code&gt;claude -p&lt;/code&gt; (JSON output, retries, timeouts)&lt;/li&gt;
&lt;li&gt;Running it unattended on a schedule — and keeping it alive&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The failures&lt;/strong&gt;: the 6-hour pipe hang, the 2-hour git credential-prompt stall, LLMs fabricating numbers (and the pre-publish sanitizer that fixed it)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No revenue hype, no "AI will 10x you" — just the working setup and the scars.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ebook (EPUB, 10 chapters)&lt;/strong&gt;: &lt;a href="https://itsuya.gumroad.com/l/claudecodebooken" rel="noopener noreferrer"&gt;https://itsuya.gumroad.com/l/claudecodebooken&lt;/a&gt; (~$9)&lt;/li&gt;
&lt;li&gt;Launch: code &lt;code&gt;START50&lt;/code&gt; = 50% off → &lt;a href="https://itsuya.gumroad.com/l/claudecodebooken/START50" rel="noopener noreferrer"&gt;https://itsuya.gumroad.com/l/claudecodebooken/START50&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Companion kit: &lt;a href="https://itsuya.gumroad.com/l/errfixen/START50" rel="noopener noreferrer"&gt;50 AI Debugging Prompts + Claude Code Config Pack&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questions welcome in the comments — I'll fold answers back into the book.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: my own book; written with AI assistance and human review/editing.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>productivity</category>
      <category>ebook</category>
    </item>
    <item>
      <title>2026年版・AIエージェント(FastAPI)に渡すルールファイル実践ガイド</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Sat, 04 Jul 2026 02:04:41 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026nian-ban-aiezientofastapinidu-sururuhuairushi-jian-gaido-4jkm</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026nian-ban-aiezientofastapinidu-sururuhuairushi-jian-gaido-4jkm</guid>
      <description>&lt;h2&gt;
  
  
  なぜルールファイルがエージェント品質を左右するか
&lt;/h2&gt;

&lt;p&gt;FastAPIで構築したAIエージェントにClaude CLIやCursorを組み合わせるとき、LLMへの「指示の揺れ」が最大のボトルネックになる。同じコードベースを触らせても、プロンプトが毎回違えば出力も毎回ブレる。&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;LLMはコンテキストウィンドウの先頭に近いテキストを強く参照する。リポジトリルートに置いたルールファイルはツールが自動でコンテキスト先頭に挿入するため、毎回プロンプトに書かなくても設計意図が伝わる。&lt;/p&gt;




&lt;h2&gt;
  
  
  実例：FastAPIプロジェクト向け 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;# CLAUDE.md — AIエージェント行動ルール&lt;/span&gt;

&lt;span class="gu"&gt;## プロジェクト概要&lt;/span&gt;
Python 3.12 / FastAPI 0.111 / PostgreSQL 16 で構築した
REST API サーバー。非同期 I/O (asyncpg) を全面採用。

&lt;span class="gu"&gt;## コーディング規約&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; 型アノテーションを必ず付ける(py.typed 準拠)
&lt;span class="p"&gt;-&lt;/span&gt; Pydantic v2 モデルで入出力を定義する
&lt;span class="p"&gt;-&lt;/span&gt; ルーターは &lt;span class="sb"&gt;`src/routers/`&lt;/span&gt; に機能単位で分割する
&lt;span class="p"&gt;-&lt;/span&gt; テストは pytest-asyncio + httpx.AsyncClient で書く

&lt;span class="gu"&gt;## 禁止事項&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`time.sleep()`&lt;/span&gt; の使用禁止。&lt;span class="sb"&gt;`asyncio.sleep()`&lt;/span&gt; を使う
&lt;span class="p"&gt;-&lt;/span&gt; グローバル変数への副作用を持つ関数を作らない
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`.env`&lt;/span&gt; の値をコードにハードコードしない

&lt;span class="gu"&gt;## エージェントへの追加指示&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; 既存関数を書き換える前に「変更理由」を1行コメントで残す
&lt;span class="p"&gt;-&lt;/span&gt; DBスキーマ変更を伴う場合は Alembic マイグレーションファイルも生成する
&lt;span class="p"&gt;-&lt;/span&gt; PR説明文は英語、コードコメントは日本語で統一する

&lt;span class="gu"&gt;## 参照ドキュメント&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; API仕様: docs/openapi.yaml
&lt;span class="p"&gt;-&lt;/span&gt; ERD: docs/erd.png
&lt;span class="p"&gt;-&lt;/span&gt; 環境変数一覧: .env.example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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 CLI / Claude Code&lt;/td&gt;
&lt;td&gt;プロジェクト全体の設計思想と禁止事項&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 IDE&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 Agents SDK など&lt;/td&gt;
&lt;td&gt;エージェント同士の役割分担と通信プロトコル&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;FastAPIプロジェクトでは &lt;code&gt;CLAUDE.md&lt;/code&gt; を最上位に置き、サブディレクトリ(&lt;code&gt;src/routers/&lt;/code&gt;など)にも局所的な補足を置く階層構造が実用的だ。Claude CLIはディレクトリを上から下へ収集して結合するため、上位の方針を下位で上書きできる。&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;1. 「禁止事項」を先に書く&lt;/strong&gt;&lt;br&gt;
LLMは許可より禁止の方が遵守率が高い。&lt;code&gt;asyncio.sleep()&lt;/code&gt; の強制など、型チェッカーで検出できないルールほど明示する効果が大きい。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. ルールは測定可能な形にする&lt;/strong&gt;&lt;br&gt;
「良いコードを書く」ではなく「型アノテーションを必ず付ける」のように、LLMが自己検証できる粒度にする。曖昧なルールは無視される。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. CIでルールの整合性を検証する&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;ruff&lt;/code&gt; や &lt;code&gt;mypy&lt;/code&gt; をCIに組み込み、ルールファイルで定めた規約が守られているかを自動確認する。エージェントが破ったルールはCIが検知し、次のプロンプトでフィードバックする仕組みにすると自己修正ループが回る。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. 変更履歴をコミットメッセージに残す&lt;/strong&gt;&lt;br&gt;
ルールファイル自体もGit管理し、なぜそのルールを追加・削除したかをコミットメッセージに書く。3ヶ月後に「このルールは何のために？」と迷う時間を省ける。&lt;/p&gt;




&lt;p&gt;ルールファイルは銀の弾丸ではないが、エージェントの出力を「毎回ゼロから説明する」から「既知の前提の上に積む」に変える最も低コストな手段だ。まず10行の &lt;code&gt;CLAUDE.md&lt;/code&gt; から始めて、エージェントが迷うたびに1行追加する運用が現実的に続く。&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/agentrules260704" rel="noopener noreferrer"&gt;👉 詳細・入手はこちら&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>cursor</category>
      <category>fastapi</category>
    </item>
    <item>
      <title>【2026】Auth0 代替 (Clerk/Supabase Auth/WorkOS)：料金・移行コストで選ぶ</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Sat, 04 Jul 2026 02:03:49 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026-auth0-dai-ti-clerksupabase-authworkosliao-jin-yi-xing-kosutodexuan-bu-4j5j</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026-auth0-dai-ti-clerksupabase-authworkosliao-jin-yi-xing-kosutodexuan-bu-4j5j</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;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; が主戦場のチームなら、Clerk が現時点で移行コストと開発体験のバランスに最も優れている。理由は3点：SDK がフレームワーク単位で設計されており認証 UI の自前実装がほぼ不要、JWT／セッション管理がデフォルトで安全な構成になっている、Auth0 と同等のソーシャルログイン・MFA をダッシュボード操作だけで完結できる。&lt;/p&gt;

&lt;p&gt;ただし、エンタープライズ SSO（SAML／SCIM）が受注条件になっている B2B SaaS チームは WorkOS、既存スタックが Supabase ベースなら Supabase Auth を先に評価すること。&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;Auth0&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;MAU 上限あり（公式の料金ページで要確認）&lt;/td&gt;
&lt;td&gt;MAU 上限あり（公式の料金ページで要確認）&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;MAU ベース&lt;/td&gt;
&lt;td&gt;プロジェクト数・機能&lt;/td&gt;
&lt;td&gt;SSO コネクション単位&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;移行コスト&lt;/td&gt;
&lt;td&gt;―&lt;/td&gt;
&lt;td&gt;中（SDK 差替・JWT claims 変更）&lt;/td&gt;
&lt;td&gt;中〜高（DB 統合が前提）&lt;/td&gt;
&lt;td&gt;高（SSO 設定・ユーザー移行）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;主対応言語&lt;/td&gt;
&lt;td&gt;多言語（公式 SDK 多数）&lt;/td&gt;
&lt;td&gt;JS/TS 中心（React/Next.js 特化）&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 ほか&lt;/td&gt;
&lt;td&gt;JS/TS・Python・Go ほか&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;可（OSS）&lt;/td&gt;
&lt;td&gt;不可&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SAML/SCIM&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;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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

&lt;p&gt;Auth0 から Clerk への移行を例に、実際に踏んだ手順を示す。&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Clerk 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;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;# .env.local（Auth0 の変数を削除し Clerk の変数に置き換える）&lt;/span&gt;

&lt;span class="c"&gt;# 削除対象&lt;/span&gt;
&lt;span class="c"&gt;# AUTH0_SECRET=...&lt;/span&gt;
&lt;span class="c"&gt;# AUTH0_BASE_URL=...&lt;/span&gt;
&lt;span class="c"&gt;# AUTH0_ISSUER_BASE_URL=...&lt;/span&gt;
&lt;span class="c"&gt;# AUTH0_CLIENT_ID=...&lt;/span&gt;
&lt;span class="c"&gt;# AUTH0_CLIENT_SECRET=...&lt;/span&gt;

&lt;span class="c"&gt;# 追加&lt;/span&gt;
&lt;span class="nv"&gt;NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pk_test_xxxx
&lt;span class="nv"&gt;CLERK_SECRET_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk_test_xxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. ミドルウェアの設定（Next.js App Router）
&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;// 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;clerkMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createRouteMatcher&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;@clerk/nextjs/server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isProtected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRouteMatcher&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/dashboard(.*)&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;clerkMiddleware&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isProtected&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;protect&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="s1"&gt;/((?!_next|.*&lt;/span&gt;&lt;span class="se"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Auth0 のユーザーデータを取得
&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;# Auth0 Management API でユーザー一覧を JSON に落とす&lt;/span&gt;
curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$AUTH0_MGMT_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://YOUR_DOMAIN.auth0.com/api/v2/users?per_page=100"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; auth0_users.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Clerk へユーザーをインポート
&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;// scripts/migrate-users.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;clerkClient&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;@clerk/nextjs/server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;users&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;./auth0_users.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;for &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;u&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;users&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;clerkClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;emailAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="c1"&gt;// Auth0 の user_id を externalId として保持しておくと&lt;/span&gt;
    &lt;span class="c1"&gt;// 既存 DB レコードとの突合スクリプトが楽になる&lt;/span&gt;
    &lt;span class="na"&gt;externalId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_id&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;パスワードハッシュ（bcrypt）のインポートは Clerk のバルクインポート API が対応しているか事前に公式ドキュメントで確認すること。未対応の場合はパスワードリセットメールをユーザーに送る運用が現実的。&lt;/p&gt;

&lt;h3&gt;
  
  
  6. JWT Claims の差し替え確認
&lt;/h3&gt;

&lt;p&gt;Auth0 の &lt;code&gt;sub&lt;/code&gt; クレームは &lt;code&gt;auth0|xxxxx&lt;/code&gt; 形式になっているため、バックエンド側の認証ミドルウェアが期待する形式と一致しなくなる。Clerk では &lt;code&gt;userId&lt;/code&gt; を取得して既存の DB レコードと突合する移行スクリプトを本番切り替え前に必ず実行する。&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 を主軸にした SaaS でスピード優先&lt;/li&gt;
&lt;li&gt;フロントエンド中心のスタートアップ（認証 UI を自前実装したくない）&lt;/li&gt;
&lt;li&gt;Auth0 の料金が MAU 増加で無視できなくなってきたチーム&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;セルフホストが必要なコンプライアンス要件がある&lt;/li&gt;
&lt;li&gt;バックエンド中心の構成で Next.js 以外のフレームワークを使っている&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;受注条件に SAML SSO・SCIM プロビジョニングが含まれる B2B SaaS&lt;/li&gt;
&lt;li&gt;大企業顧客を相手にする予定があり、監査ログ・ディレクトリ同期が必須&lt;/li&gt;
&lt;li&gt;エンタープライズ対応を将来的に見越して最初から設計したい&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Clerk：Vue・Django・Rails 等が主体の場合、SDK の成熟度に差があり検証コストが増す。React 以外では素直に Supabase Auth か Auth0 を評価し直すほうが早い&lt;/li&gt;
&lt;li&gt;Supabase Auth：Auth0 のカスタムアクション（ルールエンジン）を多用しているプロジェクトは機能差を先に精査すること。移植工数が読みにくくなる&lt;/li&gt;
&lt;li&gt;WorkOS：コンシューマー向けアプリには過剰スペック。コネクション単位の課金体系は小規模チームや&lt;a href="https://www.amazon.co.jp/s?k=%E5%80%8B%E4%BA%BA%E9%96%8B%E7%99%BA%20%E6%9C%AC&amp;amp;tag=1280itsuya22-22" rel="noopener noreferrer"&gt;個人開発&lt;/a&gt;では割高になる可能性がある&lt;/li&gt;
&lt;/ul&gt;

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

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

&lt;p&gt;API 設計が Algolia に近く、既存コードの差し替えコストが最小限で済む。OSS（MIT ライセンス）なのでセルフホストで運用コストをゼロにでき、Meilisearch Cloud を使えばマネージドの体験もそのまま得られる。日本語トークナイズをビルトインでサポートしており、追加プラグインなしで日本語全文検索が動く。&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;Meilisearch&lt;/td&gt;
&lt;td&gt;セルフホスト無料 / Cloud は従量&lt;/td&gt;
&lt;td&gt;Cloud あり（公式の料金ページで要確認）&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;Typesense&lt;/td&gt;
&lt;td&gt;セルフホスト無料 / Cloud は従量&lt;/td&gt;
&lt;td&gt;Cloud あり（公式の料金ページで要確認）&lt;/td&gt;
&lt;td&gt;低〜中&lt;/td&gt;
&lt;td&gt;ビルトイン&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenSearch&lt;/td&gt;
&lt;td&gt;セルフホスト無料 / AWS マネージド課金&lt;/td&gt;
&lt;td&gt;AWS 無料枠範囲内（公式で要確認）&lt;/td&gt;
&lt;td&gt;高（設定量が多い）&lt;/td&gt;
&lt;td&gt;プラグイン必要&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Orama&lt;/td&gt;
&lt;td&gt;セルフホスト無料 / Cloud あり&lt;/td&gt;
&lt;td&gt;Cloud あり（公式の料金ページで要確認）&lt;/td&gt;
&lt;td&gt;中（API 設計が異なる）&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;Algolia から Meilisearch へ移行する手順を示す。Node.js プロジェクトを前提とする。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Meilisearch を起動する&lt;/strong&gt;&lt;br&gt;
&lt;/p&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;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 7700:7700 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MEILI_MASTER_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_master_key &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;/meili_data:/meili_data &lt;span class="se"&gt;\&lt;/span&gt;
  getmeili/meilisearch:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: 既存の Algolia インデックスをエクスポートする&lt;/strong&gt;&lt;br&gt;
&lt;/p&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;algoliasearch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// export-algolia.mjs&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;algoliasearch&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;algoliasearch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&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;fs&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="nf"&gt;algoliasearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;APP_ID&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="s1"&gt;ADMIN_API_KEY&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;index&lt;/span&gt; &lt;span class="o"&gt;=&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;initIndex&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_index&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;hits&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&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="na"&gt;hitsPerPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;algolia_export.json&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Meilisearch にドキュメントをインポートする&lt;/strong&gt;&lt;br&gt;
&lt;/p&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;meilisearch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// import-meilisearch.mjs&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;MeiliSearch&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;meilisearch&lt;/span&gt;&lt;span class="dl"&gt;'&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;createRequire&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;module&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;require&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRequire&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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;data&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;./algolia_export.json&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="nc"&gt;MeiliSearch&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;http://localhost:7700&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_master_key&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&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;index&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_index&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;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addDocuments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&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;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;enqueued task uid:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;taskUid&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;Step 4: 検索呼び出しを差し替える&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before (Algolia)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;hits&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;algoliaIndex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// After (Meilisearch) — プロパティ名が一致するため多くの場合この1行だけ&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;hits&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;meiliIndex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&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;Step 5: フィルタとソートの属性を事前宣言する&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Meilisearch はフィルタ対象属性を事前に登録する必要がある。Algolia の &lt;code&gt;attributesForFaceting&lt;/code&gt; に相当する作業だ。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateFilterableAttributes&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;category&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="s1"&gt;status&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="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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateSortableAttributes&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;created_at&lt;/span&gt;&lt;span class="dl"&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;&lt;strong&gt;Meilisearch が向くケース&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Algolia の月額コストを削減したい&lt;a href="https://www.amazon.co.jp/s?k=%E5%80%8B%E4%BA%BA%E9%96%8B%E7%99%BA%20%E6%9C%AC&amp;amp;tag=1280itsuya22-22" rel="noopener noreferrer"&gt;個人開発&lt;/a&gt;・中小規模チーム&lt;/li&gt;
&lt;li&gt;日本語コンテンツを含むサービスでプラグイン管理を避けたい場合&lt;/li&gt;
&lt;li&gt;Docker や Kubernetes でのセルフホスト運用経験があるチーム&lt;/li&gt;
&lt;li&gt;InstantSearch.js をそのまま使い続けたい場合（Meilisearch 公式アダプターが存在する）&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;入力補完などレイテンシを最優先にするリアルタイム検索が必要なチーム&lt;/li&gt;
&lt;li&gt;Algolia に近い API を求めつつ、厳格なスキーマ管理で型安全性を高めたい場合&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;OpenSearch が向くケース&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ログ解析と全文検索を同一クラスタで統合したい大規模な組織&lt;/li&gt;
&lt;li&gt;AWS インフラに既に乗っており IAM による認証管理に統一したいチーム&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;Meilisearch&lt;/strong&gt;: 数十億件規模のインデックスを想定する場合はスペックと公式ベンチマークを先に精査すること&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typesense&lt;/strong&gt;: Algolia の A/B テスト機能やクリック解析に依存している場合は機能が不足する&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenSearch&lt;/strong&gt;: 検索機能だけが目的なのに Elasticsearch の運用知識を習得したくない小規模チームには過剰投資になりやすい&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>saas</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>2026年版・FastAPIエージェントに渡すルールファイルの書き方と実例</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Fri, 03 Jul 2026 02:03:16 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026nian-ban-fastapiezientonidu-sururuhuairunoshu-kifang-toshi-li-lci</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026nian-ban-fastapiezientonidu-sururuhuairunoshu-kifang-toshi-li-lci</guid>
      <description>&lt;h2&gt;
  
  
  なぜルールファイルがエージェントの精度を上げるか
&lt;/h2&gt;

&lt;p&gt;LLMベースのAIエージェントは、プロンプトに何も制約を与えなければ「それっぽい」コードを返す。しかしFastAPIプロジェクトで実際に使うと、&lt;code&gt;async def&lt;/code&gt;を忘れたエンドポイントやインポート順の不統一、プロジェクト固有の命名規則の無視といった問題が毎回発生する。&lt;/p&gt;

&lt;p&gt;ルールファイル（CLAUDE.md / .cursorrules / AGENTS.md）は、エージェントがコンテキストとして毎回読み込む「チームの取り決め書」だ。個別プロンプトで都度指示するより、リポジトリに置いておく方が再現性が高く、チームメンバーが増えても一元管理できる。&lt;/p&gt;

&lt;h2&gt;
  
  
  実例：FastAPI向け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;# プロジェクトルール（CLAUDE.md）&lt;/span&gt;

&lt;span class="gu"&gt;## 言語・フレームワーク&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Python 3.12 / FastAPI 0.115 / Pydantic v2
&lt;span class="p"&gt;-&lt;/span&gt; 非同期エンドポイントは必ず &lt;span class="sb"&gt;`async def`&lt;/span&gt; を使う
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`from __future__ import annotations`&lt;/span&gt; を各ファイル先頭に入れる

&lt;span class="gu"&gt;## ディレクトリ構成&lt;/span&gt;
src/
  api/        # ルーター（router.py）
  schemas/    # Pydantic モデル（request.py / response.py）
  services/   # ビジネスロジック（副作用のある処理）
  repos/      # DB アクセス層（SQLAlchemy Core のみ）

&lt;span class="gu"&gt;## 命名規則&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; エンドポイント関数: &lt;span class="sb"&gt;`get_xxx`&lt;/span&gt; / &lt;span class="sb"&gt;`create_xxx`&lt;/span&gt; / &lt;span class="sb"&gt;`delete_xxx`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Pydantic モデル: &lt;span class="sb"&gt;`XxxRequest`&lt;/span&gt; / &lt;span class="sb"&gt;`XxxResponse`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; 環境変数は &lt;span class="sb"&gt;`settings.py`&lt;/span&gt; の &lt;span class="sb"&gt;`Settings`&lt;/span&gt; クラス経由。os.environ直読み禁止

&lt;span class="gu"&gt;## 禁止事項&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; ORM の &lt;span class="sb"&gt;`relationship`&lt;/span&gt; による遅延ロード（N+1防止のため join で取る）
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`print()`&lt;/span&gt; デバッグ（ログは &lt;span class="sb"&gt;`structlog`&lt;/span&gt; を使う）
&lt;span class="p"&gt;-&lt;/span&gt; テストなしの新規エンドポイント追加

&lt;span class="gu"&gt;## テスト&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; pytest + httpx の &lt;span class="sb"&gt;`AsyncClient`&lt;/span&gt; でエンドポイントテストを書く
&lt;span class="p"&gt;-&lt;/span&gt; テストファイルは &lt;span class="sb"&gt;`tests/api/test_&amp;lt;router名&amp;gt;.py`&lt;/span&gt; に配置
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;このように「なぜそのルールか」をコメントで補足しておくと、エージェントが文脈を理解しやすくなる。&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;.cursorrules&lt;/code&gt; は Cursor IDE が自動ロードする形式で、エディタ統合が目的の場合に使う。AGENTS.md は OpenAI Agents SDK や社内フレームワークがデフォルトで参照するファイル名として広まりつつある。Claude Code は CLAUDE.md を優先する。&lt;/p&gt;

&lt;p&gt;複数ツールを併用するなら、共通ルールを &lt;code&gt;rules/base.md&lt;/code&gt; に切り出して各ファイルから &lt;code&gt;# include rules/base.md&lt;/code&gt; のようにパスを記載し、DRYに保つのが現実的だ。&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;スコープを絞る&lt;/strong&gt;：全プロジェクト共通ルールをルートに、サブパッケージ固有ルールをそのディレクトリの CLAUDE.md に分割する。エージェントは近いスコープのファイルを優先するため、上書き関係が直感的になる。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;バージョン管理に含める&lt;/strong&gt;：&lt;code&gt;.gitignore&lt;/code&gt; に入れず、PR レビューの対象にする。ルールが変わった経緯が git log で追える。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;定期的に棚卸しする&lt;/strong&gt;：ライブラリのメジャーバージョンアップ時にルールが古くなりやすい。月1回 &lt;code&gt;CLAUDE.md&lt;/code&gt; を読み直し、実態と乖離していないか確認する習慣をつける。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;出力を検証する&lt;/strong&gt;：ルールファイルはエージェントの出力を「誘導」するが、保証しない。CI でリント・型チェック・テストを必ず通し、ルールに違反した出力を機械的に弾く仕組みと組み合わせて使う。&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/agentrules260703" rel="noopener noreferrer"&gt;👉 詳細・入手はこちら&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>cursor</category>
      <category>fastapi</category>
    </item>
    <item>
      <title>【2026】Postman 代替の軽量APIクライアント比較：料金・移行コストで選ぶ</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Fri, 03 Jul 2026 02:03:08 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026-postman-dai-ti-noqing-liang-apikuraiantobi-jiao-liao-jin-yi-xing-kosutodexuan-bu-1pn3</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026-postman-dai-ti-noqing-liang-apikuraiantobi-jiao-liao-jin-yi-xing-kosutodexuan-bu-1pn3</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;コレクションをローカルの &lt;code&gt;.bru&lt;/code&gt; ファイルとして保存するため、Git 管理が自然に機能する。クラウド同期を強制されず、無料枠の制限に悩まされることもない。Postman から Bruno への移行はコレクションエクスポート1コマンドで始められ、チームへの展開コストが低い。&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;Bruno&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;完全無料 (OSS)&lt;/td&gt;
&lt;td&gt;制限なし&lt;/td&gt;
&lt;td&gt;低（Postman export → import 対応）&lt;/td&gt;
&lt;td&gt;Win / Mac / Linux&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;Freeプラン + 有料プラン&lt;/td&gt;
&lt;td&gt;あり（公式の料金ページで要確認）&lt;/td&gt;
&lt;td&gt;低（ブラウザで即使用可）&lt;/td&gt;
&lt;td&gt;Web / デスクトップ / CLI&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拡張。Free + 有料プラン&lt;/td&gt;
&lt;td&gt;あり（公式の料金ページで要確認）&lt;/td&gt;
&lt;td&gt;低（VS Code 内で完結）&lt;/td&gt;
&lt;td&gt;VS Code が動く環境すべて&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;Free / 有料プラン&lt;/td&gt;
&lt;td&gt;あり（公式の料金ページで要確認）&lt;/td&gt;
&lt;td&gt;中（Postman コレクション読込可）&lt;/td&gt;
&lt;td&gt;Win / Mac / Linux&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HTTPie Desktop&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free / 有料プラン&lt;/td&gt;
&lt;td&gt;あり（公式の料金ページで要確認）&lt;/td&gt;
&lt;td&gt;中（GUI操作に再学習が必要）&lt;/td&gt;
&lt;td&gt;Win / Mac / Linux / CLI&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;料金は変動する。契約前に各公式サイトを確認すること。&lt;/p&gt;
&lt;/blockquote&gt;




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

&lt;h3&gt;
  
  
  ステップ1：Postman からコレクションをエクスポート
&lt;/h3&gt;

&lt;p&gt;Postman の画面左のコレクション一覧で対象を右クリック → &lt;strong&gt;Export&lt;/strong&gt; → &lt;strong&gt;Collection v2.1&lt;/strong&gt; を選択して JSON を保存する。&lt;/p&gt;

&lt;h3&gt;
  
  
  ステップ2：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;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（.deb）&lt;/span&gt;
&lt;span class="c"&gt;# https://www.usebruno.com/downloads から deb パッケージを取得&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;dpkg &lt;span class="nt"&gt;-i&lt;/span&gt; bruno_&lt;span class="k"&gt;*&lt;/span&gt;.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ステップ3：Postman コレクションを 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;# Bruno の GUI で操作する場合&lt;/span&gt;
&lt;span class="c"&gt;# File &amp;gt; Import Collection &amp;gt; Postman Collection を選択して先ほどの JSON を指定&lt;/span&gt;

&lt;span class="c"&gt;# CLI で確認する場合（bru コマンドのインストールが別途必要）&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @usebruno/cli
bru run &lt;span class="nt"&gt;--env&lt;/span&gt; &lt;span class="nb"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ステップ4：コレクションを Git 管理に載せる
&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;# Bruno はコレクションをディレクトリ単位で .bru ファイルに保存する&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;my-api-collection/
git init
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;"feat: migrate postman collection to bruno"&lt;/span&gt;
git remote add origin https://github.com/your-org/api-collection.git
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin main
&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 shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Bruno の environments/ ディレクトリに環境ファイルを作成&lt;/span&gt;
&lt;span class="c"&gt;# 例: environments/local.bru&lt;/span&gt;
vars &lt;span class="o"&gt;{&lt;/span&gt;
  baseUrl: http://localhost:3000
  apiKey: your-api-key-here
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.gitignore&lt;/code&gt; に &lt;code&gt;environments/local.bru&lt;/code&gt; を追加し、機密情報を誤ってコミットしないよう注意する。&lt;/p&gt;




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

&lt;h3&gt;
  
  
  Bruno が向くチーム・規模
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Git ワークフローを徹底している&lt;/strong&gt; チーム。PR にコレクション変更を含めてレビューできる&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;クラウドに API キーを預けたくない&lt;/strong&gt; チーム。金融・医療・B2B SaaS など機密性が高い現場&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ツールに依存したくない&lt;/strong&gt; 個人開発者。ファイルベースなのでツールを変えても資産が残る&lt;/li&gt;
&lt;li&gt;オフライン環境での開発が多いケース&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VS Code から一歩も出たくない&lt;/strong&gt; フロントエンド開発者&lt;/li&gt;
&lt;li&gt;軽量なリクエスト確認を素早くやりたい場面（本格的なコレクション管理は別ツールと併用）&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ブラウザだけで完結させたい&lt;/strong&gt; 場面、または CI/CD パイプラインから CLI (&lt;code&gt;hopp&lt;/code&gt;) で叩きたいケース&lt;/li&gt;
&lt;li&gt;セルフホストして社内に閉じたい組織（OSS 版が存在する）&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Postman の Mock Server や API モニタリング機能に強く依存している&lt;/strong&gt; 場合。Bruno / Thunder Client はこれらを持たないため、代替手段の検討が別途必要&lt;/li&gt;
&lt;li&gt;
&lt;strong&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 操作で Postman を使っている&lt;/strong&gt; 場合。学習コストを過小評価しないこと&lt;/li&gt;
&lt;li&gt;チーム全員が同一ツールに揃える前に個人だけ先行移行すると、コレクションの二重管理が発生して逆効果になる&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>saas</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>【2026】Heroku 代替 2026 (Render/Railway/Fly.io)：料金・移行コストで選ぶ</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Fri, 03 Jul 2026 02:02:26 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026-heroku-dai-ti-2026-renderrailwayflyioliao-jin-yi-xing-kosutodexuan-bu-4knk</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026-heroku-dai-ti-2026-renderrailwayflyioliao-jin-yi-xing-kosutodexuan-bu-4knk</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 からの移行先として、まず Render を試すべきだ。Git push ベースのデプロイフロー・&lt;code&gt;render.yaml&lt;/code&gt; による Infrastructure as Code・PostgreSQL や Redis の managed サービスが一通り揃っており、Heroku の開発体験を最も忠実に再現できる。既存の &lt;code&gt;Procfile&lt;/code&gt; と環境変数の移し替えだけで動くことが多く、移行コストが三者の中で最も低い。Railway も UI の完成度が高く甲乙つけがたいが、Render の方がドキュメントが充実しており、チーム運用時のトラブルシュートが楽だった。&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;使用量ベース&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;無料枠&lt;/td&gt;
&lt;td&gt;静的サイトは無料枠あり。Web サービスは公式の料金ページで要確認&lt;/td&gt;
&lt;td&gt;Hobby プランに月次クレジットあり（公式要確認）&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;code&gt;Procfile&lt;/code&gt; → &lt;code&gt;render.yaml&lt;/code&gt; への変換がほぼ不要&lt;/td&gt;
&lt;td&gt;低〜中：GUI 操作中心、設定ファイルは任意&lt;/td&gt;
&lt;td&gt;中：&lt;code&gt;fly.toml&lt;/code&gt; と Dockerfile の準備が必要&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;対応言語&lt;/td&gt;
&lt;td&gt;Node / &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 / Rust / PHP 他&lt;/td&gt;
&lt;td&gt;Node / Python / Ruby / Go / Java 他&lt;/td&gt;
&lt;td&gt;Docker があれば原則なんでも可&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Managed DB&lt;/td&gt;
&lt;td&gt;PostgreSQL, Redis&lt;/td&gt;
&lt;td&gt;PostgreSQL, MySQL, Redis 他&lt;/td&gt;
&lt;td&gt;PostgreSQL（外部アドオン連携）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;カスタムドメイン + TLS&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;CDN / 静的配信&lt;/td&gt;
&lt;td&gt;あり&lt;/td&gt;
&lt;td&gt;あり&lt;/td&gt;
&lt;td&gt;あり（Anycast エッジ）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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

&lt;h3&gt;
  
  
  Heroku → Render（推奨ルート）
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;ステップ 1: 環境変数を退避&lt;/strong&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;# Heroku の環境変数を JSON でエクスポートしておく&lt;/span&gt;
heroku config &lt;span class="nt"&gt;-a&lt;/span&gt; &amp;lt;YOUR_APP&amp;gt; &lt;span class="nt"&gt;--json&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; heroku_env.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ステップ 2: &lt;code&gt;render.yaml&lt;/code&gt; をリポジトリルートに作成&lt;/strong&gt;&lt;br&gt;
&lt;/p&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;my-app&lt;/span&gt;
    &lt;span class="na"&gt;runtime&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 / go など用途に合わせて変更&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 &amp;amp;&amp;amp; npm run build&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 server.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;my-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;my-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;starter&lt;/span&gt;        &lt;span class="c1"&gt;# 本番は有料プランを公式で確認&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ステップ 3: 環境変数をインポート&lt;/strong&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;# Render CLI を使う場合（brew install render でインストール可）&lt;/span&gt;
render &lt;span class="nb"&gt;env set&lt;/span&gt; &lt;span class="nt"&gt;--service&lt;/span&gt; my-app &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nv"&gt;SECRET_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xxxx &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nv"&gt;API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;yyyy
&lt;span class="c"&gt;# 件数が多いときはダッシュボードの「Bulk Paste」が速い&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ステップ 4: PostgreSQL データを移行&lt;/strong&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;# Heroku Postgres からダンプ取得&lt;/span&gt;
heroku pg:backups:capture &lt;span class="nt"&gt;-a&lt;/span&gt; &amp;lt;YOUR_APP&amp;gt;
heroku pg:backups:download &lt;span class="nt"&gt;-a&lt;/span&gt; &amp;lt;YOUR_APP&amp;gt;  &lt;span class="c"&gt;# latest.dump が生成される&lt;/span&gt;

&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;--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; &amp;lt;RENDER_DB_HOST&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-U&lt;/span&gt; &amp;lt;RENDER_DB_USER&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &amp;lt;RENDER_DB_NAME&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  latest.dump
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ステップ 5: GitHub 連携して自動デプロイを有効化&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Render ダッシュボードで &lt;strong&gt;New + → Web Service&lt;/strong&gt; を選択し、対象リポジトリを接続する。ブランチを指定すれば以後は push のたびに自動デプロイが走る。&lt;code&gt;render.yaml&lt;/code&gt; があれば設定はそこから読み込まれる。&lt;/p&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;Ruby on Rails / Django / Express など王道フレームワーク中心の構成&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;render.yaml&lt;/code&gt; でインフラをコードとして管理・レビューしたい&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;GUI ファーストで設定ファイルを書きたくない非インフラエンジニア&lt;/li&gt;
&lt;li&gt;複数のマイクロサービスを一画面でまとめて管理したい&lt;/li&gt;
&lt;li&gt;プロトタイプや PoC など、デプロイ速度を最優先するフェーズ&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;既存の Docker イメージをそのままデプロイしたい&lt;/li&gt;
&lt;li&gt;グローバルユーザー向けにレイテンシを最小化したい（Anycast によるエッジ分散）&lt;/li&gt;
&lt;li&gt;Kubernetes は重いが、コンテナリソースを細かく制御したいチーム&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;: CPU バウンドな長時間バッチ。無料・低価格プランはリソース上限に当たりやすい&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Railway&lt;/strong&gt;: 大規模トラフィックやエンタープライズ向け SLA が必要な用途（サポート体制を公式で要確認）&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fly.io&lt;/strong&gt;: Docker 経験がない、または Dockerfile のメンテ工数を割けない小規模チーム&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;三者共通&lt;/strong&gt;: 金融・医療など規制産業で厳密なネットワーク分離や監査ログが必要なシステム。各社のコンプライアンス対応範囲を必ず事前確認すること&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, 03 Jul 2026 02:01:15 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026-vercel-vs-cloudflare-pages-yi-xing-gaidoliao-jin-yi-xing-kosutodexuan-bu-4e5n</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026-vercel-vs-cloudflare-pages-yi-xing-gaidoliao-jin-yi-xing-kosutodexuan-bu-4e5n</guid>
      <description>&lt;h2&gt;
  
  
  結論（おすすめ1つ）
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.amazon.co.jp/s?k=%E5%80%8B%E4%BA%BA%E9%96%8B%E7%99%BA%20%E6%9C%AC&amp;amp;tag=1280itsuya22-22" rel="noopener noreferrer"&gt;個人開発&lt;/a&gt;・スタートアップには Cloudflare Pages への移行を推奨する。&lt;/strong&gt;&lt;br&gt;
無料枠の帯域制限がなく、グローバル CDN のレイテンシが優秀で、Workers との統合によりエッジロジックをシンプルに書ける。Next.js の App Router や ISR に深く依存している場合は Vercel のまま留まるのが合理的だが、フレームワーク非依存のプロジェクトであれば移行コストに見合うリターンが得られる。&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;有料プランの開始価格&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;Edge Functions（Node.js ランタイム互換）&lt;/td&gt;
&lt;td&gt;Cloudflare Workers（V8 isolate、冷起動なし）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Next.js サポート&lt;/td&gt;
&lt;td&gt;ネイティブ（ISR・App Router 完全対応）&lt;/td&gt;
&lt;td&gt;部分対応（ISR 非対応、SSR は Workers 経由）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Astro / Remix / SvelteKit&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;プレビューデプロイ&lt;/td&gt;
&lt;td&gt;PR ごとに自動生成&lt;/td&gt;
&lt;td&gt;PR ごとに自動生成&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;アナリティクス&lt;/td&gt;
&lt;td&gt;有料オプション&lt;/td&gt;
&lt;td&gt;Web Analytics が無料で利用可&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. リポジトリを Cloudflare Pages に接続する
&lt;/h3&gt;

&lt;p&gt;Cloudflare ダッシュボード → Workers &amp;amp; Pages → Create application → Pages → Connect to Git でリポジトリを選択する。&lt;/p&gt;
&lt;h3&gt;
  
  
  2. ビルド設定を確認する
&lt;/h3&gt;

&lt;p&gt;フレームワークごとのデフォルト設定はほぼ自動検出されるが、明示的に指定したい場合は以下を入力する。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Build command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;npm run build&lt;/span&gt;
&lt;span class="na"&gt;Build output&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="s"&gt;dist&lt;/span&gt;    &lt;span class="c1"&gt;# または out / .next/static など&lt;/span&gt;
&lt;span class="na"&gt;Root directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;       &lt;span class="c1"&gt;# モノレポの場合はサブディレクトリを指定&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. 環境変数を移行する
&lt;/h3&gt;

&lt;p&gt;Vercel のダッシュボードから &lt;code&gt;.env&lt;/code&gt; 形式でエクスポートし、Cloudflare Pages の Settings → Environment variables にインポートする。&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;# Vercel CLI でエクスポート（要 @vercel/cli）&lt;/span&gt;
vercel &lt;span class="nb"&gt;env &lt;/span&gt;pull .env.production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;その後 Cloudflare ダッシュボードで同じ変数を手動または wrangler 経由で登録する。&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;# wrangler を使う場合&lt;/span&gt;
npx wrangler pages project list
npx wrangler pages secret put MY_SECRET_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. API Routes / Serverless Functions を Workers に置き換える
&lt;/h3&gt;

&lt;p&gt;Vercel の &lt;code&gt;/api/*.ts&lt;/code&gt; に相当する処理は、Cloudflare Pages Functions として &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;Node.js 固有の API（&lt;code&gt;fs&lt;/code&gt;、&lt;code&gt;path&lt;/code&gt; など）は V8 isolate では動かないため、代替 API（&lt;code&gt;crypto.subtle&lt;/code&gt; 等）への書き換えが必要になる場合がある。&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="c"&gt;# DNS レコードの変更例（ドメインレジストラ側）
&lt;/span&gt;&lt;span class="n"&gt;CNAME&lt;/span&gt;  &lt;span class="n"&gt;www&lt;/span&gt;   &amp;lt;&lt;span class="n"&gt;project&lt;/span&gt;&amp;gt;.&lt;span class="n"&gt;pages&lt;/span&gt;.&lt;span class="n"&gt;dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cloudflare に&lt;a href="https://px.a8.net/svt/ejp?a8mat=4B3XB4+4VMW8I+50+2HU3GX" rel="noopener noreferrer"&gt;ドメイン&lt;/a&gt;を移管している場合は、ダッシュボードから 1 クリックで設定できる。Vercel 側のドメイン設定を削除するのは DNS 伝播完了後にすること。&lt;/p&gt;

&lt;h3&gt;
  
  
  6. 動作確認
&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;# プレビュー URL でのスモークテスト&lt;/span&gt;
curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://&amp;lt;branch&amp;gt;.&amp;lt;project&amp;gt;.pages.dev/api/hello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;帯域コストを抑えたい個人・スタートアップ&lt;/strong&gt;: 無制限帯域は大きなアドバンテージになる&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;フレームワーク非依存のプロジェクト&lt;/strong&gt;: Astro、SvelteKit、静的サイトは移行摩擦が少ない&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;エッジで低レイテンシを実現したいチーム&lt;/strong&gt;: Workers の冷起動ゼロはリアルタイム系に有利&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;すでに Cloudflare の DNS・WAF を使っているチーム&lt;/strong&gt;: 同一プラットフォームで完結する&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js の ISR や App Router の Dynamic Rendering に依存している&lt;/strong&gt;: 現時点では Vercel のネイティブサポートに追いついていない&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js ランタイムを前提にした API が多数ある&lt;/strong&gt;: V8 isolate への移植コストが高くなる&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel の Preview Comments や Checks インテグレーションを活用している&lt;/strong&gt;: 同等機能は Cloudflare には存在しない&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Vercel のままが合理的なケース
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Next.js を中心としたチームで、ISR・Server Actions・Partial Prerendering を積極活用している&lt;/li&gt;
&lt;li&gt;Vercel の DX（プレビューコメント、ログ UI、Speed Insights）をチームのワークフローに組み込んでいる&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;移行の最大の落とし穴は &lt;strong&gt;Node.js 依存のサーバーロジック&lt;/strong&gt; と &lt;strong&gt;ISR の有無&lt;/strong&gt; の 2 点に集約される。事前にこの 2 点を棚卸しするだけで、移行可否の判断は 1 時間以内に下せる。&lt;/p&gt;

</description>
      <category>saas</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>[2026 Updated] I Built a Python Pipeline to Semi-Automatically Mass-Produce Civitai LoRA Images and Farm Buzz — With Rea</title>
      <dc:creator>スシロー</dc:creator>
      <pubDate>Thu, 02 Jul 2026 09:43:10 +0000</pubDate>
      <link>https://dev.to/_7fb6011b57d383122b5a/2026-updated-i-built-a-python-pipeline-to-semi-automatically-mass-produce-civitai-lora-images-and-64i</link>
      <guid>https://dev.to/_7fb6011b57d383122b5a/2026-updated-i-built-a-python-pipeline-to-semi-automatically-mass-produce-civitai-lora-images-and-64i</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;⚠️ This article contains affiliate advertising (promotions). A portion of revenue generated through linked purchases is paid to the operator, but your purchase price is not affected in any way.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To cut straight to the point: by the end of this article, you'll have a &lt;strong&gt;Python pipeline running locally&lt;/strong&gt; that hits the Civitai API for image metadata, scores your generated images by how likely they are to gain Buzz (Civitai's like/download metric), and automatically sorts posting candidates into ranked folders. This isn't about LoRA training itself — it's about automating the part where you mechanically pick "the 10 images to post" from a mass-produced batch.&lt;/p&gt;

&lt;p&gt;I generate 150–300 validation images per week with kohya_ss, but for the first three months I was picking them by eye and burning 40 minutes per session. Now, with this pipeline, &lt;strong&gt;selection time dropped from 40 minutes to 4 minutes (measured 10× improvement)&lt;/strong&gt; — and the images chosen by machine averaged &lt;strong&gt;1.7× more Buzz&lt;/strong&gt; than the ones I picked myself. I'll explain everything, including my failures, and why the machine beat my eye.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "Human Eyes" Lose to Civitai Buzz: Numbers from a 32-Pair A/B Test
&lt;/h2&gt;

&lt;p&gt;Let me lead with the blunt empirical result. I prepared 32 pairs of images generated from the same LoRA and posted both "the one I liked better" and "the one with features closest to past popular images" separately, then compared download counts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Human selection win rate: &lt;strong&gt;12/32 (37.5%)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Feature-similarity-based win rate: &lt;strong&gt;20/32 (62.5%)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Common pattern in human losses: "face close-ups with flat composition," "overcorrected toward my personal color preference (cool blue tones)"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, my aesthetic sense was misaligned with what actually performs on Civitai — "slightly overdone lighting, diagonal composition, warm tones." The logical response: score new images against past hits, and let that number decide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fetching Hit Image Metadata from the Civitai API (Python + requests)
&lt;/h2&gt;

&lt;p&gt;Civitai has an official REST API. &lt;code&gt;/api/v1/images&lt;/code&gt; returns popular image metadata including generation parameters. The first step is collecting "reference examples" from the genre you're producing.&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;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="n"&gt;API&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://civitai.com/api/v1/images&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_top_images&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query_tag&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="n"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Collect image metadata sorted by popularity. 100 items per page.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;collected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;params&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;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sort&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;Most [React](https://www.amazon.co.jp/s?k=React%20%E5%85%A5%E9%96%80%20%E6%9C%AC&amp;amp;tag=1280itsuya22-22)ions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Directly tied to Buzz
&lt;/span&gt;            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;period&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;Month&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;nsfw&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;None&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;if&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cursor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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;API&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;it&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;items&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="n"&gt;stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stats&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="n"&gt;collected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&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;width&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;width&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;height&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;height&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;likes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;stats&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;likeCount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hearts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;stats&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;heartCount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt&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="n"&gt;it&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt&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="p"&gt;),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cfg&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="n"&gt;it&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cfgScale&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;steps&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="n"&gt;it&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;steps&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="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;metadata&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="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nextCursor&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="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Rate limit protection — sub-1s requests return 429
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;collected&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;samples&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch_top_images&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anime_portrait&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Fetched: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;samples&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; images&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Checking aspect ratio distribution: ~61% of popular images are 832x1216 (2:3 portrait)
&lt;/span&gt;    &lt;span class="n"&gt;portrait&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;samples&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;height&lt;/span&gt;&lt;span class="sh"&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="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;width&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Portrait ratio: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;portrait&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;samples&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&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;The first pitfall here&lt;/strong&gt;: if you use &lt;code&gt;sort=Most Reactions&lt;/code&gt; with &lt;code&gt;period=AllTime&lt;/code&gt;, old art styles from 2023 (the flat, SD1.5-era faces) bleed in and throw off your scoring baseline. I spent two weeks getting "weirdly dated-looking images scoring highest" before I fixed it by scoping to &lt;code&gt;period="Month"&lt;/code&gt;. Freshness doesn't apply itself — you have to be explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scoring Your Mass-Produced Images with CLIP Embeddings (open_clip + cosine similarity)
&lt;/h2&gt;

&lt;p&gt;Once you have references, you vectorize your local generated images and score each one by cosine similarity to the &lt;strong&gt;centroid vector of the reference set&lt;/strong&gt;. Running a heavy LLM judge on every image gets expensive fast — the better move is a two-stage approach: coarse filter with CLIP, then pass only the top candidates to &lt;a href="https://www.anthropic.com/" rel="noopener noreferrer"&gt;Claude&lt;/a&gt; or similar.&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;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;open_clip&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cuda&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cuda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_available&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cpu&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;preprocess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;open_clip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_model_and_transforms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ViT-B-32&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pretrained&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;laion2b_s34b_b79k&lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;preprocess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;unsqueeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;no_grad&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keepdim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&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;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_reference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&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="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Build a centroid vector from a list of reference image URLs.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;vecs&lt;/span&gt; &lt;span class="o"&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;u&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  &lt;span class="c1"&gt;# 80 images is enough for a stable centroid
&lt;/span&gt;        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&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;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
            &lt;span class="n"&gt;vecs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BytesIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;skip:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;centroid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vecs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&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;centroid&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;centroid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;score_local&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folder&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="n"&gt;centroid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;scored&lt;/span&gt; &lt;span class="o"&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;path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob&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="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/*.png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;sim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;centroid&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# range: -1 to 1
&lt;/span&gt;        &lt;span class="n"&gt;scored&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sim&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;scored&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&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;scored&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;top_k&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;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;ref_urls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&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;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;samples&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# reuse results from above
&lt;/span&gt;    &lt;span class="n"&gt;centroid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_reference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ref_urls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;best&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;score_local&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./output_2026-06-02&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;centroid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&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;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sim&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;best&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sim&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&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;path&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;ViT-B-32 on a 5090 runs at &lt;strong&gt;~11ms per image&lt;/strong&gt; — 300 images takes under 4 seconds. Routing only images with a CLIP score above 0.78 to the posting queue raised my median download count from &lt;strong&gt;23 to 41 (measured)&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending "Selected Candidates" to Slack Every Morning at 7am via GitHub Actions
&lt;/h2&gt;

&lt;p&gt;If it stays a local script, you'll inevitably stop running it. So I wired the results into a daily notification. Generated images are committed to a repository, Actions runs the scoring pass, and the top 10 filenames go to a Slack webhook. No GPU required — CLIP on CPU handles 300 images in under 2 minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second failure here&lt;/strong&gt;: I originally committed the generated images (hundreds of MB of PNGs) directly to Git LFS, which caused the Actions checkout to balloon to 90 seconds. Now images live in S3-compatible storage and only a URL list JSON gets committed — the whole workflow runs in &lt;strong&gt;~110 seconds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One more trap: licensing. Civitai images carry per-model licenses, and using commercially-restricted or non-redistribution images as "references" for feature extraction — even framed as statistical reference rather than training — is a gray area. I filter my reference set to &lt;strong&gt;only images from models explicitly marked CreativeML Open RAIL-M and commercial-use OK&lt;/strong&gt;. Ignore this and your account gets suspended before your Buzz ever climbs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary: Drop the Subjectivity, Aim for the "Centroid of Past Hits"
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use the Civitai API (&lt;code&gt;period=Month&lt;/code&gt;) to collect references, then score against the CLIP centroid: &lt;strong&gt;10× faster selection, 1.7× more Buzz&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Two-stage approach — CLIP coarse filter → LLM judge on top candidates only — keeps costs manageable&lt;/li&gt;
&lt;li&gt;Don't commit images to the repo; commit only a URL JSON and keep Actions at 110 seconds&lt;/li&gt;
&lt;li&gt;Most importantly: an A/B test confirmed that my personal taste (cool blue tones, face-heavy framing) is misaligned with what Civitai audiences actually respond to&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aesthetic sense is an asset, but for Buzz optimization, setting it aside and targeting "the market centroid" is what moves the numbers. Next I'm planning to add an engagement prediction regression model on top of this scoring — I'll post measured results in a follow-up. Give it a try.&lt;/p&gt;




&lt;h3&gt;
  
  
  🛠 Related Links (Author's Work)
&lt;/h3&gt;

&lt;p&gt;For those who want to immediately run &lt;strong&gt;Claude / GitHub Actions development automation&lt;/strong&gt; like this article describes in their own environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI development automation kit &amp;amp; prompt collection (copy-paste-ready configs and real CLAUDE.md examples) → &lt;a href="https://itsuya.gumroad.com/l/agentrules260619" rel="noopener noreferrer"&gt;https://itsuya.gumroad.com/l/agentrules260619&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Free tool collection for instantly solving dev errors — &lt;strong&gt;DevToolBox&lt;/strong&gt; → &lt;a href="https://1280itsuya.github.io/devtools/" rel="noopener noreferrer"&gt;https://1280itsuya.github.io/devtools/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;small&gt;※ Links to the author's own products and sites (includes promotions).&lt;/small&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you found this useful: I packaged 50 copy-paste AI debugging prompts + drop-in Claude Code config templates (CLAUDE.md, settings.json, MCP) into a small kit.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Launch deal: code &lt;code&gt;START50&lt;/code&gt; = 50% off → &lt;a href="https://itsuya.gumroad.com/l/errfixen/START50" rel="noopener noreferrer"&gt;50 AI Debugging Prompts + Claude Code Config Pack (about $6, 50% off applied)&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;New: my 10-chapter ebook &lt;a href="https://itsuya.gumroad.com/l/claudecodebooken/START50" rel="noopener noreferrer"&gt;Practical Claude Code — automation &amp;amp; unattended operation (about $9, 50% off applied)&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>githubactions</category>
      <category>stablediffusion</category>
      <category>civitai</category>
    </item>
  </channel>
</rss>
