jpskill.com
🛠️ 開発・MCP コミュニティ

api-baas-supabase

Supabaseは、認証、データベース、リアルタイム通信、ストレージなどのバックエンド機能をまとめて提供し、エッジ関数やセキュリティポリシーも設定できる、モダンなWeb/アプリ開発を効率化するSkill。

📜 元の英語説明(参考)

Supabase backend-as-a-service — Auth, Database, Realtime, Storage, Edge Functions, RLS policies, typed client

🇯🇵 日本人クリエイター向け解説

一言でいうと

Supabaseは、認証、データベース、リアルタイム通信、ストレージなどのバックエンド機能をまとめて提供し、エッジ関数やセキュリティポリシーも設定できる、モダンなWeb/アプリ開発を効率化するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o api-baas-supabase.zip https://jpskill.com/download/10227.zip && unzip -o api-baas-supabase.zip && rm api-baas-supabase.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/10227.zip -OutFile "$d\api-baas-supabase.zip"; Expand-Archive "$d\api-baas-supabase.zip" -DestinationPath $d -Force; ri "$d\api-baas-supabase.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して api-baas-supabase.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → api-baas-supabase フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

Supabase パターン

クイックガイド: Supabase を Postgres データベース、認証、リアルタイムサブスクリプション、ファイルストレージ、およびエッジ関数用の backend-as-a-service として使用します。常に Database ジェネリックを使用した型付きクライアントを使用し、すべてのテーブルで RLS を有効にし、シークレットキーはサーバーでのみ使用してください。


<critical_requirements>

重要: この Skill を使用する前に

すべてのコードは CLAUDE.md のプロジェクト規約に従う必要があります (kebab-case、名前付きエクスポート、インポート順序、import type、名前付き定数)

(公開されたスキーマ内のすべてのテーブルで、必ず Row Level Security (RLS) を有効にする必要があります — 例外はありません)

(型安全なクエリのために、createClient<Database>()Database ジェネリック型を必ず使用する必要があります)

(クライアント側のコードでシークレットキーを絶対に公開しないでください — ブラウザでは公開可能なキーを使用し、シークレットキーはサーバーでのみ使用してください)

(パフォーマンスのために、RLS ポリシー内でサブクエリでラップされた (select auth.uid()) を必ず使用する必要があります)

(すべての Supabase レスポンスを { data, error } でデストラクトして処理する必要があります — 成功を前提としないでください)

</critical_requirements>


自動検出: Supabase, createClient, @supabase/supabase-js, @supabase/ssr, supabase-js, auth.uid(), RLS, row level security, realtime, postgres_changes, supabase.auth, supabase.from, supabase.storage, supabase.functions, supabase.channel, edge function, Deno.serve

使用する場面:

  • TypeScript の型安全性を備えた Supabase クライアントのセットアップ
  • 認証の実装 (メール/パスワード、OAuth、マジックリンク、セッション管理)
  • Supabase クライアント経由での Postgres のクエリ (select, insert, update, delete, RPC)
  • データアクセス制御のための Row Level Security ポリシーの記述
  • データベースの変更をリアルタイムでサブスクライブ
  • Supabase Storage からのファイルのアップロードと提供
  • Supabase Edge Functions (Deno) を使用したサーバーレス関数の構築

カバーする主要なパターン:

  • Database ジェネリックと環境変数を使用した型付きクライアントのセットアップ
  • 認証フロー: サインアップ、サインイン、OAuth、マジックリンク、セッションリフレッシュ、onAuthStateChange
  • フィルター、結合、RPC 呼び出し、およびエラー処理を使用したデータベースクエリ
  • RLS ポリシー: USING vs WITH CHECKauth.uid()、ロールベースのアクセス
  • channel().on('postgres_changes') を介したリアルタイムサブスクリプション
  • ストレージ: アップロード、署名付き URL、パブリック URL、バケットポリシー
  • エッジ関数: Deno.serve、CORS ヘッダー、シークレット、関数内の Supabase クライアント

使用しない場面:

  • 直接的な Postgres 接続 (代わりにデータベースドライバースキルを使用)
  • 複雑なサーバーサイド ORM パターン (専用の ORM スキルを使用)
  • Supabase 以外の認証プロバイダー (専用の認証スキルを使用)

詳細なリソース:

  • 意思決定フレームワークとアンチパターンについては、reference.md を参照してください。

クライアントとクエリ:

  • examples/core.md — クライアントのセットアップ、型付きクエリ、エラー処理パターン

認証:

  • examples/auth.md — 完全な認証フロー、OAuth、マジックリンク、セッションリフレッシュ、ミドルウェア保護

データベース:

ストレージ:

  • examples/storage.md — ファイルアップロード、署名付き URL、バケットポリシー、画像変換

エッジ関数:


<philosophy>

哲学

Supabase は、Postgres 上に構築されたオープンソースの Firebase の代替です。Postgres 拡張機能、自動生成された REST/GraphQL API、認証、リアルタイムサブスクリプション、ファイルストレージ、およびエッジ関数の組み合わせを通じて、完全なバックエンドを提供します。

コア原則:

  1. コアは Postgres — すべての機能は Postgres 上に構築されています。RLS ポリシー、認証、およびリアルタイムはすべて Postgres プリミティブを活用します。Postgres を理解することは、Supabase を理解することです。
  2. エンドツーエンドの型安全性supabase gen types を使用して、データベーススキーマから TypeScript 型を生成します。Database ジェネリックを createClient に渡して、完全に型付けされたクエリを実現します。
  3. デフォルトでセキュリティ — RLS はすべてのテーブルで有効にする必要があります。公開可能なキーはブラウザで安全です (RLS がアクセスを強制します)。シークレットキーは RLS をバイパスするため、サーバーから決して離れてはなりません。
  4. 値としてのエラー — すべての Supabase メソッドは { data, error } を返します。成功を前提としないでください。data を使用する前に、必ず error を確認してください。
  5. 組み込みのリアルタイム — Postgres の変更は、チャネルを介して WebSocket 経由でストリーミングされます。個別の pub/sub インフラストラクチャは必要ありません。
  6. エッジファースト関数 — エッジ関数は、ユーザーに近いエッジで Deno を実行します。短命で冪等な操作を想定して設計してください。

Supabase を使用する場面:

  • Postgres、認証、およびストレージをすぐに利用できる迅速なバックエンド開発
  • リアルタイム機能 (チャット、通知、ライブダッシュボード) を必要とするプロジェクト
  • 個別の認証、データベース、およびストレージサービスの管理を避けたいチーム
  • マルチテナントデータ分離のために Row Level Security が役立つアプリケーション

使用しない場面:

  • 完全なアプリケーションサーバーを必要とする複雑なサーバーサイドビジネスロジック (単純なケースにはエッジ関数を使用し、複雑なケースには専用の API を使用)
  • 高度なクエリ構築を備えた ORM を必要とするアプリケーション (Supabase クエリビルダーは強力ですが、完全な ORM ではありません)
  • 複雑な同期プロトコルを必要とするオフラインファーストアプリケーション

</philosophy>


<patterns>

コアパターン

パターン 1: 型付きクライアントのセットアップ

テーブル名、カラム名、および戻り値の型を完全にオートコンプリートするには、常に Database ジェネリックを createClient に渡します。URL とキーには環境変数を使用します。

export const supabase = createClient<Database>(
  SUPABASE_URL,
  SUPABASE_PUBLISHABLE_KEY,
);

ジェネリックがない場合、テーブル/カラム名のタイプミスはコンパイル時に検出されません。examples/core.md を参照して、ブラウザ、サーバー、および管理者クライアントのセットアップパターンを確認してください。


パターン 2: { data, error } を使用したエラー処理

すべての Supabase メソッドは { data, error } を返します。常にデストラクトして、data を使用する前に error を確認してください。決してノー

📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Supabase Patterns

Quick Guide: Use Supabase as your backend-as-a-service for Postgres database, authentication, realtime subscriptions, file storage, and edge functions. Always use the typed client with Database generic, enable RLS on every table, and use the secret key only on the server.


<critical_requirements>

CRITICAL: Before Using This Skill

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST enable Row Level Security (RLS) on EVERY table in an exposed schema — no exceptions)

(You MUST use the Database generic type with createClient<Database>() for type-safe queries)

(You MUST NEVER expose the secret key in client-side code — use the publishable key in browsers, the secret key only on the server)

(You MUST use (select auth.uid()) wrapped in a subquery inside RLS policies for performance)

(You MUST handle all Supabase responses with { data, error } destructuring — never assume success)

</critical_requirements>


Auto-detection: Supabase, createClient, @supabase/supabase-js, @supabase/ssr, supabase-js, auth.uid(), RLS, row level security, realtime, postgres_changes, supabase.auth, supabase.from, supabase.storage, supabase.functions, supabase.channel, edge function, Deno.serve

When to use:

  • Setting up a Supabase client with TypeScript type safety
  • Implementing authentication (email/password, OAuth, magic links, session management)
  • Querying Postgres via the Supabase client (select, insert, update, delete, RPC)
  • Writing Row Level Security policies for data access control
  • Subscribing to database changes in real time
  • Uploading and serving files from Supabase Storage
  • Building serverless functions with Supabase Edge Functions (Deno)

Key patterns covered:

  • Typed client setup with Database generic and environment variables
  • Auth flows: sign up, sign in, OAuth, magic link, session refresh, onAuthStateChange
  • Database queries with filters, joins, RPC calls, and error handling
  • RLS policies: USING vs WITH CHECK, auth.uid(), role-based access
  • Realtime subscriptions via channel().on('postgres_changes')
  • Storage: upload, signed URLs, public URLs, bucket policies
  • Edge Functions: Deno.serve, CORS headers, secrets, Supabase client in functions

When NOT to use:

  • Direct Postgres connections (use a database driver skill instead)
  • Complex server-side ORM patterns (use a dedicated ORM skill)
  • Non-Supabase authentication providers (use dedicated auth skills)

Detailed Resources:

  • For decision frameworks and anti-patterns, see reference.md

Client & Queries:

Authentication:

  • examples/auth.md — Full auth flows, OAuth, magic links, session refresh, middleware protection

Database:

Storage:

Edge Functions:


<philosophy>

Philosophy

Supabase is an open-source Firebase alternative built on Postgres. It provides a complete backend through a combination of Postgres extensions, auto-generated REST/GraphQL APIs, authentication, realtime subscriptions, file storage, and edge functions.

Core principles:

  1. Postgres at the core — Every feature is built on Postgres. RLS policies, auth, and realtime all leverage Postgres primitives. Understanding Postgres is understanding Supabase.
  2. Type safety end-to-end — Generate TypeScript types from your database schema with supabase gen types. Pass the Database generic to createClient for fully typed queries.
  3. Security by default — RLS must be enabled on every table. The publishable key is safe for browsers (RLS enforces access). The secret key bypasses RLS and must never leave the server.
  4. Error as values — Every Supabase method returns { data, error }. Never assume success. Always check error before using data.
  5. Realtime built in — Postgres changes stream over WebSockets via channels. No separate pub/sub infrastructure needed.
  6. Edge-first functions — Edge Functions run Deno at the edge, close to users. Design for short-lived, idempotent operations.

When to use Supabase:

  • Rapid backend development with Postgres, auth, and storage out of the box
  • Projects needing realtime features (chat, notifications, live dashboards)
  • Teams wanting to avoid managing separate auth, database, and storage services
  • Applications that benefit from Row Level Security for multi-tenant data isolation

When NOT to use:

  • Complex server-side business logic requiring a full application server (use Edge Functions for simple cases, a dedicated API for complex ones)
  • Applications needing an ORM with advanced query building (Supabase query builder is powerful but not a full ORM)
  • Offline-first applications requiring complex sync protocols

</philosophy>


<patterns>

Core Patterns

Pattern 1: Typed Client Setup

Always pass the Database generic to createClient for full autocomplete on table names, column names, and return types. Use environment variables for URL and keys.

export const supabase = createClient<Database>(
  SUPABASE_URL,
  SUPABASE_PUBLISHABLE_KEY,
);

Without the generic, typos in table/column names are not caught at compile time. See examples/core.md for browser, server, and admin client setup patterns.


Pattern 2: Error Handling with { data, error }

Every Supabase method returns { data, error }. Always destructure and check error before using data. Never use non-null assertions on data.

const { data, error } = await supabase
  .from("profiles")
  .select("id, username")
  .eq("id", userId)
  .single();
if (error) throw new Error(`Failed to fetch profile: ${error.message}`);

See examples/core.md for the reusable error handler pattern and common mistakes.


Pattern 3: Authentication Flows

Supabase Auth supports email/password (signInWithPassword), OAuth (signInWithOAuth), magic links (signInWithOtp), and phone OTP. Register onAuthStateChange early in the app lifecycle and always clean up with subscription.unsubscribe().

Key gotcha: Do NOT call Supabase methods directly inside onAuthStateChange — use setTimeout(..., 0) to defer.

See examples/auth.md for sign up, sign in, OAuth, magic link, session management, middleware protection, and password reset patterns.


Pattern 4: Database Queries

Use the query builder for type-safe CRUD with filters, joins, ordering, and pagination. Always add .select() after .insert() or .update() to return the affected row.

const { data, error } = await supabase
  .from("posts")
  .select("id, title, author:profiles(username)")
  .eq("published", true)
  .order("created_at", { ascending: false })
  .range(0, PAGE_SIZE - 1);

See examples/database.md for complex queries, upserts, RPC calls, conditional filters, counting, and migrations.


Pattern 5: Row Level Security (RLS) Policies

RLS is the primary security mechanism. Enable it on every table, write separate policies per operation (not FOR ALL), and wrap auth.uid() in a subquery for performance.

alter table public.posts enable row level security;

create policy "posts_select" on public.posts for select to authenticated
using ( published = true or (select auth.uid()) = author_id );

Never trust user_metadata from JWT for access control — it is user-modifiable. See examples/database.md for full CRUD policies, team-based access, and anti-patterns.


Pattern 6: Realtime Subscriptions

Subscribe to database changes via channel().on('postgres_changes', ...). Always unsubscribe on cleanup. DELETE events cannot be filtered — all deletes are received. UPDATE/DELETE payloads need replica identity full for old record data.

const channel = supabase
  .channel("room-messages")
  .on(
    "postgres_changes",
    {
      event: "INSERT",
      schema: "public",
      table: "messages",
      filter: `room_id=eq.${roomId}`,
    },
    (payload) => {
      /* handle */
    },
  )
  .subscribe();

Use for chat, live dashboards, notifications. Avoid for high-frequency data (> 100 updates/sec).


Pattern 7: Storage Operations

Upload files with supabase.storage.from(bucket).upload(). Use getPublicUrl() for public buckets, createSignedUrl() for private buckets with time-limited access. Storage access control uses RLS on storage.objects.

See examples/storage.md for upload, signed URLs, public URLs, image transforms, bucket policies, and signed upload URLs.


Pattern 8: Edge Functions

Use Deno.serve() (not the deprecated serve import). Import supabase-js with npm: prefix: import { createClient } from "npm:@supabase/supabase-js@2". Handle CORS on every response. Use Deno.env.get() for secrets. Forward user JWT for RLS enforcement.

See examples/edge-functions.md for basic functions, authenticated access, shared utilities, webhooks, multi-route "fat functions", and background processing with EdgeRuntime.waitUntil().

</patterns>


<decision_framework>

Decision Framework

Which Supabase Key to Use

Where is the code running?
├─ Browser / Client-side → publishable key (RLS enforced)
├─ Server / API route → publishable key + user JWT (RLS enforced per user)
└─ Admin / Migration script → secret key (bypasses RLS)
    └─ NEVER expose the secret key in client bundles

Auth Method Selection

What auth flow does the user need?
├─ Email + Password → signInWithPassword
├─ Social login (GitHub, Google, etc.) → signInWithOAuth
├─ Passwordless email → signInWithOtp (magic link)
├─ Phone + SMS → signInWithOtp (phone)
└─ SSO / SAML → signInWithSSO (enterprise)

Realtime vs Polling

How fresh must the data be?
├─ Instant (< 1 second) → Realtime subscription (postgres_changes)
├─ Near-instant (1-5 seconds) → Realtime subscription
├─ Periodic (> 5 seconds ok) → Polling with setInterval
└─ On-demand (user refresh) → Re-fetch on action
    └─ High-frequency updates (> 100/sec)?
        ├─ YES → Polling or batch (Realtime has per-subscriber checks)
        └─ NO → Realtime is fine

Storage: Public vs Private Buckets

Who should access the files?
├─ Anyone (public assets, avatars) → Public bucket + getPublicUrl()
├─ Authenticated users only → Private bucket + createSignedUrl()
├─ Specific users (own files) → Private bucket + RLS on storage.objects
└─ Server-only processing → secret key for upload/download

Edge Functions vs Client Queries

Does the operation need server-side logic?
├─ Simple CRUD → Client query with RLS (no edge function needed)
├─ Multi-step / transactional → Edge function or Postgres function (RPC)
├─ Third-party API call → Edge function
├─ Webhook receiver → Edge function
└─ Heavy computation → Edge function with EdgeRuntime.waitUntil() for background work

</decision_framework>


<red_flags>

RED FLAGS

High Priority Issues:

  • Missing RLS on tables — Any table without RLS in an exposed schema is completely open to the public. In January 2025, 170+ apps were found with exposed databases due to missing RLS (CVE-2025-48757).
  • Secret key in client code — The secret key (formerly service_role key) bypasses all RLS. Exposing it in browser bundles gives every user full admin database access.
  • Ignoring { data, error } returns — Accessing data without checking error leads to runtime crashes when operations fail.
  • Using auth.jwt() ->> 'user_metadata' in RLS policiesuser_metadata is modifiable by authenticated users via updateUser(). Never use it for access control decisions.

Medium Priority Issues:

  • Using FOR ALL in RLS policies — Separate into SELECT, INSERT, UPDATE, DELETE policies for clarity and auditability.
  • Bare auth.uid() in policies without subquery — Wrap in (select auth.uid()) for up to 94-99% performance improvement per Supabase benchmarks.
  • Not specifying to authenticated or to anon in policies — Without a role, policies apply to all roles, which may expose data unintentionally.
  • *Using `select("")` everywhere** — Fetches all columns including sensitive data. Select only the columns you need.
  • Deprecated serve import in Edge Functionsimport { serve } from "https://deno.land/std/http/server.ts" is deprecated. Use Deno.serve().

Common Mistakes:

  • Not adding .select() after .insert() or .update() — Without .select(), these methods return no data (only null).
  • Missing CORS headers in Edge Functions — Browser requests fail without proper CORS headers and OPTIONS handling.
  • Not unsubscribing from Realtime channels — Leaks WebSocket connections and can cause memory issues.
  • Using bare specifiers in Edge Functionsimport { createClient } from "@supabase/supabase-js" fails in Deno. Use npm:@supabase/supabase-js@2.
  • Using getSession() to verify authgetSession() reads from local storage and can be tampered with. Use getUser() for secure server-side verification.

Gotchas & Edge Cases:

  • Realtime DELETE events cannot be filtered — All deletes for a subscribed table are received regardless of filter.
  • Realtime requires replica identity full for old record data — By default, UPDATE and DELETE payloads only include the new record. Set alter table X replica identity full to access payload.old.
  • RLS policies are not applied to Realtime DELETE events — Be cautious about what information DELETE events expose.
  • onAuthStateChange fires on tab focusSIGNED_IN events fire when a browser tab regains focus, not just on actual sign-in.
  • Do NOT call Supabase methods inside onAuthStateChange callback — This can cause deadlocks. Use setTimeout(..., 0) to defer.
  • Signed URLs expirecreateSignedUrl() URLs expire after the specified duration. Signed upload URLs expire after 2 hours.
  • Public bucket URLs bypass RLS — Files in public buckets are accessible to anyone with the URL, regardless of policies.
  • Edge Function cold starts — First invocation after idle period has additional latency. Design "fat functions" (fewer, larger functions) to minimize cold starts.
  • Edge Functions: file writes only on /tmp — The /tmp directory is the only writable path in edge functions.

</red_flags>


<critical_reminders>

CRITICAL REMINDERS

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST enable Row Level Security (RLS) on EVERY table in an exposed schema — no exceptions)

(You MUST use the Database generic type with createClient<Database>() for type-safe queries)

(You MUST NEVER expose the secret key in client-side code — use the publishable key in browsers, the secret key only on the server)

(You MUST use (select auth.uid()) wrapped in a subquery inside RLS policies for performance)

(You MUST handle all Supabase responses with { data, error } destructuring — never assume success)

Failure to follow these rules will create security vulnerabilities, type-unsafe queries, and silent runtime failures.

</critical_reminders>