ShrimpReelとは?
ShrimpReelは、アップロードした1枚の写真を、バイラル形式に基づくAI生成動画へ変換するWebサイトを構築するためのオープンソースSaaSテンプレートです。想定されるワークフローは、トレンドキーワードごとに個別のリポジトリを作成し、サイトの設定と二言語コンテンツを変更してメディアを差し替え、完成したアプリケーションをCloudflareにデプロイするというものです。
このスタックでは、フロントエンドとサーバーサイドレンダリングにTanStack Start、React 19、Tailwind CSS 4を組み合わせています。Hono APIは/api/*配下のルート、メディア配信、robotsディレクティブ、サイトマップ、IndexNowの検証を処理します。サーバーのエントリーポイントはsrc/server.tsです。
このアプリケーションは、Cloudflare Workers、D1、R2、KV、Queues、Rate Limiting、Cron Triggersを中心に設計されています。英語ページは/から配信され、中国語ページは/zh配下で利用できます。
プロジェクトの状況:READMEによると、完全なワークフローはローカルのユニットテストとPlaywrightのエンドツーエンドテストに合格しますが、このテンプレートはまだ本番環境へのデプロイとして検証されていません。実際のサービスとの個別の統合を利用する前に、
ROADMAP.mdを確認してください。
主な機能
アカウント、課金、クレジット
- Google One Tapを含むGoogleサインイン、およびlocalhost専用の開発用ログイン。
- クレジットパックと、任意で選択できる月額または年額サブスクリプション。
- クレジット台帳、引き換えコード、紹介リンク、課金履歴、印刷可能な注文詳細、アカウント削除、データエクスポート。
- デフォルトの決済プロバイダーとしてのWaffo Pancake、または代替プロバイダーとしてのDodo Payments。
- クレジットの自動回収に対応した一部返金および全額返金。
動画生成
- デフォルトの動画プロバイダーとしてのfal.aiキューAPI。
- yir.aiを経由した任意のルーティング。
- ローカル開発とテスト中にテンプレート動画をコピーするモックプロバイダー。
- 生成キュー、デッドレターキュー、生成失敗時のクレジット自動返還。
- 動画ごとにユーザーが有効化できる公開動画共有ページ。
成長、管理、運用
- UTM値と広告クリック識別子を使用した、初回接触および最終接触アトリビューション。
- 訪問から生成までのファネルと、同意を管理したGA4イベント。
- ユーザー、注文、生成、決済イベント、削除依頼、レポート、メール、監査記録、紹介、ランタイム設定、接続テスト用の管理画面。
- プロバイダーコストと粗利益率のレポート。
- メンテナンスモード、お知らせ、1日の生成上限、ヘルスアラート、ブラウザーエラー報告、決済通知。
- D1からR2への毎日のバックアップ。
安全性、保持、SEO
- アップロードのモデレーションと、動画へのAI生成ラベル付与。
- 7日後の写真自動削除と、30日後の動画自動削除。
- 同じ元写真から作成された動画を削除し、その写真をブロックする48時間の削除依頼キュー。
- 問い合わせフォームと報告フォームでのTurnstile対応。
- 正規URL、hreflangメタデータ、JSON-LD、サイトマップ、法務ページ、ガイド、関連記事、コード分割されたローカライズ済みコピー。
npm run seo:checkで利用できるサイト全体のSEOリンター。
前提条件
Node.jsとnpm 11.19以降をインストールしてください。古いnpmバージョンではpackage-lock.jsonが書き換えられ、後で継続的インテグレーションのnpm ciが失敗する形式になる場合があります。
本番環境にデプロイするには、Cloudflareアカウント、決済プロバイダーのアカウント、動画プロバイダーのAPIキー、Google OAuth認証情報も必要です。FFmpegが必要なのは、付属スクリプトでプレースホルダーメディアを再生成する場合だけです。
ShrimpReelをローカルでインストールして実行する
1. 依存関係をインストールしてローカル変数を作成する
npm install
cp .dev.vars.example .dev.vars.dev.varsを開き、少なくともSESSION_SECRETを設定してください。本番環境とステージング環境では、32文字以上の強力な値が必要です。READMEでは、次のコマンドで生成することを推奨しています。
openssl rand -hex 322. ローカルデータベースとメディアストレージを準備する
npm run seed:localこのコマンドはD1マイグレーションを適用し、seed/templates/*.mp4のファイルをローカルでエミュレートされたR2ストレージにアップロードします。
3. 開発サーバーを起動する
npm run dev -- --host 127.0.0.1http://127.0.0.1:3000を開いてください。Windowsでは、127.0.0.1を明示的に使用することで、テストツールがlocalhostをIPv6に解決する場合も回避できます。
開発サーバーを
0.0.0.0で実行したり、インターネットに直接公開したりしないでください。開発用ログイン、モック決済、/api/dev/*は、localhostからの直接リクエスト専用です。
基本的なワークフローを試す
デフォルトのローカル設定では、PAYMENT_PROVIDER=mock、VIDEO_PROVIDER=mock、MODERATION_PROVIDER=mockを使用します。これにより、カードに請求したり、外部動画サービスにジョブを送信したりせずに、プロダクトを試すことができます。
- サインインページを開き、本番環境以外で表示される開発用ログインを使用します。
- クレジットパックを選択します。モックチェックアウトでは、請求を発生させずに決済をシミュレートします。
- 写真をアップロードして生成を開始します。
- モック動画プロバイダーは、AIモデルを呼び出す代わりに、シード済みのテンプレート動画をコピーします。
- ダッシュボードを開き、生成された動画、クレジット台帳、課金記録、共有設定を確認します。
アップロード拒否をシミュレートするには、mockOutcome=rejectを付けてアップロードフォームを送信します。ローカルでTurnstileを無効にする場合は、TURNSTILE_SITE_KEYを空のままにしてください。
現在サインインしているユーザーのメディアについて、保持期間のクリーンアップをテストすることもできます。
POST /api/dev/sweep
Content-Type: application/json
{"days": 8}ローカルのメール配信はシミュレートされます。次のコマンドで送信ボックスを確認できます:
GET /api/dev/emails?to=user@example.com&ref=<order-or-takedown-id>新しいトレンドのサイトを作成する
1. 上流の履歴を保持したままリポジトリをクローンする
git clone https://github.com/qianshuixia/shrimpreel.git moonhop
cd moonhop
git remote rename origin upstream
git remote add origin git@github.com:<owner>/moonhop.git今後のテンプレート更新をマージしたい場合は、GitHubのテンプレートボタンを使用しないでください。その方法で作成したリポジトリは、ソースリポジトリと履歴を共有しません。通常のクローンでupstreamリモートを追加すると、マージベースが保持されます。
2. サイトのスキャフォルダーを実行する
まずドライランを実行して変更案を確認し、その後--writeを追加します:
node scripts/new-site.mjs --keyword "Moon Hop" --domain moonhop.ai --keywords "AI dance video,Moon Hop filter"
node scripts/new-site.mjs --keyword "Moon Hop" --domain moonhop.ai --keywords "AI dance video,Moon Hop filter" --writeスキャフォルダーはsite.ts、wrangler.jsonc内のCloudflareリソース名、パッケージ名を更新します。デプロイ固有の識別子をリセットし、テンプレートのステージング設定を削除します。その後、残りの手作業のチェックリストを出力します。
3. 料金と生成を設定する
src/config/site.tsを編集します。packagesのクレジットパック、subscriptionsEnabledスイッチ、サブスクリプションのplans、利用可能なdurations、video.falModelを確認してください。
サイトで都度購入パックのみを販売する場合は、subscriptionsEnabledをfalseに設定します。パックではanchorPriceCentsを使用して取り消し線付きの比較価格を表示できますが、READMEでは、そのパックが実際に販売された価格を表すべきだと注意しています。新しいサイトでは通常、未設定のままにします。
4. ローカライズされたコンテンツを書き換える
src/content/en.tsとsrc/content/zh.tsのトレンド固有のコピーを置き換えます。最低限、ヒーローセクション、説明、アイデア、FAQ、2つの付属記事を書き換えてください。任意の問題提起ブロックと比較ブロックも書き換えるか、nullに設定します。
既存のテキスト全体でキーワードだけを変更するのは避けてください。テンプレートでは、機械的に複製されたサイトは検索エンジンによって大規模コンテンツの不正利用と見なされる可能性があると明確に警告しています。
記事を追加するには、まずsite.tsのarticlesセクションにメタデータエントリを作成し、次にすべてのロケールに対応するコンテンツキーを追加します。記事は自動的にガイドハブ、サイトマップ、設定済みの関連記事リンクに含まれます。ホームページがリンクしているため、既存のtrendとhowToのエントリは残してください。
5. すべてのプレースホルダーメディアを置き換える
- ソース生成クリップを
seed/templates/に<template.id>-<seconds>s.mp4のパターンで配置します。 - ホームページの動画とポスターを
public/demo/で置き換えます。 public/og.pngとpublic/favicon.svgを置き換えます。- オリジナルまたはライセンス取得済みのデモメディアのみを使用し、帰属情報を
site.examples.*.creditに記録します。
FFmpegが利用可能な場合は、次のコマンドでプロジェクトのオリジナルのプレースホルダーアセットを再生成できます:
node scripts/generate-placeholder-media.mjstemplate.idを変更した後は、seed/templates/から不要になったテンプレートファイルを削除します。
実際のプロバイダーを設定する
ランタイム変数
秘密情報ではない本番変数をwrangler.jsoncに設定します。重要な値には、SITE_URL、APP_ENV=production、PAYMENT_PROVIDER、VIDEO_PROVIDER、MODERATION_PROVIDER、TURNSTILE_SITE_KEY、ADMIN_EMAILS、EMAIL_FROM、商品マッピング、GOOGLE_CLIENT_IDなどがあります。
決済プロバイダーの商品価格が正式な基準となります。サイトに表示する価格は、プロバイダーのダッシュボードと同期させる必要があります。商品マッピングでは、設定済みの各パックまたはプランをプロバイダーの商品IDに関連付けます。
シークレット
選択した連携に応じて、シークレットにはSESSION_SECRET、GOOGLE_CLIENT_SECRET、Waffoの認証情報、Dodoの認証情報、FAL_KEY、任意のYIR_API_KEY、モデレーション用の任意のOPENAI_API_KEY、TURNSTILE_SECRET_KEYなどが含まれます。
個別のシークレットを設定するには:
npx wrangler secret put <NAME>または、本番変数ファイルをコピーして入力し、計画を確認してから、不足しているシークレットを適用します:
cp .dev.vars.example .dev.vars.production
node scripts/sync-secrets.mjs
node scripts/sync-secrets.mjs --apply同期スクリプトはシークレットの値を出力しません。既存のリモートシークレットは、--overwriteを指定しない限り保持されます。
Cloudflareリソースをプロビジョニングする
キーワードサイトごとに個別のリソースセットを作成します。名前はwrangler.jsoncのバインディングと一致させる必要があります。
npx wrangler d1 create <name>
npx wrangler r2 bucket create <name>-media
npx wrangler kv namespace create <name>-kv
npx wrangler queues create <name>-jobs
npx wrangler queues create <name>-jobs-dlq
npm run db:migrate:remote
npx wrangler r2 object put <name>-media/templates/<file>.mp4 --file seed/templates/<file>.mp4 --content-type video/mp4 --remote生成されたD1データベースIDとKVネームスペースIDをwrangler.jsoncにコピーします。各サイトのレート制限用namespace_idも、Cloudflareアカウント内で一意でなければなりません。
プロジェクトで説明されているR2ライフサイクルルールを設定し、アップロードされた写真と生成された動画に7日間および30日間の保持期間を適用します。トランザクションメールを利用するには、送信ドメインもCloudflare Email Serviceに登録する必要があります。
検証とデプロイ
ローカル品質チェックを実行する
npm run typecheck
npm test
npm run test:e2e
npm run seo:checkデプロイ前に、設定ドクターを実行します。
npm run doctor設定ドクターは、環境、ドメイン、選択したプロバイダー、商品マッピング、Cloudflareリソースのバインディング、キュー、Cron設定、必要なシークレット名、未適用のマイグレーション、未解決のTODO(site)マーカーをチェックします。リモートチェックを意図的に利用できない場合は、--offlineを使用します。
デプロイしてスモークテストを実行する
npm run deploy
SMOKE_BASE_URL=https://<domain> npm run test:smokenpm run deployは、最初にデプロイ前のチェックを実行します。デプロイ後、Cloudflareでカスタムドメインを接続し、SITE_URLがsite.domainと完全に一致していることを確認します。正規URL、サイトマップ、同一オリジンのCSRFチェックは、この一致に依存します。
カスタムドメインが機能したら、workers_devとpreview_urlsをfalseに設定します。そうしない場合、本番Workerは、同じD1およびR2リソースを使用する公開Cloudflare開発URLとバージョンURLから引き続きアクセス可能になります。
SEO公開作業を完了する
npm run seo:check -- --base https://<domain> --production
npm run seo:indexnow -- --submitIndexNowコマンドは、site.seo.indexNowKeyを設定した後にのみ実行します。Google Search ConsoleとBing Webmaster Toolsでドメインを確認し、https://<domain>/sitemap.xmlを送信します。
高度なヒント
本番環境にモックを残さない
本番環境とステージング環境では、選択したプロバイダーがmockのままだと、チェックアウト、生成、アップロードが503レスポンスで拒否されます。開発用ログイン、モックのチェックアウトルート、開発用APIエンドポイントは、これらの環境では404を返します。これは安全機構であり、npm run doctorの実行に代わるものではありません。
パッチをコピーせず、テンプレートの更新をマージする
サイト固有の作業は、src/config/site.ts、src/content/*、public/*、seed/、wrangler.jsonc、およびパッケージ名に保持します。共有修正はテンプレートで行い、各サイトにマージします。
git fetch upstream
git show upstream/main:scripts/sync-plan.mjs > .tmp/sync-plan.mjs
node .tmp/sync-plan.mjs
git merge --no-ff upstream/main
npm install
npm run typecheck
npm test
npm run test:e2e
npm run db:migrate:remoteスカッシュマージ、リベース、チェリーピックではなく、マージコミットを使用します。同期計画はgit merge-base HEAD upstream/mainに依存します。マージを記録する際は、コミットメッセージの末尾をTemplate-sync: <template commit sha>にします。
デプロイ中も後方互換性を維持する
マイグレーション実行後にデプロイが失敗した場合、新しいWorkerバージョンはロールバックできますが、D1マイグレーションは自動的に元に戻りません。ロールバックを可能にするため、マイグレーションは以前のアプリケーションバージョンと互換性を保つようにします。
適切な場合は、同梱のClaude Codeワークフローを使用する
このリポジトリには、トレンド固有のサイトをスキャフォールディングするnew-hot-siteスキル、テンプレートの変更をマージするsync-upstreamスキル、公開前および稼働中のチェックを行う読み取り専用のlaunch-auditスキルが含まれています。これらのツールは手動レビューの代わりにはなりません。生成されたコピー、ライセンス済みメディア、ドメイン、プロバイダーの商品、OAuth設定、メールの登録、ライフサイクルポリシーについては、引き続き検証が必要です。
コアロジックを変更する前にプロジェクトドキュメントを確認する
クレジット、決済のフルフィルメント、バイリンガルコンテンツ、マイグレーション、エンドツーエンドテストを変更する前に、AGENTS.mdを確認します。追加の詳細は、docs/env.md、docs/payments.md、docs/subscriptions.md、docs/SEO_AUDIT.md、docs/SAAS_VIDEO_FEATURES.mdにあります。READMEには、これらのドキュメントが現在中国語で書かれていると記載されています。
まとめ
ShrimpReelは、生成キュー、課金、クレジット、管理、保持、コンプライアンスワークフロー、分析、SEO、Cloudflare運用を含む、キーワード重視のAI動画SaaSの実質的な出発点を提供します。安全なモックワークフローから始め、サイト固有の各レイヤーをカスタマイズし、プレースホルダーコンテンツをライセンス済みアセットに置き換え、すべてのプロバイダーとCloudflareの設定を検証してください。完全なテスト、ドクター、SEO、スモークテストの手順に合格してからデプロイします。
