ai-saas-mvp-kinde

Page content

了解。そのスタックは「軽量・低コスト・高速MVP」にかなり良い構成です。ただし最初に一つだけ現実的な指摘をしておくと、Kinde + Supabase + Stripe + Geminiを“全部同時に完璧統合”しようとすると確実に詰まります
なのでMVPは 段階的に動かす(Auth → DB → AI → 課金) が正解です。

以下に「コピペで進められるレベル」で、CLI中心の完全手順を書きます。


全体構成

Frontend: Astro (Cloudflare Pages)
Auth: Kinde
DB: Supabase (RLS)
Billing: Stripe
AI: Gemini (Google AI Studio)
Backend: Cloudflare Workers

0. 事前準備(アカウント)

作成しておくもの:

  • Cloudflare

  • Kinde

  • Supabase

  • Stripe

  • Google AI Studio(Gemini)


1. プロジェクト作成(Astro + Cloudflare)

CLI

npm create astro@latest ai-saas-mvp-kinde
cd ai-saas-mvp-kinde

# テンプレ
# → minimal
# → TypeScript YES

npm install

Cloudflare用

npm install -D wrangler
npx wrangler login

2. Kinde(認証)

Kinde設定

  • Application作成

  • Redirect URL:

http://localhost:4321/api/auth/kinde_callback

SDKインストール

×npm install @kinde-oss/kinde-auth-node

npm install @kinde-oss/kinde-auth-pkce-js

環境変数

.env

KINDE_CLIENT_ID=xxx
KINDE_CLIENT_SECRET=xxx
KINDE_ISSUER_URL=https://xxx.kinde.com
KINDE_SITE_URL=http://localhost:4321
KINDE_REDIRECT_URL=http://localhost:4321/api/auth/kinde_callback

ログインAPI(Astro)

src/pages/api/login.ts

import { handleAuth } from "@kinde-oss/kinde-auth-node";

export const GET = handleAuth();

3. Supabase(DB + RLS)

CLI

npm install @supabase/supabase-js

環境変数

PUBLIC_SUPABASE_URL=xxx
PUBLIC_SUPABASE_ANON_KEY=xxx
SUPABASE_SERVICE_ROLE_KEY=xxx

テーブル作成(SQL)

create table users (
  id uuid primary key,
  email text
);

create table leads (
  id uuid default gen_random_uuid() primary key,
  user_id uuid,
  company text,
  problem text,
  created_at timestamp default now()
);

RLS

alter table leads enable row level security;

create policy "Users can access own leads"
on leads
for all
using (auth.uid() = user_id);

4. Gemini(AI)

APIキー取得

→ Google AI Studio

インストール

npm install @google/generative-ai

AI API(Cloudflare Workers)

src/pages/api/generate.ts

import { GoogleGenerativeAI } from "@google/generative-ai";

export async function POST({ request }) {
  const { company, problem } = await request.json();

  const genAI = new GoogleGenerativeAI(import.meta.env.GEMINI_API_KEY);
  const model = genAI.getGenerativeModel({ model: "gemini-pro" });

  const prompt = `
You are a BDR expert.
Write a cold email.

Company: ${company}
Problem: ${problem}
`;

  const result = await model.generateContent(prompt);
  const text = result.response.text();

  return new Response(JSON.stringify({ text }));
}

5. Stripe(課金)

CLI

npm install stripe
stripe login

商品作成

stripe products create --name="AI Sales Tool"
stripe prices create \
  --unit-amount=2000 \
  --currency=jpy \
  --recurring[interval]=month \
  --product=prod_xxx

Checkout API

src/pages/api/checkout.ts

import Stripe from "stripe";

const stripe = new Stripe(import.meta.env.STRIPE_SECRET_KEY);

export async function POST() {
  const session = await stripe.checkout.sessions.create({
    payment_method_types: ["card"],
    mode: "subscription",
    line_items: [
      {
        price: "price_xxx",
        quantity: 1,
      },
    ],
    success_url: "http://localhost:4321/success",
    cancel_url: "http://localhost:4321/cancel",
  });

  return new Response(JSON.stringify({ url: session.url }));
}

6. UI(Astro)

src/pages/index.astro

---
---

<form id="form">
  <input name="company" placeholder="Company" />
  <input name="problem" placeholder="Problem" />
  <button type="submit">Generate</button>
</form>

<pre id="result"></pre>

<script>
document.getElementById("form").onsubmit = async (e) => {
  e.preventDefault();

  const form = new FormData(e.target);

  const res = await fetch("/api/generate", {
    method: "POST",
    body: JSON.stringify({
      company: form.get("company"),
      problem: form.get("problem"),
    }),
  });

  const data = await res.json();
  document.getElementById("result").innerText = data.text;
};
</script>

7. Cloudflare Deploy

npm run build
npx wrangler pages deploy dist

8. MVP完成条件(重要)

ここを満たせば“勝ち筋あり”:

  • ログインできる(Kinde)

  • データ保存できる(Supabase)

  • AI生成できる(Gemini)

  • 課金できる(Stripe)


9. 次にやるべき(超重要)

MVP完成後すぐやる:

  1. リード保存 → 自動メール送信(Resend)

  2. LinkedInスクレイピング or Apollo連携

  3. 返信自動化(AIエージェント)

  4. RLS強化(B2Bマルチテナント)


まとめ(本質)

この構成の強み:

  • Cloudflare → 無料 & 高速

  • Kinde → Auth最速

  • Supabase → DB + RLS

  • Gemini → 低コストAI

  • Stripe → 収益化即可能


いい質問。ここがグチャると確実に詰むので、1ファイルで整理しておくのが正解です。
そのままコピペできる形で「用途別に整理済み」の .env を出します。


.env 完全版(コピペOK)

########################################
# 🌐 App Base
########################################
PUBLIC_APP_URL=http://localhost:4321

########################################
# 🔐 Kinde (Auth)
########################################
KINDE_CLIENT_ID=your_kinde_client_id
KINDE_CLIENT_SECRET=your_kinde_client_secret
KINDE_ISSUER_URL=https://your-domain.kinde.com

KINDE_SITE_URL=http://localhost:4321
KINDE_REDIRECT_URL=http://localhost:4321/api/auth/kinde_callback
KINDE_LOGOUT_REDIRECT_URL=http://localhost:4321

########################################
# 🗄 Supabase (DB)
########################################
PUBLIC_SUPABASE_URL=https://your-project.supabase.co
PUBLIC_SUPABASE_ANON_KEY=your_anon_key

# ⚠️ サーバー専用(絶対にフロントに出さない)
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key

########################################
# 🤖 Gemini (AI)
########################################
GEMINI_API_KEY=your_gemini_api_key

########################################
# 💳 Stripe (Billing)
########################################
# 公開キー(フロントOK)
PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_xxx

# 秘密キー(サーバーのみ)
STRIPE_SECRET_KEY=sk_test_xxx

# 商品・価格ID
STRIPE_PRICE_ID=price_xxx

# Webhook(後で使う)
STRIPE_WEBHOOK_SECRET=whsec_xxx

########################################
# ☁️ Cloudflare (Deploy)
########################################
CLOUDFLARE_ACCOUNT_ID=your_account_id
CLOUDFLARE_API_TOKEN=your_api_token

########################################
# ✉️ Optional(後で使う)
########################################
RESEND_API_KEY=your_resend_key

⚠️ 超重要ポイント(ここミスる人多い)

PUBLIC_ の意味

  • PUBLIC_ → フロントで使える

  • それ以外 → 絶対にサーバー専用

👉 例

PUBLIC_SUPABASE_ANON_KEY → OK
SUPABASE_SERVICE_ROLE_KEY → 絶対に隠す

② Stripeの罠

  • pk_ → フロント

  • sk_ → サーバー

逆にすると即バグ or セキュリティ事故


③ KindeのURLミス

これが一番多い:

KINDE_REDIRECT_URL=http://localhost:4321/api/auth/kinde_callback

👉 Kindeダッシュボード側と完全一致必須


④ Cloudflareにデプロイ時

.envは使われないので👇に設定:

wrangler secret put GEMINI_API_KEY
wrangler secret put STRIPE_SECRET_KEY

🔥 本番用(重要)

本番ではこう変える:

PUBLIC_APP_URL=https://yourdomain.com
KINDE_SITE_URL=https://yourdomain.com
KINDE_REDIRECT_URL=https://yourdomain.com/api/auth/kinde_callback

🚀 まとめ

この .env が揃えば:

  • 認証 → Kinde

  • DB → Supabase

  • AI → Gemini

  • 課金 → Stripe

👉 全部つながる状態になる


必要なら次は👇いける:

  • 「環境変数のエラー診断チェックリスト」

  • 「本番デプロイ完全手順(Cloudflare + Kinde + Stripe)」

  • 「セキュア設計(漏洩防止)」

どこまで詰める?