取り組みの背景:なぜ EdTech アプリなのか
教育・学習市場(EdTech)は世界規模で急成長しており、2026年時点で市場規模は約6,000億ドルを超えると予測されています。英会話・プログラミング・資格対策・趣味のスキルアップなど、学習系アプリはリテンション率が高く、サブスクリプション収益モデルとの相性も抜群です。
ここではRork Max を使って本格的な EdTech 学習アプリをゼロから構築する上級チュートリアルを提供します。Supabase をバックエンドに使ったコース管理と進捗トラッキング、Stripe によるコンテンツペイウォール、オフライン対応のアーキテクチャ設計まで、実際のアプリをリリースするために必要な知識を網羅します。
この記事で構築するアプリの機能:
- ユーザー認証(メール+ソーシャル)
- コース一覧・詳細・レッスン画面
- 動画・テキスト・クイズのレッスン形式
- レッスンごとの進捗トラッキング&完了率表示
- Stripe によるコースアクセス制御(サブスクリプション or 買い切り)
- オフライン時のコンテンツキャッシュ
- プッシュ通知(学習リマインダー)
対象読者: Rork の基本操作に慣れており、Supabase や Stripe の概念を理解している方。上級レベルの実装に挑戦したい個人開発者・エンジニア向けです。
前提知識・環境準備
必要なツールとアカウント
- Rork Max プラン($200/月): Swift ネイティブビルドと高度な AI 生成機能を使用するため必須
- Supabase アカウント(無料プランで開始可能): データベース・認証・リアルタイム機能
- Stripe アカウント(テストモード): 課金フロー実装
- Apple Developer Program($99/年): App Store 公開時に必要
アーキテクチャ概要
今回構築するアプリの技術スタック:
フロントエンド: Rork Max (SwiftUI / ネイティブ Swift)
バックエンド: Supabase (PostgreSQL + Edge Functions)
認証: Supabase Auth (メール + Apple Sign In)
決済: Stripe (サブスクリプション + 買い切り)
メディア: Supabase Storage (動画・画像)
通知: APNs (Apple Push Notification service)
Rork Max がネイティブ Swift コードを生成するため、SwiftUI の @State、@StateObject、ObservableObject などのパターンがそのまま活用できます。AI への指示(プロンプト)をうまく設計することで、複雑なデータバインディングや非同期処理も自動生成できます。
概念と設計思想:EdTech アプリのアーキテクチャ
データモデル設計
Supabase のデータベーススキーマを先に設計することで、Rork Max への指示が明確になります。以下が基本スキーマです:
-- コーステーブル
CREATE TABLE courses (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
title TEXT NOT NULL,
description TEXT,
thumbnail_url TEXT,
category TEXT NOT NULL,
level TEXT CHECK (level IN ('beginner', 'intermediate', 'advanced')),
price_type TEXT CHECK (price_type IN ('free', 'subscription', 'one_time')),
stripe_price_id TEXT, -- Stripe の Price ID
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- レッスンテーブル
CREATE TABLE lessons (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
course_id UUID REFERENCES courses(id) ON DELETE CASCADE,
title TEXT NOT NULL,
content_type TEXT CHECK (content_type IN ('video', 'text', 'quiz')),
content_url TEXT, -- Supabase Storage の URL
duration_seconds INTEGER,
order_index INTEGER NOT NULL,
is_preview BOOLEAN DEFAULT FALSE -- 無料プレビュー可能なレッスン
);
-- 進捗管理テーブル
CREATE TABLE user_progress (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
lesson_id UUID REFERENCES lessons(id) ON DELETE CASCADE,
course_id UUID REFERENCES courses(id) ON DELETE CASCADE,
completed BOOLEAN DEFAULT FALSE,
progress_seconds INTEGER DEFAULT 0, -- 動画視聴位置
completed_at TIMESTAMPTZ,
UNIQUE(user_id, lesson_id)
);
-- ユーザーのコース購入/サブスクリプション管理
CREATE TABLE user_course_access (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
course_id UUID REFERENCES courses(id) ON DELETE CASCADE,
access_type TEXT CHECK (access_type IN ('free', 'subscription', 'purchased')),
stripe_subscription_id TEXT,
expires_at TIMESTAMPTZ, -- サブスクリプション有効期限
created_at TIMESTAMPTZ DEFAULT NOW()
);Row Level Security (RLS) の設定も忘れずに:
-- ユーザーは自分の進捗のみ読み書き可能
ALTER TABLE user_progress ENABLE ROW LEVEL SECURITY;
CREATE POLICY "user_progress_self_access" ON user_progress
FOR ALL USING (auth.uid() = user_id);
-- コースアクセス権限チェック
ALTER TABLE user_course_access ENABLE ROW LEVEL SECURITY;
CREATE POLICY "course_access_self" ON user_course_access
FOR SELECT USING (auth.uid() = user_id);RLS により、ユーザーが他人の進捗データにアクセスすることを完全に防ぎます。詳細な認証設定については Firebase・Supabase 認証完全ガイド を参照してください。
ステップバイステップ実装
Step 1: コース一覧画面の構築
Rork Max のプロンプトで以下を指示します:
コース一覧画面を作成してください。
要件:
- 縦スクロールのグリッドレイアウト(2カラム)
- 各コースカードにはサムネイル画像、タイトル、カテゴリバッジ、
レベル(初級/中級/上級)、レッスン数、価格タイプ(無料/有料)を表示
- カテゴリフィルターをトップに配置(全て/プログラミング/言語/デザイン/ビジネス)
- Supabase の courses テーブルからデータをフェッチ(AsyncImage 使用)
- ロード中はスケルトンUIを表示
- コースタップ時にコース詳細画面に遷移
Supabase のテーブル名: courses
カラム: id, title, description, thumbnail_url, category, level, price_type
期待される生成結果: SwiftUI の LazyVGrid、AsyncImage、Supabase クライアントとの統合、カテゴリフィルター用の @State 変数、スケルトンローディングアニメーションが自動生成されます。
Step 2: レッスン詳細・再生画面
コース詳細画面を作成してください。
画面構成:
1. ヘッダー: サムネイル(背景)、タイトル、説明文、進捗バー(全体の完了率%)
2. レッスンリスト: セクション別レッスン一覧、各レッスンに完了チェックマーク表示
3. アクセス制御: user_course_access テーブルをチェックし、有料コースで未購入の場合は
ロックアイコンを表示してペイウォールシートを表示
4. 動画レッスンタップ時: AVPlayer を使ったフルスクリーン再生、視聴位置を
user_progress テーブルの progress_seconds に30秒ごとに自動保存
5. テキストレッスン: ScrollView でリッチテキスト表示(Markdown 対応)
6. クイズレッスン: 選択肢式のクイズ画面、回答後に正解/不正解をアニメーションで表示
完了ボタンタップ時: user_progress の completed を true に更新し、
Supabase Realtime でコース全体の進捗率を即座に更新する
ポイント: AVPlayer を使った動画再生と進捗自動保存は、Rork Max の ネイティブ Swift 生成機能があるからこそ実現できる機能です。React Native(通常の Rork)では追加ライブラリが必要ですが、Rork Max ではネイティブ API を直接使えます。
Step 3: Stripe 課金フローの統合
Stripe との連携は Edge Functions を経由して行います。まず Supabase Edge Function を作成:
// supabase/functions/create-checkout/index.ts
import Stripe from "https://esm.sh/stripe@14.0.0";
const stripe = new Stripe(Deno.env.get("STRIPE_SECRET_KEY")!, {
apiVersion: "2024-06-20",
});
Deno.serve(async (req) => {
const { courseId, priceId, userId, accessType } = await req.json();
const session = await stripe.checkout.sessions.create({
mode: accessType === "subscription" ? "subscription" : "payment",
line_items: [{ price: priceId, quantity: 1 }],
success_url: `rorklab://purchase-success?courseId=${courseId}&sessionId={CHECKOUT_SESSION_ID}`,
cancel_url: `rorklab://purchase-cancel`,
metadata: { courseId, userId, accessType },
client_reference_id: userId,
});
return new Response(JSON.stringify({ url: session.url }), {
headers: { "Content-Type": "application/json" },
});
});Rork Max に対してペイウォール画面を指示:
購入画面(ペイウォールシート)を作成してください。
要件:
- ボトムシートとして表示
- コース名と概要を表示
- 購入オプション:
Option A: 月額サブスクリプション ¥980/月(全コース見放題)
Option B: 買い切り ¥4,980(このコースのみ)
- 購入ボタンタップ時: Supabase Edge Function "create-checkout" を呼び出して
Stripe Checkout URL を取得し、SafariViewController で開く
- ディープリンク "rorklab://purchase-success" を受け取ったら
user_course_access テーブルに購入記録を追加してアクセスを有効化
- Apple Pay オプションも表示(Stripe PaymentSheet 使用)
Stripe の詳細な実装については Rork Max × Stripe サブスクリプション実装ガイド も参考にしてください。
Step 4: 進捗トラッキングとダッシュボード
学習アプリにおいてモチベーション維持は最重要課題です。ダッシュボード画面で学習の可視化を実装します:
ホームダッシュボード画面を作成してください。
セクション構成:
1. 今日の学習目標: 目標時間 vs 今日の学習時間(円グラフ)
2. 継続日数ストリーク: 連続学習日数をカレンダー風に表示
(Firebase Realtime DB ではなく Supabase RPC で計算)
3. 学習中のコース: 進捗バー付きで最大3件表示
4. おすすめコース: カテゴリベースのレコメンデーション
5. 週間学習グラフ: 過去7日間の学習時間をバーチャートで表示
データ取得:
- user_progress テーブルから今日の完了レッスン数と学習時間を集計
- 連続学習日数は SQL の DATE 関数と Supabase RPC で計算
- SwiftUI Charts フレームワーク(iOS 16+)を使ってグラフ表示
状態管理のアーキテクチャについては Rork Max 状態管理ガイド を参照すると、より効率的な実装が可能です。
応用パターン:オフライン対応と AI 連携
オフラインダウンロード機能
学習アプリでは「電車内でも学習できる」オフライン対応が競合との差別化ポイントになります:
レッスンのオフラインダウンロード機能を実装してください。
要件:
- レッスン詳細画面に「ダウンロード」ボタンを追加
- タップで Supabase Storage から動画ファイルを URLSession でダウンロード
- ダウンロード進捗をプログレスバーで表示
- ダウンロード済みファイルは Documents ディレクトリに保存
- アプリ起動時にローカルキャッシュを確認し、あればネットワーク不要で再生
- ストレージ使用量の表示と一括削除オプション
- CoreData または SwiftData で「ダウンロード済みレッスン」一覧を管理
オフラインアーキテクチャの詳細設計については オフラインファーストアーキテクチャガイド も合わせて確認してください。
AI パーソナライズ機能(Rork Max × Core ML)
上級者向けの差別化機能として、AI によるパーソナライズ推薦を実装します:
AI パーソナライズ推薦システムを追加してください。
実装内容:
- ユーザーの学習履歴(完了コース・視聴時間・クイズスコア)を分析
- Create ML で学習した推薦モデル(.mlmodel)をアプリに組み込み
- 「あなたへのおすすめ」セクションでパーソナライズされたコースを表示
- フォールバック: Core ML モデルがない場合はカテゴリベースのルールで推薦
オンデバイス推論なのでユーザーのデータはサーバーに送信不要
プライバシー設定画面に「学習データを元にした推薦」のオン/オフスイッチを追加
トラブルシューティング
よくある問題と解決策
問題1: Supabase RLS でデータが取得できない
- Row Level Security が有効なテーブルに未認証でアクセスしていないか確認
- Supabase のダッシュボードで「Authentication → Users」にユーザーが作成されているか確認
- クエリに
.auth.uid()が正しく評価されているかログで確認
問題2: Stripe Webhook が届かない
- Supabase Edge Function の URL が Stripe Dashboard の Webhook エンドポイントに設定されているか確認
- ローカルテスト時は
stripe listen --forward-toでローカル転送を使用 - 署名検証(
Stripe-Signatureヘッダー)を忘れずに実装
問題3: AVPlayer で動画が再生されない
- Supabase Storage の動画 URL に署名付きトークン(Signed URL)が必要か確認
Info.plistのNSAppTransportSecurity設定を確認(HTTP URL の場合)- Rork Max に「AVPlayer での動画再生エラーのデバッグ」を指示して自動修正させる
問題4: プッシュ通知が届かない
- Apple Developer Program の APNs キーが Supabase に登録されているか確認
- デバイストークンの更新処理(アプリ起動時)が実装されているか確認
- シミュレーターではプッシュ通知は受信できないため実機テストが必須
公開・収益化のポイント
App Store 審査を通過するための注意点
EdTech アプリは以下の点で審査が厳しくなる場合があります:
1. ペイウォールの表示タイミング
App Store ガイドラインでは、アプリを「十分に体験」する前に課金を強制することを禁じています。必ず複数のレッスンを無料プレビューとして提供し、価値を体験させてから購入を促す設計にしましょう。is_preview フラグを活用して最初の2〜3レッスンを無料開放することを推奨します。
2. サブスクリプションの明示 サブスクリプション課金を含む場合、必ず課金額・更新頻度・キャンセル方法を購入画面に明記する必要があります。Rork Max にペイウォール画面を生成させる際に「サブスクリプションの詳細条件と解約方法を明示したテキストを追加」と指示してください。
3. 教育コンテンツのコンプライアンス 子ども向け(17歳以下)のコンテンツを含む場合は COPPA(米国)や各国の児童向けプライバシー法への対応が必要です。ターゲットユーザーを明確にし、年齢制限を適切に設定してください。
収益化モデルの選択
| モデル | メリット | デメリット | おすすめシーン |
|---|---|---|---|
| 月額サブスク | 安定した継続収益、MRR 予測可能 | 解約率(チャーン)管理が必要 | コンテンツが継続的に追加される場合 |
| 買い切り | ユーザー心理的ハードル低い | 月次収益が不安定 | 単発コース・資格対策 |
| フリーミアム | 集客しやすい | 課金転換率の最適化が重要 | まず認知度を上げたい場合 |
| コース別課金 | 高単価コースで収益最大化 | 管理が複雑 | 専門性の高いコンテンツ |
収益化戦略の詳細は Rork Max 収益化完全ガイド を参照してください。
まとめ
ここではRork Max を使って本格的な EdTech 学習アプリを構築するための完全な実装ガイドを提供しました。
実装した主要機能:
- Supabase によるコース・レッスン・進捗管理(RLS 付き)
- Stripe によるサブスクリプション+買い切りのハイブリッド課金モデル
- AVPlayer を使ったネイティブ動画再生と視聴位置の自動保存
- SwiftData によるオフラインダウンロードとキャッシュ管理
- Core ML を使った AI パーソナライズ推薦
EdTech 市場への参入障壁は技術よりもコンテンツの質とニッチ選定にあります。Rork Max を使えば開発コストを最小化できるため、残りのリソースをコンテンツ制作とマーケティングに集中させることができます。まずは特定のニッチ(例: TOEIC 900点対策、React 入門 for デザイナーなど)から小さく始め、ユーザーの反応を見ながら拡張していくアプローチを推奨します。