配信者・コミュニティ向けリアルタイム・ビンゴ大会ウェブアプリケーション
- Next.js (App Router, React)
- Tailwind CSS (CSS-first configuration)
- Supabase (Database, Realtime, Authentication)
- OAuth (Google, Twitch)
- Zod (Validation)
- pnpm (Package Manager)
Bingifyは Supabase Auth を使用した認証システムを実装しています。
- 認証方法: OAuth (Google、Twitch)
- 認証が必須の機能:
- スペースの作成・管理 (
/dashboard/*) - ビンゴカードの表示・参加 (
/spaces/*,/@<share_key>) - 管理者機能 (
/admin/*) - 認証不要の機能:
- 表示専用画面 (
/screen/[token]) - ストリーミング配信用
OAuthプロバイダーの設定は、Supabase DashboardのAuthentication > Providersから行います。
pnpm install環境変数の設定には、以下の3つの方法があります:
Supabaseローカルインスタンスから自動的に設定を取得します:
# Supabaseを起動
pnpm supabase:start
# 環境変数を自動生成
pnpm dev:envこのコマンドは以下を自動実行します:
- Supabaseインスタンスからキーを取得
- ランダムなシークレットキーの自動生成
- 既存の
.envの値を保持
対話形式で環境変数を設定できるスクリプトを用意しています:
pnpm env:generateこのスクリプトは以下の機能を提供します:
- 必須項目の対話的な入力
- ランダムなシークレットキーの自動生成
- 既存の
.envがある場合の値の保持 - 入力値のバリデーション
非対話モード(CI/CD環境向け):
pnpm env:generate --non-interactive強制上書きモード:
pnpm env:generate --force.env.example をコピーして、Supabaseの接続情報を手動で設定します:
cp .env.example .env# Supabaseローカルインスタンスを起動
pnpm local:setup
# 開発サーバーを起動
pnpm devアプリケーションは http://localhost:3000 で起動します。
pnpm local:stopBingifyは複数のデプロイ方法をサポートしています。
VercelはNext.jsアプリケーションに最適化されたホスティングプラットフォームです。自動スケーリング、グローバルCDN、プレビューデプロイなど、強力な機能を提供します。
詳細なデプロイガイド: docs/VERCEL_DEPLOY.md
クイックスタート:
- Bingify GitHubリポジトリ をフォーク
- Vercel Dashboard でリポジトリをインポート
- 環境変数を設定
- デプロイを実行
Dockerコンテナでのデプロイもサポートしています。
docker build -t bingify:latest .docker run -d \
--name bingify \
-p 3000:3000 \
-e NEXT_PUBLIC_SUPABASE_URL=your_supabase_url \
-e NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key \
-e SUPABASE_SERVICE_ROLE_KEY=your_service_role_key \
bingify:latestまたは、環境変数ファイルを使用:
docker run -d \
--name bingify \
-p 3000:3000 \
--env-file .env.production \
bingify:latestその他のデプロイ方法: Docker、VPS、クラウドサーバーなどのセルフホスティングについては、docs/SELF_HOSTED.md を参照してください。
- マルチステージビルド: 最適化された小さなイメージサイズ
- Node.js 24 Alpine: 軽量なベースイメージ
- 非 root ユーザー: セキュリティのための専用ユーザー (UID: 1001)
- ヘルスチェック: コンテナの健全性を自動監視
最低限必要な環境変数:
NEXT_PUBLIC_SUPABASE_URL: SupabaseプロジェクトのURLNEXT_PUBLIC_SUPABASE_ANON_KEY: Supabaseの匿名キーSUPABASE_SERVICE_ROLE_KEY: Supabaseのサービスロールキー
その他のオプション環境変数については、.env.example を参照してください。
- 管理画面 (
/dashboard) でビンゴスペースを作成 - 認証必須: OAuth (Google、Twitch) によるログインが必要
- 共有キー形式:
[ユーザー入力]-[日付YYYYMMDD](例:my-party-20251224) - リアルタイムで重複チェック
- 公開URL:
/@<share_key> - 認証必須: アクセスには認証が必要
- Supabaseの
share_keyでUUIDを検索 /spaces/<uuid>に内部rewrite (URLは/@<share_key>のまま表示)
/dashboard/spaces/<uuid>: スペース管理・ビンゴ抽選実行- 認証必須: スペース所有者のみアクセス可能
- リアルタイム同期
/spaces/<uuid>または/@<share_key>: ビンゴカード表示- 認証必須: 認証されたユーザーのみアクセス可能
- Supabase Realtimeでリアルタイム同期
/screen/[token]:view_tokenを使用した公開表示画面- 認証不要: ストリーミング配信などで使用する表示専用画面
- リアルタイムで抽選結果を表示
動的ルートのパラメータは必ず await してください。
export default async function Page({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
// ...
}app/
├── dashboard/
│ ├── spaces/[id]/page.tsx
│ ├── actions.ts
│ └── page.tsx
├── spaces/[id]/page.tsx
├── globals.css
└── layout.tsx
lib/
├── supabase/
│ ├── server.ts
│ └── client.ts
├── schemas/
│ └── space.ts
└── utils.ts
pnpm dev— 開発サーバー起動pnpm build— 本番ビルドpnpm local:setup— Supabaseローカルインスタンス起動pnpm local:stop— Supabaseローカルインスタンス停止pnpm supabase:test— データベーステスト実行 (PgTAP)pnpm supabase:typegen— Supabaseの型定義を生成 (DB変更後に実行)pnpm lint— コードチェック (Ultracite)pnpm lint:docs— ドキュメントチェック (textlint) - 詳細pnpm test— フロントエンドテスト実行 (Vitest)
Bingifyでは PgTAP を使用してデータベース層のテストを実施しています。これにより、RLS (Row Level Security) ポリシーやスキーマ定義が意図通りに動作することを検証できます。
# Supabaseローカルインスタンスを起動
pnpm local:setup
# データベーステストを実行
pnpm supabase:testテストファイルは supabase/tests/database/ ディレクトリに配置されています:
01_schema.sql— スキーマ定義のテスト (テーブル、カラム、外部キー制約)02_rls_security.sql— RLSポリシーのテスト (権限とセキュリティ)
新しいデータベーステストを追加する場合は、supabase/tests/database/ ディレクトリに .sql ファイルを作成してください。PgTAPの関数を使用してテストを記述します。詳細は PgTAPドキュメント を参照してください。
ローカル開発時は .env.example に記載されている値を参照してください。本番環境ではSupabase Cloudを使用します。
supabase/migrations ディレクトリ配下の .sql マイグレーションファイルは、main ブランチへのマージ時に自動的にCloud Supabaseへデプロイされます。
- 既に適用済みのマイグレーションファイル (mainブランチに存在するファイル) は絶対に編集しないでください
- Supabaseは一度適用されたマイグレーションを再実行しないため、既存ファイルの編集は新規環境にのみ反映され、環境間の不整合を引き起こします
- 変更が必要な場合は、必ず新しいマイグレーションファイルを作成してください (詳細は docs/MIGRATIONS.md を参照)
- マイグレーションファイルをリポジトリから削除しても、Cloud Supabaseに適用済みのマイグレーションは削除されません
- ロールバックが必要な場合は、新しいマイグレーションファイルで明示的にロールバックSQLを記述してください
動作フロー:
supabase/migrations/**/*.sqlに変更を含むPRを作成- PRがレビュー・承認される
mainブランチへマージ- GitHub Actionsが自動的にマイグレーションをCloud Supabaseに適用
- デプロイ前後の検証ステップで安全性を確保
必要な GitHub Secrets:
SUPABASE_ACCESS_TOKEN— SupabaseのPersonal Access Token (Settings > Access Tokens から取得)SUPABASE_PROJECT_ID— SupabaseプロジェクトのProject Reference ID (プロジェクト設定から確認可能)
緊急時や特定の環境へのデプロイが必要な場合は、GitHub Actionsの workflow_dispatch から手動実行できます。
- GitHubリポジトリの Actions タブを開く
- Deploy Migrations ワークフローを選択
- Run workflow をクリックし、デプロイ先の環境を選択
# ローカルSupabaseインスタンスにマイグレーションを適用
pnpm local:setup
# 新しいマイグレーションファイルを作成
supabase migration new <migration_name>マイグレーションが失敗した場合:
- GitHub Actionsのログで詳細なエラーメッセージを確認
- マイグレーションファイルのSQL構文を確認
- Supabase Dashboardで現在のデータベーススキーマを確認
- 必要に応じて、手動でロールバックSQLを実行
ロールバックが必要な場合:
マイグレーションの自動ロールバックは実装されていません。問題が発生した場合は、以下の手順で手動対応してください:
- Supabase DashboardのSQL Editorを開く
- 問題のあるマイグレーションを元に戻すSQLを実行
- 修正内容を新しいマイグレーションファイルとして作成し、PRを作成 (
⚠️ 既存ファイルは編集しない)
SupabaseのデータベーススキーマからTypeScriptの型定義を自動生成できます。
データベースのスキーマを変更した後は、以下のコマンドで型定義を更新してください:
pnpm supabase:typegenこのコマンドは types/supabase.ts に最新の型定義を生成します。
重要:
- ローカルのSupabaseインスタンスが起動している必要があります (
pnpm local:setup) - 生成された型定義ファイルはGit管理対象となります
- DBスキーマ変更後は必ず型定義を更新し、コミットに含めてください
import type { Database, Tables } from "@/types/supabase";
// テーブルの Row 型を取得
type Space = Tables<"spaces">;
type BingoCard = Tables<"bingo_cards">;
// Database 型を使用して Supabaseクライアントを型付け
import { createClient } from "@supabase/supabase-js";
const supabase = createClient<Database>(url, key);