こんにちは。
今回はwebアプリ制作の第3回ということで、ついに投稿機能を実装していきます。
そのためにSupabaseというサービスを使って、投稿とデータベースへの保存を可能にしていきます。
量が多いので、前編、中編、後編の3部構成になっております。
Supabaseとは?
Supabase は、Firebase の代替として使われる オープンソースのバックエンドサービス です。
以下のような機能を提供してくれます:
- PostgreSQL データベース(SQLベースのデータ管理)
- 認証機能(Auth)(ユーザーログイン・管理)
- リアルタイムデータ更新(データが変わると自動で画面更新)
- ストレージ(画像やファイルをアップロード)
Supabaseを使うことで、投稿内容をデータベースに保存し、後で一覧表示できる ようになります。
Supabase プロジェクトを作成
① Supabase のアカウント作成
- Supabaseの公式サイト にアクセス
- 「Start your project」 をクリック
- GitHub でログイン(またはアカウント作成)
② 新しいプロジェクトを作成
- 「New Project」 をクリック
- プロジェクト名 を入力(例: my-app)
- データベースのパスワードを設定(忘れないようにメモ)
- リージョンは「Northeast Asia(日本)」を選択
- 「Create new project」をクリック
👉 プロジェクトが作成されるまで数分かかるので、少し待つ。
環境変数を設定
① APIキーを取得
- Supabaseの 「Settings → Data API」 に移動
- 「Project URL」 と 「anon public key」 をコピー
👀 取得する情報
- Supabase URL(例: https://xyzcompany.supabase.co)
- anon public key(例: eyJhbGciOiJIUzI1NiIsInR…)
② .env.local に追加
Next.js プロジェクトの .env.local を開いて、以下の内容を追加します。
NEXT_PUBLIC_SUPABASE_URL=https://xyzcompany.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR...
👉 NEXT_PUBLIC_ をつけることで、フロントエンドから直接利用可能になる。
👉 .env.local を変更したら、Next.js の開発サーバーを再起動 する必要があるので、ターミナルで以下のコマンドを入力。
npm run dev
Supabase のパッケージをインストール
Supabase を Next.js で使うために、ターミナルから@supabase/supabase-js をインストールします。
npm install @supabase/supabase-js
Supabase クライアントを作成
Supabaseを使うための クライアント(接続設定) を作成します。
lib/supabase.ts を作成
lib/supabase.ts を新しく作成し、以下のコードを追加:
import { createClient } from "@supabase/supabase-js";
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!;
export const supabase = createClient(supabaseUrl, supabaseAnonKey);
💡 ここでのポイント
- createClient() を使って Supabase に接続
- .env.local から URL と API キーを取得
- supabase オブジェクトをエクスポートし、どこでも使えるようにする
Clerk の JWT Templates 設定
JWTについて詳しく解説(クリックで展開)
JWT(JSON Web Token)とは?
- JWT(JSON Web Token) は、認証情報を安全にやり取りするための「デジタル証明書」 です。
- これは 「このユーザーは本当に正しいログインユーザーです!」という証拠 を表すもの。
- これがあることで、「この JWT を持っている人=Clerk にログイン済みのユーザー」として Supabase に認識されます。
なぜ Clerk の JWT Templates 設定が必要なの?
- Clerk でログインしただけでは、その情報を Supabase は知らない!
- Clerk のユーザーを Supabase でも認証できるようにするため、JWT Templates を作成する!
Clerk → Supabase への認証の流れ
- ユーザーが Clerk でログインする
- getToken({ template: “supabase” }) で Clerk から Supabase 用の JWT を取得
- その JWT を API の Authorization ヘッダーに付けて送信
- Supabase がその JWT を検証し、「このユーザーは認証済みだ!」と判断
✅ このために、Clerk 側で Supabase 用の JWT を発行する「JWT Templates」を作成する!
設定手順
- Supabase の「Project Settings」→「Data API」の JWT Settings から JWT Secret をコピー
- Clerkのダッシュボード にアクセス
- 「JWT Templates」 に移動
- 「New JWT Template」 を作成
- 以下のように設定
- Template Name: supabase
- Claims:
{
"role": "authenticated",
"email": "{{user.primary_email_address}}",
"user_id": "{{user.id}}"
}
- Signing key: 先ほどコピーした JWT Secret をペースト
- 「Save」 をクリック

こんな感じです。
項目 | 説明 |
---|---|
Template Name: supabase | Clerk で JWT を発行するときのテンプレート名 |
Claims: | JWT に含める情報(Supabase に送るユーザー情報) |
role: “authenticated” | Supabase に「このユーザーは認証済み」と伝える |
email: {{user.primary_email_address}} | JWT にユーザーのメールアドレスを含める |
user_id: {{user.id}} | Clerk の userId(user_xxxxxx の形式)を含める |
Signing key(署名キー) | Supabase の JWT Secret を登録(これがないと Supabase で JWT を検証できない) |
- この設定が完了すると、Clerk の getToken({ template: “supabase” }) を使った際に Supabase 用の JWT が取得できるようになります。
Supabase のデータベースを設定
テーブルを作成
- Supabaseのダッシュボード にアクセス
- 「Database」 → 「Tables」 → 「New Table」 をクリック
- 以下のようにテーブルを2つ作成します:
1つ目のテーブル名:users
以下の二つの項目にはチェックしない ❌
❌ Enable Row Level Security (RLS) (Recommended)
Restrict access to your table by enabling RLS and writing Postgres policies.
❌ Enable Realtime
Broadcast changes on this table to authorized subscribers
テーブルは以下のように作成して下さい。
Column Name | Type | Default Value | Primary Key | Is Nullable | Is Unique | Define as Array |
id | UUID | gen_random_uuid() | ✅ Yes | (自動で No) | (自動で Yes) | (自動で No) |
clerk_id | text | (何も設定しない) | ❌ No | ❌ No | ✅ Yes | ❌ No |
Is Nullable, Is Unique, Define as Array は Primary Key を 「No」 に設定すると右に出てくる歯車から設定して下さい。
2つ目のテーブル名:post
以下の二つの項目にチェック ✅
✅ Enable Row Level Security (RLS) (Recommended)
Restrict access to your table by enabling RLS and writing Postgres policies.
✅ Enable Realtime(こっちはチェックしてもしなくてもいいです)
Broadcast changes on this table to authorized subscribers
テーブルは以下のように作成して下さい。
Column Name | Type | Default Value | Primary Key | Is Nullable | Is Unique | Define as Array |
id | UUID | gen_random_uuid() | ✅ Yes | (自動で No) | (自動で Yes) | (自動で No) |
user_id | text | (何も設定しない) | ❌ No | ❌ No | ❌ No | ❌ No |
content | text | (何も設定しない) | ❌ No | ❌ No | ❌ No | ❌ No |
created_at | timestamptz | now() | ❌ No | ❌ No | ❌ No | ❌ No |
- 「Save」 を押してテーブルを作成
Supabase の SQL で外部キーを設定
SQLについて詳しく解説(クリックで展開)
SQL(Structured Query Language)とは?
- SQL(エスキューエル) とは、データベースを操作するための言語 です。
- Supabase では、データベースに保存されたデータを操作するために SQL を使います!
- Supabase の「SQL Editor」 で SQL コマンドを実行できます!
SQL を使うと、次のような操作が可能になります。
操作 | SQL コマンド | 例 |
---|---|---|
データを取得 | SELECT | SELECT * FROM users; |
データを追加 | INSERT | INSERT INTO users (clerk_id) VALUES (‘user_123’); |
データを更新 | UPDATE | UPDATE users SET clerk_id = ‘user_456’ WHERE clerk_id = ‘user_123’; |
データを削除 | DELETE | DELETE FROM users WHERE clerk_id = ‘user_123’; |
テーブルを作成 | CREATE TABLE | CREATE TABLE users (id UUID PRIMARY KEY, clerk_id TEXT); |
外部キーを追加 | ALTER TABLE | ALTER TABLE hitorigoto ADD CONSTRAINT fk_hitorigoto_user FOREIGN KEY (user_id) REFERENCES users (clerk_id); |
Supabase の「SQL Editor」とは?
Supabase には「SQL Editor」という機能があり、SQL コードを実行できます!
「SQL Editor」の開き方
- Supabase ダッシュボード にログイン
- 「Database」 → 「SQL Editor」 をクリック
- SQL コードを入力して実行できる!
外部キーとは?
- 外部キー(Foreign Key, FK) とは、あるテーブルのカラムを 別のテーブルのカラムと関連付ける仕組み です。
- 外部キーを設定することで、データの整合性が保証されます。
例:post.user_id を users.clerk_id と関連付ける(2つのテーブルのidを繋いでいる)
この関係を作る理由
- post(投稿データ)の user_id が 必ず users テーブルに存在する clerk_id であることを保証
- 不正な user_id のデータが入らないようにする
- ユーザーが削除されたら、その人の投稿も削除されるようにする
Supabase の「SQL Editor」を開いて、以下の手順で SQL を実行!
- Supabase ダッシュボードにログイン
- 「Database」 → 「SQL Editor」 を開く
- 以下の SQL を入力
ALTER TABLE public.post
ADD CONSTRAINT fk_post_user
FOREIGN KEY (user_id)
REFERENCES public.users (clerk_id)
ON DELETE CASCADE;
- 「Run」ボタンをクリック
- これで成功すれば、post.user_id は users.clerk_id に紐づくようになります
この SQL の意味
コマンド | 説明 |
---|---|
ALTER TABLE public.post | post テーブルの定義を変更する |
ADD CONSTRAINT fk_post_user | post テーブルに fk_post_user という外部キー制約を追加 |
FOREIGN KEY (user_id) | post の user_id を外部キーとして設定 |
REFERENCES public.users (clerk_id) | user_id は users テーブルの clerk_id に紐づける |
ON DELETE CASCADE | users.clerk_id のユーザーが削除されたら、関連する post のデータも削除する |
これにより、post.user_id は users.clerk_id に存在するデータしか保存できなくなります。
RLS(Row Level Security)ポリシーを適用
RLS とは?
- Row Level Security(RLS) は、テーブルのデータを特定のユーザーしか操作できないようにする 仕組み。
- Supabase では 「RLS を有効化しないと、誰でもデータを読み書きできる」 ため、必ず RLS を設定する必要がある。
RLS を設定しない場合の問題点
状況 | 問題点 |
---|---|
RLS を設定しない | すべてのユーザーが post の投稿を自由に操作できる |
他のユーザーの投稿を削除可能 | 他のユーザーの投稿を簡単に削除できてしまう |
不正な user_id の投稿ができる | user_id に誰の id でも入力できるため、不正データが入りやすい |
RLS を有効にすることで、ユーザーごとのアクセス制御が可能になる!
SQL で INSERT の RLS ポリシーを設定
投稿を行うときに、ログインしているユーザーだけが hitorigoto に INSERT できるようにします。
CREATE POLICY "Allow Insert for Authenticated Users"
ON public.post
FOR INSERT
TO authenticated
WITH CHECK (
EXISTS (
SELECT 1 FROM users WHERE users.clerk_id = post.user_id
)
);
この SQL の意味
コマンド | 説明 |
---|---|
CREATE POLICY “Allow Insert for Authenticated Users” | 新しい RLS ポリシーを作成(名前: Allow Insert for Authenticated Users) |
ON public.post | post テーブルに適用 |
FOR INSERT | INSERT(データの追加) に適用 |
TO authenticated | 認証済みユーザー(authenticated) のみに適用 |
WITH CHECK (…) | 条件を満たした場合のみ INSERT を許可 |
EXISTS (…) | users.clerk_id に post.user_id が存在する場合のみ許可 |
- この設定により、users.clerk_id に存在しない user_id では INSERT できない!
- Clerk の userId を users.clerk_id に登録しているユーザーだけが投稿できる!
セットアップ完了
これで投稿機能実装の前編が終了です!
今回はSupabaseのセットアップとClerkとの連携を実装しました。
残り2回でこの内容を反映させるコードを書いていきます。
コメント