mcpField
S
saas-architect

saas-architect

github.com/sitechfromgeorgia開発62 回インストール
リポジトリ

saas-architect について

saas-architect は、Next.js 15 と Supabase で SaaS を設計する個人開発者向けの計画スキルです。データベース、認証、サブスクリプション、機能、安全性、開発計画を含む設計文書を作成します。

主な機能

  1. 01SaaS の製品と料金設計
  2. 02PostgreSQL スキーマと RLS の計画
  3. 03Next.js のファイル構成生成
  4. 04認証と請求フローの計画
  5. 05機能分解と開発ロードマップ
  6. 06セキュリティとデプロイのチェックリスト

活用シーン

  1. 01新しいサブスクリプション型 SaaS の計画
  2. 02マルチテナント組織とロールの設計
  3. 03既存 SaaS への機能追加
  4. 04開発とリリースのロードマップ作成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/sitechfromgeorgia/georgian-distribution-system --skill saas-architect

インストール後、Claude Code で/saas-architectを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
RLS_PATTERNS.md
STRIPE_PATTERNS.md
scripts/
validate-schema.js

詳細

SaaS アーキテクト - Next.js + Supabase エディション

目的

このスキルは、SaaS のアイデアを Next.js 15 + Supabase スタックに最適化された実行可能な技術アーキテクチャへと変換します。サブスクリプション型プロダクトを開発するソロ開発者に向けて、データベース設計、認証フロー、サブスクリプションのロジック、ファイル構成、現実的な開発スケジュールを網羅した包括的な計画を提供します。

基本理念

1. サブスクリプションを最優先したアーキテクチャ
  • 初日から継続的な収益を前提に設計する
  • 複数の料金プランを計画する
  • アップグレード/ダウングレードのフローを早期に構築する
  • トライアル期間と猶予期間を検討する
2. デフォルトでマルチテナント対応
  • Row Level Security(RLS)は必須
  • 組織/チーム構成を組み込む
  • ユーザーの役割と権限を最初から設定する
  • データの分離は絶対条件
3. Next.js 15 + Supabase に最適化
  • データ取得には Server Components を使用する
  • 更新処理には Server Actions を活用する
  • Supabase の組み込み機能(Auth、Storage、Realtime)を利用する
  • カスタムバックエンドコードを最小限に抑える
4. 初日から本番環境に対応
  • セキュリティを事前に考慮する
  • スケーラビリティのパターンを組み込む
  • モニタリングとエラートラッキングを計画する
  • デプロイ戦略を定める

このスキルの仕組み

フェーズ 1:SaaS プロダクトの定義
1.1 中核となる価値提案
**Product Name:** [Name]
**One-Line Pitch:** [What it does in one sentence]
**Target Market:** [Who pays for this]
**Primary Use Case:** [Main problem solved]
**Success Metric:** [How you measure value]
1.2 収益モデル
**Pricing Strategy:** [Freemium / Trial / Pay-to-start]
**Tiers:** [How many pricing tiers]
**Key Differentiators:** [What makes higher tiers worth it]
**Billing Cycle:** [Monthly / Annual / Both]

例(プロジェクト管理 SaaS):

**Product Name:** TaskFlow
**One-Line Pitch:** Project management for distributed teams with AI-powered task prioritization
**Target Market:** Remote teams, 10-50 employees, tech companies
**Primary Use Case:** Coordinate async work across timezones
**Success Metric:** Teams complete 30% more tasks on time

**Pricing Strategy:** Freemium with 14-day trial on paid plans
**Tiers:** 
  - Free: 1 project, 5 users, basic features
  - Pro ($29/mo): Unlimited projects, 25 users, AI features
  - Enterprise ($99/mo): Unlimited users, advanced integrations, priority support
**Key Differentiators:** 
  - Pro: AI task prioritization, integrations
  - Enterprise: SSO, custom workflows, dedicated support
**Billing Cycle:** Monthly + Annual (2 months free)
フェーズ 2:技術アーキテクチャの計画
2.1 データベーススキーマ設計

このスキルは、RLS ポリシーを含む完全な PostgreSQL スキーマを生成します。

すべての SaaS に必要な基本テーブル:

-- ============================================
-- USERS & AUTHENTICATION
-- ============================================
-- Note: Supabase Auth handles auth.users table
-- We extend it with profiles

CREATE TABLE profiles (
  id UUID REFERENCES auth.users PRIMARY KEY,
  email TEXT NOT NULL,
  full_name TEXT,
  avatar_url TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- RLS Policies
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users can view own profile"
  ON profiles FOR SELECT
  USING (auth.uid() = id);

CREATE POLICY "Users can update own profile"
  ON profiles FOR UPDATE
  USING (auth.uid() = id);

-- ============================================
-- ORGANIZATIONS (Multi-Tenant Core)
-- ============================================
CREATE TABLE organizations (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  name TEXT NOT NULL,
  slug TEXT UNIQUE NOT NULL,
  logo_url TEXT,
  subscription_tier TEXT DEFAULT 'free',
  subscription_status TEXT DEFAULT 'active',
  trial_ends_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

ALTER TABLE organizations ENABLE ROW LEVEL SECURITY;

-- ============================================
-- ORGANIZATION MEMBERS (Team Management)
-- ============================================
CREATE TYPE member_role AS ENUM ('owner', 'admin', 'member');

CREATE TABLE organization_members (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
  user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
  role member_role DEFAULT 'member',
  invited_by UUID REFERENCES auth.users(id),
  joined_at TIMESTAMPTZ DEFAULT NOW(),
  UNIQUE(organization_id, user_id)
);

ALTER TABLE organization_members ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Members can view own org members"
  ON organization_members FOR SELECT
  USING (
    organization_id IN (
      SELECT organization_id FROM organization_members 
      WHERE user_id = auth.uid()
    )
  );

-- ============================================
-- STRIPE INTEGRATION (Subscriptions)
-- ============================================
CREATE TABLE customers (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
  stripe_customer_id TEXT UNIQUE,
  email TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE products (
  id TEXT PRIMARY KEY, -- Stripe product ID
  active BOOLEAN DEFAULT true,
  name TEXT NOT NULL,
  description TEXT,
  image TEXT,
  metadata JSONB,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE prices (
  id TEXT PRIMARY KEY, -- Stripe price ID
  product_id TEXT REFERENCES products(id),
  active BOOLEAN DEFAULT true,
  currency TEXT DEFAULT 'usd',
  type TEXT CHECK (type IN ('one_time', 'recurring')),
  unit_amount BIGINT,
  interval TEXT CHECK (interval IN ('day', 'week', 'month', 'year')),
  interval_count INTEGER,
  trial_period_days INTEGER,
  metadata JSONB,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE subscriptions (
  id TEXT PRIMARY KEY, -- Stripe subscription ID
  organization_id UUID REFERENCES organizations(id),
  customer_id TEXT REFERENCES customers(stripe_customer_id),
  status TEXT NOT NULL,
  price_id TEXT REFERENCES prices(id),
  quantity INTEGER,
  cancel_at_period_end BOOLEAN DEFAULT false,
  current_period_start TIMESTAMPTZ,
  current_period_end TIMESTAMPTZ,
  trial_start TIMESTAMPTZ,
  trial_end TIMESTAMPTZ,
  canceled_at TIMESTAMPTZ,
  ended_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- RLS for subscription data
ALTER TABLE customers ENABLE ROW LEVEL SECURITY;
ALTER TABLE subscriptions ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Org owners can view own subscription"
  ON subscriptions FOR SELECT
  USING (
    organization_id IN (
      SELECT organization_id FROM organization_members 
      WHERE user_id = auth.uid() AND role IN ('owner', 'admin')
    )
  );

-- ============================================
-- FEATURE-SPECIFIC TABLES
-- ============================================
-- This section is customized based on your SaaS features
-- Example: Project Management SaaS

CREATE TABLE projects (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
  name TEXT NOT NULL,
  description TEXT,
  status TEXT DEFAULT 'active',
  created_by UUID REFERENCES auth.users(id),
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

ALTER TABLE projects ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Org members can view org projects"
  ON projects FOR SELECT
  USING (
    organization_id IN (
      SELECT organization_id FROM organization_members 
      WHERE user_id = auth.uid()
    )
  );

CREATE POLICY "Org members can create projects"
  ON projects FOR INSERT
  WITH CHECK (
    organization_id IN (
      SELECT organization_id FROM organization_members 
      WHERE user_id = auth.uid()
    )
  );

CREATE TABLE tasks (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
  title TEXT NOT NULL,
  description TEXT,
  status TEXT DEFAULT 'todo',
  priority TEXT DEFAULT 'medium',
  assigned_to UUID REFERENCES auth.users(id),
  due_date TIMESTAMPTZ,
  created_by UUID REFERENCES auth.users(id),
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

ALTER TABLE tasks ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Org members can view org tasks"
  ON tasks FOR SELECT
  USING (
    project_id IN (
      SELECT id FROM projects 
      WHERE organization_id IN (
        SELECT organization_id FROM organization_members 
        WHERE user_id = auth.uid()
      )
    )
  );
2.2 Next.js のファイル構成

このスキルは、本番環境に対応したファイル構成を生成します。

your-saas-app/
├── app/
│   ├── (auth)/                          # Auth layout group
│   │   ├── login/
│   │   │   └── page.tsx                 # Login page
│   │   ├── signup/
│   │   │   └── page.tsx                 # Signup page
│   │   ├── forgot-password/
│   │   │   └── page.tsx
│   │   └── layout.tsx                   # Auth pages layout
│   │
│   ├── (dashboard)/                     # Protected dashboard routes
│   │   ├── layout.tsx                   # Dashboard shell (sidebar, nav)
│   │   ├── page.tsx                     # Dashboard home
│   │   │
│   │   ├── [orgSlug]/                   # Organization-specific routes
│   │   │   ├── projects/
│   │   │   │   ├── page.tsx             # Projects list
│   │   │   │   ├── [id]/
│   │   │   │   │   └── page.tsx         # Single project view
│   │   │   │   └── new/
│   │   │   │       └── page.tsx         # Create project
│   │   │   │
│   │   │   ├── tasks/
│   │   │   │   ├── page.tsx
│   │   │   │   └── [id]/page.tsx
│   │   │   │
│   │   │   ├── team/
│   │   │   │   ├── page.tsx             # Team members
│   │   │   │   └── invite/page.tsx      # Invite flow
│   │   │   │
│   │   │   └── settings/
│   │   │       ├── page.tsx             # Org settings
│   │   │       ├── billing/
│   │   │       │   └── page.tsx         # Subscription management
│   │   │       └── members/
│   │   │           └── page.tsx         # Member management
│   │   │
│   │   └── onboarding/                  # Post-signup onboarding
│   │       ├── page.tsx
│   │       └── create-org/page.tsx
│   │
│   ├── (marketing)/                     # Public pages
│   │   ├── page.tsx                     # Landing page
│   │   ├── pricing/
│   │   │   └── page.tsx                 # Pricing page
│   │   ├── about/
│   │   │   └── page.tsx
│   │   └── layout.tsx                   # Marketing layout
│   │
│   ├── api/                             # API routes
│   │   ├── stripe/
│   │   │   ├── checkout/
│   │   │   │   └── route.ts             # Create checkout session
│   │   │   ├── portal/
│   │   │   │   └── route.ts             # Customer portal
│   │   │   └── webhook/
│   │   │       └── route.ts             # Stripe webhooks
│   │   │
│   │   └── webhooks/
│   │       └── supabase/
│   │           └── route.ts             # Supabase webhooks
│   │
│   ├── globals.css
│   └── layout.tsx                       # Root layout
│
├── components/
│   ├── ui/                              # shadcn/ui components
│   │   ├── button.tsx
│   │   ├── card.tsx
│   │   ├── dialog.tsx
│   │   ├── dropdown-menu.tsx
│   │   ├── form.tsx
│   │   ├── input.tsx
│   │   ├── table.tsx
│   │   └── ...
│   │
│   ├── layouts/
│   │   ├── dashboard-shell.tsx          # Dashboard wrapper
│   │   ├── marketing-header.tsx
│   │   └── marketing-footer.tsx
│   │
│   ├── auth/
│   │   ├── login-form.tsx
│   │   ├── signup-form.tsx
│   │   └── auth-guard.tsx               # Protected route wrapper
│   │
│   ├── billing/
│   │   ├── pricing-card.tsx
│   │   ├── subscription-status.tsx
│   │   └── usage-meter.tsx
│   │
│   ├── organizations/
│   │   ├── org-switcher.tsx             # Switch between orgs
│   │   ├── org-selector.tsx
│   │   └── invite-member-dialog.tsx
│   │
│   └── features/                        # Feature-specific components
│       ├── projects/
│       │   ├── project-list.tsx
│       │   ├── project-card.tsx
│       │   └── create-project-dialog.tsx
│       └── tasks/
│           ├── task-list.tsx
│           ├── task-card.tsx
│           └── task-form.tsx
│
├── lib/
│   ├── supabase/
│   │   ├── client.ts                    # Browser client
│   │   ├── server.ts                    # Server client
│   │   ├── middleware.ts                # Auth middleware
│   │   └── types.ts                     # Generated types
│   │
│   ├── stripe/
│   │   ├── client.ts                    # Stripe initialization
│   │   ├── products.ts                  # Product/price helpers
│   │   └── webhooks.ts                  # Webhook handlers
│   │
│   ├── hooks/
│   │   ├── use-user.ts                  # Get current user
│   │   ├── use-organization.ts          # Get current org
│   │   ├── use-subscription.ts          # Get subscription status
│   │   └── use-permissions.ts           # Check user permissions
│   │
│   ├── actions/                         # Server Actions
│   │   ├── auth.actions.ts
│   │   ├── org.actions.ts
│   │   ├── subscription.actions.ts
│   │   └── features/
│   │       ├── projects.actions.ts
│   │       └── tasks.actions.ts
│   │
│   └── utils/
│       ├── permissions.ts               # Permission checking
│       ├── rate-limit.ts                # Rate limiting
│       └── errors.ts                    # Error handling
│
├── types/
│   ├── database.types.ts                # Generated from Supabase
│   ├── stripe.types.ts
│   └── app.types.ts
│
├── middleware.ts                        # Next.js middleware (auth)
├── .env.local
├── .env.example
├── next.config.js
├── package.json
├── tailwind.config.ts
└── tsconfig.json
フェーズ 3:機能の計画と細分化

このスキルは、SaaS の機能を実装可能な単位に分解します。

3.1 SaaS の基本機能(必須)

認証とユーザー管理

## Auth Flow
**User Stories:**
- As a user, I can sign up with email/password
- As a user, I can sign in with OAuth (Google, GitHub)
- As a user, I can reset my password
- As a user, I can update my profile

**Technical Implementation:**
- Supabase Auth handles all authentication
- Magic link email for password reset
- OAuth providers configured in Supabase dashboard
- Profile updates via Server Actions

**Acceptance Criteria:**
- [ ] Users can create accounts
- [ ] Email verification works
- [ ] Password reset flow functional
- [ ] OAuth providers work
- [ ] Sessions persist across refreshes
- [ ] Logout clears session

**Time Estimate:** 2-3 days

組織管理

## Multi-Tenant Organizations
**User Stories:**
- As a user, I can create an organization
- As an owner, I can invite team members
- As a member, I can accept invitations
- As an owner, I can manage member roles
- As a user, I can switch between organizations

**Technical Implementation:**
- Organizations table with RLS
- Invitation system via email
- Role-based access control (owner, admin, member)
- Organization switcher component
- Invites expire after 7 days

**Acceptance Criteria:**
- [ ] Users can create orgs with unique slugs
- [ ] Owners can invite via email
- [ ] Invites create pending records
- [ ] Members can accept/decline
- [ ] Role changes reflect immediately
- [ ] Users can switch orgs via dropdown

**Time Estimate:** 3-4 days

サブスクリプションと請求

## Stripe Subscription Flow
**User Stories:**
- As a user, I can view pricing plans
- As an org owner, I can subscribe to a plan
- As an org owner, I can upgrade/downgrade
- As an org owner, I can manage billing
- As an org owner, I can cancel subscription

**Technical Implementation:**
- Stripe Checkout for subscriptions
- Webhook handler for subscription events
- Customer Portal for self-service billing
- Trial period (14 days)
- Graceful downgrade handling

**Acceptance Criteria:**
- [ ] Pricing page shows all plans
- [ ] Checkout flow works end-to-end
- [ ] Webhooks update subscription status
- [ ] Features respect subscription tier
- [ ] Portal allows plan changes
- [ ] Cancellation handles end of period

**Time Estimate:** 4-5 days
3.2 機能ごとの計画

このスキルは、SaaS に基づいてカスタムの機能分解を生成します。

例:プロジェクト管理機能

## Projects Feature
**User Stories:**
- As a member, I can view all org projects
- As a member, I can create new projects
- As a member, I can update project details
- As an admin, I can archive projects

**Database:**
- `projects` table with org relationship
- RLS policies for org-based access

**Components:**
- ProjectList (with search/filter)
- ProjectCard (preview)
- CreateProjectDialog (form)
- ProjectSettings (edit)

**API:**
- GET /api/projects?orgId=xxx
- POST /api/projects
- PATCH /api/projects/:id
- DELETE /api/projects/:id

**Time Estimate:** 3 days

## Tasks Feature
**User Stories:**
- As a member, I can create tasks in projects
- As a member, I can assign tasks
- As an assignee, I can update task status
- As a member, I can set due dates

**Database:**
- `tasks` table with project relationship
- Status enum (todo, in_progress, done)
- Priority enum (low, medium, high)

**Components:**
- TaskList (kanban or table view)
- TaskCard (draggable)
- CreateTaskDialog (form)
- TaskDetailView (modal)

**Time Estimate:** 3-4 days
フェーズ 4:開発ロードマップ

このスキルは、週ごとの現実的な計画を生成します。

第 1 週:基盤と認証
## Days 1-2: Project Setup
**Tasks:**
- [ ] Create Next.js 15 project with TypeScript
- [ ] Install dependencies (Supabase, Stripe, shadcn/ui, Zod)
- [ ] Set up Supabase project
- [ ] Configure environment variables
- [ ] Set up database schema (run SQL)
- [ ] Configure RLS policies
- [ ] Generate TypeScript types from database

**Deliverable:** Empty project with database ready

## Days 3-4: Authentication
**Tasks:**
- [ ] Implement Supabase Auth
- [ ] Create login/signup pages
- [ ] Add OAuth providers (Google, GitHub)
- [ ] Build auth middleware
- [ ] Create protected route wrapper
- [ ] Add password reset flow
- [ ] Style auth pages with shadcn/ui

**Deliverable:** Working authentication system

## Day 5: User Profiles
**Tasks:**
- [ ] Create profile page
- [ ] Implement profile update form
- [ ] Add avatar upload (Supabase Storage)
- [ ] Build user settings page

**Deliverable:** Users can manage profiles

## Weekend: Buffer
- Fix any blocking issues
- Test auth flows
- Start organization setup
第 2 週:組織とチーム
## Days 1-2: Organization Core
**Tasks:**
- [ ] Create org creation flow
- [ ] Build org switcher component
- [ ] Implement org slug validation
- [ ] Add org settings page
- [ ] Create org context/provider

**Deliverable:** Organizations functional

## Days 3-4: Team Management
**Tasks:**
- [ ] Build invitation system
- [ ] Create invite email templates
- [ ] Implement role management
- [ ] Add member list page
- [ ] Build invite acceptance flow

**Deliverable:** Team collaboration works

## Day 5: Polish
**Tasks:**
- [ ] Add loading states
- [ ] Improve error handling
- [ ] Add toast notifications
- [ ] Test org workflows

**Weekend:** Integration testing
第 3 週:Stripe 連携
## Days 1-2: Stripe Setup
**Tasks:**
- [ ] Set up Stripe account
- [ ] Create products and prices
- [ ] Implement webhook endpoint
- [ ] Test webhook locally (Stripe CLI)
- [ ] Add webhook handlers for key events

**Deliverable:** Stripe connected

## Days 3-4: Subscription Flow
**Tasks:**
- [ ] Build pricing page
- [ ] Implement checkout flow
- [ ] Create success/cancel pages
- [ ] Add subscription status indicator
- [ ] Implement Customer Portal link

**Deliverable:** Subscriptions work end-to-end

## Day 5: Feature Gates
**Tasks:**
- [ ] Add subscription checking middleware
- [ ] Implement usage limits per tier
- [ ] Build upgrade prompts
- [ ] Add billing page to dashboard

**Weekend:** Test all subscription scenarios
第 4 週:中核機能
## Days 1-3: Primary Feature (e.g., Projects)
**Tasks:**
- [ ] Build CRUD operations
- [ ] Create list/detail views
- [ ] Add search and filtering
- [ ] Implement Server Actions
- [ ] Add optimistic updates

**Deliverable:** Primary feature functional

## Days 4-5: Secondary Feature (e.g., Tasks)
**Tasks:**
- [ ] Build basic CRUD
- [ ] Create list view
- [ ] Add quick actions
- [ ] Implement status updates

**Weekend:** Feature testing and polish
第 5 週:仕上げとリリース準備
## Days 1-2: UX Polish
**Tasks:**
- [ ] Add loading skeletons
- [ ] Improve error messages
- [ ] Add empty states
- [ ] Implement toast notifications
- [ ] Add confirmation dialogs

## Days 3-4: Testing & Bugs
**Tasks:**
- [ ] Test all user flows
- [ ] Fix critical bugs
- [ ] Test mobile responsiveness
- [ ] Check cross-browser compatibility

## Day 5: Deploy
**Tasks:**
- [ ] Set up Vercel project
- [ ] Configure production environment variables
- [ ] Set up Stripe webhook in production
- [ ] Deploy to production
- [ ] Test production deployment

**Weekend:** Monitor, fix critical issues
フェーズ 5:セキュリティとベストプラクティス

このスキルでは、セキュリティパターンを徹底します。

5.1 Row Level Security(RLS)のパターン
-- Pattern 1: User owns resource
CREATE POLICY "Users can only access own data"
  ON table_name FOR ALL
  USING (user_id = auth.uid());

-- Pattern 2: Org member access
CREATE POLICY "Org members can access org data"
  ON table_name FOR SELECT
  USING (
    organization_id IN (
      SELECT organization_id FROM organization_members 
      WHERE user_id = auth.uid()
    )
  );

-- Pattern 3: Role-based access
CREATE POLICY "Only admins can delete"
  ON table_name FOR DELETE
  USING (
    organization_id IN (
      SELECT organization_id FROM organization_members 
      WHERE user_id = auth.uid() 
      AND role IN ('owner', 'admin')
    )
  );

-- Pattern 4: Resource creator can update
CREATE POLICY "Creator can update"
  ON table_name FOR UPDATE
  USING (created_by = auth.uid());
5.2 Server Action のセキュリティ
// lib/actions/secure-action.ts
import { createClient } from '@/lib/supabase/server';
import { redirect } from 'next/navigation';

export async function secureAction(
  handler: (userId: string, orgId: string) => Promise<any>
) {
  const supabase = await createClient();
  
  // 1. Verify authentication
  const { data: { user }, error } = await supabase.auth.getUser();
  
  if (error || !user) {
    redirect('/login');
  }
  
  // 2. Get current organization
  const { data: membership } = await supabase
    .from('organization_members')
    .select('organization_id')
    .eq('user_id', user.id)
    .single();
    
  if (!membership) {
    throw new Error('No organization access');
  }
  
  // 3. Execute handler with verified context
  return handler(user.id, membership.organization_id);
}

// Usage in Server Actions
export async function createProject(formData: FormData) {
  'use server';
  
  return secureAction(async (userId, orgId) => {
    const name = formData.get('name') as string;
    
    // Validation
    if (!name || name.length < 3) {
      return { error: 'Name must be at least 3 characters' };
    }
    
    // Database operation (RLS will further verify access)
    const supabase = await createClient();
    const { data, error } = await supabase
      .from('projects')
      .insert({
        name,
        organization_id: orgId,
        created_by: userId
      })
      .select()
      .single();
      
    if (error) {
      return { error: error.message };
    }
    
    return { data };
  });
}
5.3 API Route のセキュリティ
// app/api/stripe/webhook/route.ts
import { headers } from 'next/headers';
import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET!;

export async function POST(req: Request) {
  const body = await req.text();
  const signature = headers().get('stripe-signature');

  if (!signature) {
    return new Response('No signature', { status: 400 });
  }

  try {
    // Verify webhook signature
    const event = stripe.webhooks.constructEvent(
      body,
      signature,
      webhookSecret
    );

    // Handle different events
    switch (event.type) {
      case 'checkout.session.completed':
        await handleCheckoutComplete(event.data.object);
        break;
      case 'customer.subscription.updated':
        await handleSubscriptionUpdate(event.data.object);
        break;
      case 'customer.subscription.deleted':
        await handleSubscriptionCancel(event.data.object);
        break;
    }

    return new Response(JSON.stringify({ received: true }));
  } catch (err) {
    console.error('Webhook error:', err);
    return new Response('Webhook error', { status: 400 });
  }
}
フェーズ 6:デプロイとモニタリング
6.1 環境変数
# .env.example
# Supabase
NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key

# Stripe
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_xxx
STRIPE_SECRET_KEY=sk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx

# App
NEXT_PUBLIC_APP_URL=http://localhost:3000
NEXT_PUBLIC_APP_NAME=YourSaaS

# Email (optional)
RESEND_API_KEY=re_xxx
6.2 Vercel デプロイチェックリスト
## Pre-Deploy
- [ ] All environment variables set in Vercel
- [ ] Supabase RLS policies tested
- [ ] Stripe webhook URL configured for production
- [ ] Production Stripe keys configured
- [ ] Error tracking set up (Sentry)
- [ ] Analytics configured (PostHog, Plausible)

## Deploy
- [ ] Push to main branch
- [ ] Verify build succeeds
- [ ] Check production URL
- [ ] Test critical flows in production

## Post-Deploy
- [ ] Monitor error rates
- [ ] Check webhook delivery
- [ ] Verify subscription flows
- [ ] Test on mobile devices

出力形式

SaaS アーキテクチャの計画を依頼すると、このスキルは次の内容を提供します。

# [Your SaaS Name] - Technical Architecture Document

## Executive Summary
[2-3 paragraphs: what you're building, for whom, tech stack]

## Product Overview
**Name:** [Product Name]
**Target:** [Target Audience]
**Value Prop:** [One-liner]
**Revenue Model:** [Pricing strategy]

## Technical Stack
- **Frontend:** Next.js 15 (App Router) + TypeScript + Tailwind CSS
- **UI Components:** shadcn/ui
- **Backend:** Next.js Server Actions + API Routes
- **Database:** PostgreSQL (Supabase)
- **Auth:** Supabase Auth
- **Payments:** Stripe
- **Storage:** Supabase Storage
- **Hosting:** Vercel
- **Email:** Resend (optional)

## Database Architecture
[Complete SQL schema with RLS policies]

## File Structure
[Full Next.js directory structure]

## Feature Breakdown

### Core SaaS Features (Week 1-3)
[Authentication, Organizations, Subscriptions]

### Product Features (Week 4-6)
[Your specific features broken down]

## Development Roadmap
[Week-by-week plan with tasks and deliverables]

## Security Considerations
[RLS patterns, authentication flows, API security]

## Deployment Strategy
[Vercel setup, environment variables, monitoring]

## Success Metrics
- **Activation:** [First meaningful action]
- **Engagement:** [Regular usage indicator]
- **Retention:** [Return behavior]
- **Revenue:** [MRR growth targets]

## Risks & Mitigations
| Risk | Impact | Mitigation |
|------|--------|------------|
| [Risk 1] | [High/Med/Low] | [How to handle] |

## Next Steps
1. [First actionable task]
2. [Second task]
3. [Third task]

このスキルの使い方

基本的な使い方
I need architecture for a SaaS product.

Use saas-architect skill.

Idea: [Your SaaS idea]
Target Users: [Who]
Pricing: [How you'll charge]
詳細な計画
Create complete SaaS architecture plan using saas-architect.

Product: [Detailed description]
Features: [List key features]
Timeline: [Launch target]
Constraints: [Any technical/business constraints]
機能ごとの計画
I have existing SaaS, need to add [feature].

Use saas-architect to plan:
- Database changes needed
- File structure for feature
- Implementation steps
- Timeline estimate

Existing Stack: Next.js 15 + Supabase

開発との連携

Claude Code との連携

アーキテクチャを生成した後、Claude Code で次のように使用します。

Generate starter code for this SaaS architecture:

[Paste architecture document]

Start with:
1. Database schema (run SQL in Supabase)
2. Initial project structure
3. Auth implementation
4. Organization setup
他のスキルとの連携

推奨ワークフロー:

  1. idea-validator-pro → 市場適合性を検証
  2. saas-architect → 技術計画
  3. modern-ui-designer → デザインシステム
  4. Claude Code → 実装
  5. code-quality-guardian → コードレビュー
  6. deployment-automation → リリース

ベストプラクティス

するべきこと ✅
  • SaaS の基本機能から始める:まず認証、組織、サブスクリプションに取り組む
  • あらゆる場所で RLS を使う:Row Level Security を省略しない
  • サブスクリプションを早期にテストする:Stripe の Webhook は非常に重要
  • マルチテナントを前提に計画する:シングルテナントで始める場合でも対応する
  • 決定事項を記録する:将来の自分に役立ちます
してはいけないこと ❌
  • RLS ポリシーを省略する:データ漏えいは致命的です
  • Stripe のキーをハードコードする:環境変数を使用する
  • Webhook のテストを軽視する:まず Webhook をローカルでテストする
  • 過剰に設計する:シンプルに始め、後からスケールする
  • 認証なしで構築する:認証から始める

よくあるシナリオ

シナリオ 1:フリーミアム SaaS
Challenge: Need free tier with upgrade path
Solution: 
- Free tier with feature limits
- Trial period for paid plans
- Usage tracking in database
- Upgrade prompts in UI
シナリオ 2:チームコラボレーション
Challenge: Multiple users per organization
Solution:
- Organization-based RLS
- Role-based permissions
- Invitation system
- Activity logging
シナリオ 3:従量課金
Challenge: Charge based on usage, not seats
Solution:
- Usage tracking table
- Metered billing with Stripe
- Usage dashboards
- Overage handling

技術的負債の防止

フェーズ 1(1〜2 週目):想定なし

基盤を適切に整えることに注力します。

フェーズ 2(3〜4 週目):以下を監視
  • テストカバレッジ(重要な処理経路で 70% 超を目指します)
  • エラーハンドリングの一貫性
  • ローディング状態のパターン
フェーズ 3(5〜6 週目):リファクタリングの時間
  • 再利用可能なフックを抽出します
  • 類似したコンポーネントを統合します
  • データベースクエリを最適化します
  • 不足しているインデックスを追加します

リリースチェックリスト

リリース前(1 週間前)
  • すべての主要機能が動作する
  • モバイル対応をテスト済み
  • クロスブラウザーでテスト済み
  • 決済フローをエンドツーエンドでテスト済み
  • エラートラッキングを設定済み
  • アナリティクスを設定済み
  • 利用規約を用意済み
  • プライバシーポリシーを用意済み
  • サポートメールを設定済み
リリース当日
  • 本番環境にデプロイ
  • すべての Webhook が動作していることを確認
  • サインアップフローをテスト
  • サブスクリプションフローをテスト
  • エラー率を監視
  • アナリティクストラッキングを確認
リリース後(最初の 1 週間)
  • 毎日監視
  • 重大なバグを修正
  • ユーザーからのフィードバックを収集
  • 課題点を改善

スキルのメタデータ

バージョン: 1.0.0
最終更新日: 2025 年 11 月
最適化対象: Next.js 15、Supabase、Stripe
対象: SaaS 製品を構築する個人開発者
出力: 技術アーキテクチャの完全なドキュメント


重要なポイント:優れた SaaS アーキテクチャとは、すべての機能を備えることではなく、拡張性のある適切な基盤を構築することです。まずは認証、マルチテナンシー、サブスクリプションに注力しましょう。それ以外は後から改善できます。

コメント