Supabase 初心者向け解説、Supabase CLI インストール(Scoop)
更新日:2025/04/09

Supabaseってなに?
超ざっくり言うと「Firebaseのオープンソース版みたいなもの」です。
サーバーサイドの面倒な処理をノーコード/ローコードで簡単にできるサービスです。
Supabaseは「BaaS(Backend as a Service)」に分類され、バックエンドのサービスを用意してくれます!
主な特徴:
- PostgreSQLベースのリアルタイムなデータベース
- ユーザー認証機能(ログインとか)
- ストレージ(画像とかファイルを保存できる)
- API自動生成(DB作るとREST APIが勝手にできる)
- ローカル開発にも対応(→ Supabase CLI)
PostgreSQLは?
PostgreSQL(ポスグレ)は、世界中で使われている
無料で高機能なデータベースソフトのことです。
ソフト名 | 特徴 |
---|---|
MySQL | 軽くて速い。WordPressや多くのWebサーバーで使われる。 |
PostgreSQL | 高機能で拡張性が高い。Supabaseが使っている。 |
SQLite | 軽量。ファイル1つだけで動く。スマホアプリやテスト用に◎ |
MariaDB | MySQLと互換性あり。オープンソース志向の人に人気。 |
Oracle Database | 商用。大企業・官公庁向けで超高機能。 |
SQL Server | Microsoft製。Windows環境でよく使われる。 |

アカウント作成
メールアドレスで登録、GitHub認証できるようです。

アカウント作成後、ダッシュボードにアクセスできます
ダッシュボードについて
+ New Project で新しくプロジェクトを作成
organization を設定してない場合は作成する必要があります
organizationは会社や個人利用といった組織の設定ですね。
New Projectはプロジェクト名、データベースパスワード、リージョンを選択して作成できます!
プロジェクト作成するとProject API Keysも/settings/apiで確認できるようです
Get started by building out your database
プロジェクトページのウェルカムメッセージの下にデータベースの構築から始めましょうとありますので、まず用意されているSQLをSQLエディタで流してみることで構築を進めてみるとよさそうです、、
下記のDOCSを参考にSQLを実行してみます
https://supabase.com/docs/guides/getting-started/quickstarts/nextjs
-- Create the table
create table instruments (
id bigint primary key generated always as identity,
name text not null
);
-- Insert some sample data into the table
insert into instruments (name)
values
('violin'),
('viola'),
('cello');
alter table instruments enable row level security;
「Table Editor」で作成が確認できました!

Supabase CLI + Scoopについて
Supabase CLIって?
Supabaseをローカルで開発できるようにするコマンドツールです。
例:コマンドでデータベース立ち上げたり、テーブル作ったり、マイグレーションしたりできます。
Scoopって?
Windowsのパッケージ管理ツールです。
macOSでいうHomebrewみたいな感じ。コマンドで簡単にツールをインストールできます。
またScoopは管理者権限不要で個人フォルダにインストールで
C:\Users\<ユーザー名>\app\scoop\にインストールする場合
- 下記は管理者権限で開く必要はありません
cd ~/Downloads
- インストーラーをダウンロード
Invoke-WebRequest -UseBasicParsing get.scoop.sh -OutFile installer.ps1
- インストーラー先を指定して実行
./installer.ps1 -ScoopDir "C:\Users\<ユーザー名>\app\scoop"
>>
Initializing...
Downloading...
Creating shim...
Adding ~\app\scoop\shims to your path.
Scoop was installed successfully!
Type 'scoop help' for instructions.
- インストール成功の確認
scoop config
- Supabaseのバケット(レポジトリ)を登録
scoop bucket add supabase https://github.com/supabase/scoop-bucket.git
>>
Checking repo... OK
The supabase bucket was added successfully.
- Supabase CLI をインストール
scoop install supabase
>>
-----
'supabase' (2.20.12) was installed successfully!
- インストール確認
supabase --version
>>
2.20.12
C:\
└─ Users\
└─ <ユーザー名>\
└─ app\
└─ scoop\ ← Scoop本体のルート
├─ apps\ ← 実際にインストールされたアプリの本体が入る
│ └─ supabase\
│ └─ current\ ← Supabase CLI の実体(実行ファイルなど)
│ ├─ supabase.exe ← CLI本体(ここが実行される)
│ └─ その他ファイル
├─ shims\ ← CLI実行用のショートカット群(Pathに通ってる)
│ └─ supabase.exe ← 実行用の中継ファイル(shim)
├─ cache\ ← 一時ファイル(ZIPなどが入る)
├─ buckets\ ← インストール元(GitHubレポジトリ)情報
└─ persist\ ← 永続的な設定や保存データ(ツールによる)

制作物のおすすめ(Supabase練習向け)
以下はHTML/CSS/JS/PHP/Node.jsスキルを活かせる実践的な練習ネタです:
① ログイン付き掲示板(PHP or Node.js)
- Supabaseの認証機能+DB(投稿内容)
- ログインしてる人だけが書き込みできる
② TODOアプリ(HTML/CSS/JS + Supabase)
- ログイン不要でもOK
- SupabaseのDBを使ってCRUD(登録・編集・削除)
- JSから直接REST API呼ぶだけでも作れる!
③ ファイルアップローダー
- Supabaseのストレージ機能を使って画像などをアップロード
④ お問い合わせフォーム + 管理画面(PHP)
- お問い合わせ内容をSupabaseに保存
- 管理者だけが内容を一覧・返信できるページを作る
⑤ 勉強メモ共有サービス(Node.js + Supabase)
- 自分の学習メモを投稿・保存・公開
- タグ・検索機能もつけるとステップアップ
WordPressから記事取得(Next.js & Supabase)
supabaseで下記の様なテーブルを作成(Supabase CLIかダッシュボードで確認)
supabase login
Hello from Supabase! Press Enter to open browser and login automatically.
Here is your login link in case browser did not open https://supabase.com/dashboard/cli/login?session_id=
Enter your verification code: xxxxxxxx
Token cli created successfully.
You are now logged in. Happy coding!
supabase link --project-ref <project-ref>
//
CREATE TABLE IF NOT EXISTS "public"."posts" (
"id" "uuid" DEFAULT "gen_random_uuid"() NOT NULL,
"title" "text",
"content" "text",
"source_url" "text",
"published_at" timestamp without time zone
);
Supabase に一意制約(UNIQUE制約)を追加する
ALTER TABLE posts
ADD CONSTRAINT unique_source_and_date
UNIQUE (source_url, published_at);
Next.js プロジェクト作成
npx create-next-app@latest wp-supa-search --typescript
Supabase SDK インストール
npm install @supabase/supabase-js
Supabase SDK(@supabase/supabase-js
)ってなに?
Supabase の REST / Realtime / Auth 機能を、JavaScript / TypeScript から簡単に扱えるようにしたクライアントライブラリ!
.env.local(環境変数ファイル)を作成
プロジェクトのダッシュボード「API Settings」から確認
NEXT_PUBLIC_SUPABASE_URL=https://あなたのプロジェクト.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=ここにanonキー
src\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)
src\lib\supabase.tsを作成
// Next.js の App Router で API Route を返すためのレスポンスユーティリティ
import { NextResponse } from 'next/server'
// Supabase クライアントの読み込み
import { supabase } from '@/lib/supabase'
// 取得対象となる WordPress サイトのURLリスト(複数対応)
const WP_SITES = [
'https://yoursite.com/',
'https://yoursite.com/',
'https://yoursite.com/',
]
// WordPress REST API で一度に取得できる最大件数(100件)
const PER_PAGE = 100;
export async function GET() {
const created: string[] = [];
const updated: string[] = [];
const unchanged: string[] = [];
for (const site of WP_SITES) {
let page = 1;
let hasMore = true;
while (hasMore) {
const url = `${site}/wp-json/wp/v2/posts?_embed&per_page=${PER_PAGE}&page=${page}`;
try {
console.log(`🔍 Fetching from: ${url}`);
const res = await fetch(url, {
// ヘッダーに User-Agent を追加してVercelからWordPressにアクセスできるようにする(Bot判定で User-Agent が引っかかってる?)
headers: {
"User-Agent":
"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
},
});
if (!res.ok) {
console.error(`❌ Failed to fetch ${url} → status: ${res.status}`);
break;
}
const posts = await res.json();
console.log(`✅ ${site} page ${page} - ${posts.length} posts fetched`);
if (posts.length === 0) break;
for (const post of posts) {
const { title, content, date, link } = post;
const titleText = title?.rendered || "(no title)";
const contentText = content?.rendered || "";
const publishedAt = new Date(date).toISOString();
const { data: existing } = await supabase
.from("posts")
.select("title, content")
.eq("source_url", link)
.eq("published_at", publishedAt)
.maybeSingle();
if (!existing) {
const { error } = await supabase.from("posts").insert([
{
title: titleText,
content: contentText,
source_url: link,
published_at: publishedAt,
},
]);
if (!error) {
created.push(link);
console.log(`🆕 Created: ${link}`);
}
} else if (
existing.title !== titleText ||
existing.content !== contentText
) {
const { error } = await supabase
.from("posts")
.update({
title: titleText,
content: contentText,
})
.eq("source_url", link)
.eq("published_at", publishedAt);
if (!error) {
updated.push(link);
console.log(`🔄 Updated: ${link}`);
}
} else {
unchanged.push(link);
}
}
page += 1;
hasMore = posts.length === PER_PAGE;
} catch (err) {
console.error(`💥 Exception while fetching ${site}:`, err);
hasMore = false;
}
}
}
console.log(
`✨ Fetch complete - Created: ${created.length}, Updated: ${updated.length}, Unchanged: ${unchanged.length}`
);
return NextResponse.json({
created: created.length,
updated: updated.length,
unchanged: unchanged.length,
details: {
created,
updated,
unchanged,
},
});
}
src\app\page.tsxを作成
"use client";
import { useEffect, useState } from "react";
import { supabase } from "@/lib/supabase";
type Post = {
id: string;
title: string;
content: string;
source_url: string;
published_at: string;
};
const PAGE_SIZE = 10;
export default function Home() {
const [posts, setPosts] = useState<Post[]>([]);
const [total, setTotal] = useState(0);
const [page, setPage] = useState(1);
const [search, setSearch] = useState("");
useEffect(() => {
const fetchPosts = async () => {
const from = (page - 1) * PAGE_SIZE;
const to = from + PAGE_SIZE - 1;
let query = supabase
.from("posts")
.select("*", { count: "exact" })
.order("published_at", { ascending: false })
.range(from, to);
if (search.trim() !== "") {
query = query.or(
`title.ilike.%${search.trim()}%,content.ilike.%${search.trim()}%`
);
}
const { data, error, count } = await query;
if (!error && data) {
setPosts(data);
setTotal(count || 0);
} else {
console.error(error);
}
};
fetchPosts();
}, [page, search]);
const totalPages = Math.ceil(total / PAGE_SIZE);
// WordPress の記事を取得中かどうか
const [loading, setLoading] = useState(false);
const [result, setResult] = useState<null | {
created: string[];
updated: string[];
unchanged: string[];
}>(null);
const fetchPosts = async () => {
setLoading(true);
setResult(null);
try {
const res = await fetch("/api/fetch-posts");
const json = await res.json();
setResult(json.details);
} catch (err) {
console.error("取得エラー:", err);
} finally {
setLoading(false);
}
};
return (
<main
style={{
padding: "2rem",
fontFamily: "sans-serif",
maxWidth: 800,
margin: "auto",
}}
>
<h1>クロスサイト検索ポータル</h1>
<input
type="text"
placeholder="タイトルや本文を検索"
value={search}
onChange={(e) => {
setSearch(e.target.value);
setPage(1);
}}
style={{
padding: "0.75rem",
width: "100%",
marginBottom: "1.5rem",
border: "1px solid #ccc",
borderRadius: "4px",
fontSize: "1rem",
}}
/>
<button
onClick={fetchPosts}
disabled={loading}
style={{
padding: "0.6rem 1.2rem",
backgroundColor: "#0070f3",
color: "#fff",
border: "none",
borderRadius: "4px",
cursor: "pointer",
marginBottom: "1.5rem",
}}
>
{loading ? "取得中..." : "記事を再取得"}
</button>
<p>Vercel上で WordPress API にアクセスできない 403エラー(おそらくCloudflare・WAF・Wordfenceなどの制限)</p>
<p>ローカルではWordPress API の内容 正常に取得できる✅</p>
{result && (
<div style={{ marginBottom: "2rem" }}>
<h3>取得結果</h3>
<p>
<strong>新規:</strong> {result.created.length}件
</p>
<ul>
{result.created.map((url) => (
<li key={url}>
<a href={url} target="_blank">
{url}
</a>
</li>
))}
</ul>
<p>
<strong>更新:</strong> {result.updated.length}件
</p>
<ul>
{result.updated.map((url) => (
<li key={url}>
<a href={url} target="_blank">
{url}
</a>
</li>
))}
</ul>
<p>
<strong>変更なし:</strong> {result.unchanged.length}件
</p>
<ul>
{result.unchanged.map((url) => (
<li key={url}>
<a href={url} target="_blank">
{url}
</a>
</li>
))}
</ul>
</div>
)}
{posts.length === 0 && <p>記事が見つかりませんでした。</p>}
{posts.map((post) => (
<div
key={post.id}
style={{
marginBottom: "1.5rem",
padding: "1rem",
border: "1px solid #ddd",
borderRadius: "6px",
backgroundColor: "#fafafa",
}}
>
<h2 style={{ margin: 0 }}>
<a
href={post.source_url}
target="_blank"
style={{ textDecoration: "none", color: "#0070f3" }}
>
{post.title}
</a>
</h2>
<p style={{ fontSize: "0.85rem", color: "#666" }}>
{new Date(post.published_at).toLocaleDateString()}
</p>
</div>
))}
<div
style={{
marginTop: "2rem",
display: "flex",
flexWrap: "wrap",
columnGap: "calc(10% / 9)",
rowGap: "2px",
}}
>
{Array.from({ length: totalPages }, (_, i) => (
<button
key={i}
onClick={() => setPage(i + 1)}
style={{
padding: "0.5rem 1rem",
backgroundColor: page === i + 1 ? "#333" : "#eee",
color: page === i + 1 ? "#fff" : "#000",
border: "none",
borderRadius: "4px",
cursor: "pointer",
minWidth: "9%",
}}
>
{i + 1}
</button>
))}
</div>
</main>
);
}

-
検索
(例) debug search etc.. -
カテゴリー
-
mixhostでのWordPress利用について
更新日:2024/04/02
299 view
-
scrollHint
更新日:2024/03/13
250 view
-
XML Sitemap Generator for Google不具合のダウングレード対応、代替プラグイン
更新日:2024/06/13
236 view
-
【SnowMonkey】納品までのフローまとめ
更新日:2025/02/15
163 view
-
ワードプレスでフォントを変えたいとき、プラグインを使えば初心者でも簡単
更新日:2025/02/16
144 view
-
【Googleサーチコンソール】検索画面で表示させたくない「Googleのインデックス削除」
更新日:2024/06/07
130 view
-
【Snow Monkey】ショートコードで編集画面で任意の場所にHTMLファイルを挿入
更新日:2025/04/04
125 view
-
キーワード検索で上位表示させる方法【SEO】
更新日:2023/10/28
120 view
-
tailwindcss使い方
更新日:2024/03/13
120 view
-
Recline: GitHub Copilotで動作するClaude 3.5 Sonnet搭載の開発支援ツール
更新日:2025/01/20
111 view
-
WordPressプラグイン「All-in-One WP Migration」のトラブル
更新日:2022/03/31
84 view
-
ワードプレスセキュリティー対策まとめ【2025年】「site guard wordpress」「BackWPup バージョン5でUI変更!?」
更新日:2025/02/25
76 view
-
VSCodeで開発効率を劇的に向上させる!Roo Code(Roo-Cline)プラグイン完全ガイド
更新日:2025/04/06
55 view
-
SSHを使用してGitHubのリポジトリをクローン、複数の接続元で公開鍵をディレクトリで区別する方法
更新日:2025/01/13
47 view
-
Express、FastAPIを使用し、二重fetch構成のメリット
更新日:2025/03/28
41 view
-
「JSONスキーマ」と「Few-shot Learning」で実現する次世代生成AIソフトウェア開発の可能性
更新日:2025/02/12
40 view
-
WordPressの無料画像素材のおすすめダウンロードサイト!
更新日:2022/02/22
35 view
-
リファクタリング【VSCode Javasctipt Python】
更新日:2025/03/09
35 view
-
形態素解析とは?初心者でもわかるツールの使い方と実践例
更新日:2025/02/08
33 view
-
【Next.js AWS】音声文字起こし&要約、分析アプリケーション(S3)(Transcribe)(Amazon Bedrock)
更新日:2025/02/13
30 view