day3 について
Day3は、小規模なSaaSチーム向けのメールサービスで、キャンペーンとトランザクションメール、配信状況の追跡をまとめています。MCPエンドポイントを通じて、コーディングツールからDay3に編集可能なブロック形式でキャンペーンを作成できます。
主な機能
- 01キャンペーン作成とブロックエディター
- 02予約送信と送信ごとの統計
- 03オーディエンスのセグメントとCSVインポート
- 04配信状況付きトランザクションメール
- 05メール自動化と配信指標
活用シーン
- 01コーディングツールからキャンペーンを作成
- 02製品更新や変更履歴を準備
- 03領収書などのトランザクションメールを送信
- 04配信状況とエンゲージメントを追跡
MCP 対応
MCPエンドポイントにより、Claude Code、Cursor、VS Codeからキャンペーンを作成し、編集可能なブロックとしてDay3に追加できます。
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://go.day3.app/api/mcpclaude mcp add --transport http mopra-day3 https://go.day3.app/api/mcp{"mcpServers":{"mopra-day3":{"type":"http","url":"https://go.day3.app/api/mcp"}}}Cursor で開く{"servers":{"mopra-day3":{"type":"http","url":"https://go.day3.app/api/mcp"}}}VS Code で開く{"mcpServers":{"mopra-day3":{"type":"http","url":"https://go.day3.app/api/mcp"}}}{"mcpServers":{"mopra-day3":{"serverUrl":"https://go.day3.app/api/mcp"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
https://go.day3.app/api/mcp認証が必要ツール
詳細
Day3
マーケティングメールとトランザクションメールを、送信数に応じて課金します。月額 $1。連絡先への課金も、習得が必要なマーケティングスイートもありません。
ソース公開型であり、オープンソースではありません。 このコードは透明性と参考のために公開されています。利用条件についてはLICENSEをご覧ください。
このリポジトリはDay3のプロダクトそのものです。go.day3.appのアプリ、公開REST API、WebhookおよびMCPエンドポイント、メールを送信するワーカーが含まれています。
できること
Day3は、小規模なSaaSチーム向けに意図的に機能を絞ったメールツールです。1つの検証済みドメイン、1つの月間利用枠、配信状況を確認できる1つの場所を通じて、ユーザーにプロダクトの更新情報や変更履歴を送り、アプリのトランザクションメール(パスワードリセット、領収書、マジックリンク)も送信できます。
- ブロック形式の作成画面、任意で利用できるAIアシスト、スケジュール設定、送信ごとの統計を備えたキャンペーン
- セグメント(保存済みフィルター)、トピック(購読カテゴリ)、CSVインポート、ホスト型登録フォームを備えたオーディエンス
POST /v1/emails経由のトランザクションメール。形式はResendと互換性があり、メールごとの配信状況を確認できます- オートメーション:オンボーディングやライフサイクルのフローをノードキャンバスで作成し、不変のバージョンとして公開できます。すべてのプランで無制限に利用できます
- 標準搭載の配信到達性対策:送信ドメインの検証、ダブルオプトイン、ワンクリック登録解除、バウンスと苦情の自動抑制、評判が悪化した場合のアカウント自動一時停止
- 配信到達性、評判、エンゲージメントのメトリクスに加え、これまでに送信したすべてのメールの検索可能なログ
- 公開API v1、署名付きWebhook、MCP サーバーを備えており、Claude Code、Cursor、VS Codeからキャンペーンの下書きを作成すると、編集可能なブロックとしてDay3に取り込めます
- 課金対象は購読者ではなく送信数です。 無料アカウントでは、ドメインを設定し、オーディエンスを作成し、サンドボックスモードで実際にメールを送信できます。有料プランでは、ほかのすべての宛先に送信するための利用枠を購入できます。
PRODUCT.mdには、Day3の概要、料金、各機能の動作について、正式な説明が記載されています。コードを読む前にご覧ください。
技術スタック
| レイヤー | テクノロジー |
|---|---|
| Webフレームワーク | Vercel上のNext.js 16(App Router) |
| UI | React 19、Tailwind CSS 4、Base UI上のshadcn/ui、react-hook-form、Zod |
| リッチテキスト | TipTap |
| データベース | Drizzle ORMとpostgres.jsドライバーを使用したPostgres(Supabase) |
| キュー/ジョブ | BullMQ + Redis(ioredis)。VPSワーカーが処理します |
| メール | 送信にはAWS SES v2(eu-north-1)、配信イベントにはAWS SNS |
| 認証/テナント管理/課金 | Clerk(Organizationsがテナントの境界となり、Clerk Billingも使用) |
| ファイルストレージ | Supabase Storage(CSVインポート) |
| AI(任意) | Vercel AI SDK経由のOpenRouter |
| MCP サーバー | /api/mcpでStreamable HTTP上に手書きのJSON-RPCを実装。ステートレスでツールのみ |
| DNS自動化 | SESレコードの自動設定に使用するCloudflare OAuth(任意) |
| テスト | Vitestとpgliteを使用。テストごとにインメモリPostgresを起動 |
クイックリンク
| Webサイト | day3.app:Day3の概要、料金、その特長 | リポジトリ |
| アプリ | go.day3.app:サインイン、キャンペーンの作成、メールの送信 | リポジトリ |
| ドキュメント | docs.day3.app:APIリファレンス、ガイド、Webhook、MCP | リポジトリ |
Pradsgaard Labsが開発しています。同じ開発元のプロジェクトには、稼働状況監視ツールのexit1.devもあります。
ローカル開発
npm install
# Env: web tier + worker (see "Required environment variables" below)
cp .env.example .env.local
cp .env.worker.example .env.worker
# Database
npm run db:migrate # forward-only, applies un-applied journal entries
npm run db:seed # optional sample data
npm run dev # Next.js on http://localhost:3000
npm run worker # BullMQ worker, in a second terminal
Clerk にサインインして組織を作成すると、テナントが作成されます。キャンペーンのパイプライン(レビュー、宛先の生成、バッチキュー送信、統計)はローカルでエンドツーエンドに動作します。
便利なコマンド:
npm test:実際の Postgres(pglite)に対して Vitest を実行します。毎回、最初からマイグレーションを適用し、スキーマ、ジャーナル、スナップショットが一致することを検証します。冪等性テストもここに含まれています。npm run typecheck/npm run lint/npm run buildnpm run db:generate:スキーマ変更後に新しい Drizzle マイグレーションを生成しますnpm run db:studio:ローカルデータベースを閲覧します
マイグレーションの運用ルール
src/db/schema.ts を唯一の信頼できる情報源とします。migrations/ 以下の SQL は前方のみに適用され、生成されたものであり、手動で編集してはいけません。ジャーナル(migrations/meta/_journal.json)とマイグレーションごとの *_snapshot.json ファイルもマイグレーションの一部なので、必ずまとめてコミットしてください。
スキーマを変更する場合のワークフロー:
src/db/schema.tsを編集します。npm run db:generateを実行すると、次のNNNN_*.sql、そのスナップショット、ジャーナルエントリーが生成されます。- SQL を確認します(差分が煩雑な場合は、同じ PR 内で統合するか名前を変更します)。その後、SQL と
meta/の変更を1つのコミットにまとめます。 npm testで、最初から正常に適用できることを確認します。
CI ではこれを強制しています。drizzle-kit generate を再実行し、差分が生じた場合はビルドを失敗させます。これは、schema.ts とコミット済みのマイグレーションに食い違いがあるか、スナップショットなしでマイグレーションが追加されたことを意味します。2人のコントリビューターがそれぞれマイグレーションを生成すると、次の NNNN インデックスが衝突します。マージ済みの schema.ts から一方を再生成して解決し、ジャーナルの連続性を保ってください。
本番環境での適用順序は drizzle-kit migrate(デプロイチェックリストを参照)です。未適用のジャーナルエントリーのみを DATABASE_URL に対して適用し、__drizzle_migrations テーブルに記録します。ライブ環境との差分を取り、カラムを削除する可能性がある db:push は絶対に使用しないでください。
必須の環境変数
両方のプロセスは起動時に環境を検証し(src/lib/env.ts)、必須変数が欠落している場合、またはシークレットが短すぎる場合(最小16文字)には起動を拒否します。これにより、未設定の UNSUBSCRIBE_SECRET が "" で HMAC トークンに署名してしまう(偽造可能な配信停止リンクやワンクリックリンクが生成される)状況や、未設定の OAUTH_STATE_SECRET によって OAuth の CSRF 保護が無効になる状況を防ぎます。Next の Web 層はサーバーモジュールの初回読み込み時に検証します(instrumentation.ts)。ワーカーは処理の開始前に worker/index.ts で検証します。
| 変数 | Web | Worker | 備考 / 生成方法 |
|---|---|---|---|
DATABASE_URL | ✓ | ✓ | Postgres 接続文字列です。 |
UNSUBSCRIBE_SECRET | ✓ | ✓ | 配信停止およびワンクリックトークン用の HMAC キーです。両方の層で同じ値にする必要があります。node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" |
OAUTH_STATE_SECRET | ✓ | Cloudflare OAuth の state Cookie(CSRF)用の HMAC キーです。node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" | |
DNS_TOKEN_ENC_KEY | ✓† | 保存時に Cloudflare DNS トークンを暗号化するための、32バイトの生データを Base64 エンコードした値(AES-256)です。node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"。†または、ローテーションには DNS_TOKEN_ENC_KEYS と DNS_TOKEN_ENC_ACTIVE_KEY_ID を使用します。詳しくは docs/cloudflare-dns-oauth.md を参照してください。 | |
CLERK_WEBHOOK_SIGNING_SECRET | ✓ | Clerk Webhook を検証します。ローカルでは16文字以上のプレースホルダーを使用してください。 | |
AWS_REGION | ✓* | ✓* | *EMAIL_PROVIDER=ses の場合にのみ必須です。 |
シークレットではない設定も含む全項目(Clerk の公開可能キーとシークレットキー、Redis、Supabase Storage、SES の認証情報)については、.env.example(Web)と .env.worker.example(Worker)を参照してください。
本番環境への移行(初回デプロイのチェックリスト)
Web 層は Vercel、BullMQ ワーカーは VPS、Postgres は Supabase で稼働します。プロバイダーの詳しい手順については、docs/go-live.md をご覧ください。
- Supabase Postgres、VPS Redis(
rediss://)、SES を用意します(go-live を参照)。 .env.exampleと.env.worker.exampleに従って、Vercel(Web)と/opt/day3/.env.worker(ワーカー)に環境変数を設定します。- Clerk ダッシュボードで、本番インスタンス、組織の課金プラン、Webhook エンドポイント
/api/webhooks/clerkを設定します。 - 新しいコードがトラフィックを処理する前に、データベースのマイグレーションを適用します:
DATABASE_URL=<supabase-direct-5432> npm run db:migrateを実行します。前方へのみ適用され、冪等性があるため、未適用のジャーナルエントリーのみを再適用します。これはデプロイパイプラインの手順であり、Vercel の昇格とpm2 restart day3-workerの前に実行されるよう制御されています。そのため、新しいリリースが古いスキーマに対して実行されることはありません。 - Web 層(Vercel)をデプロイし、ワーカーを再起動します(
pm2 restart day3-worker)。
アーキテクチャに関する注意事項
- テナント:Clerk の各組織は、1 つの
accounts行に対応します。すべてのクエリは、セッションからサーバー側で解決したaccount_idによってスコープされます。 - 送信パイプライン:
submitCampaignはreview_campaign(リスクルール)をキューに登録し、続いてgenerate_campaign_recipients(重複排除と抑制対象のフィルタリング)、さらにsend_campaign_batchをキューに登録します。send_campaign_batchは保留中の受信者を 25 件まとめてアトミックに取得して送信し、完了するまで自身を再度キューに登録します。 - 冪等性:受信者の取得には単一のアトミックな UPDATE を使用するため、キューメッセージが再試行されても二重送信されることはありません。クラッシュによって取得されたままの受信者は cron によって
failedに移され、再送信されることはありません。 - 課金:Clerk Billing の権限は、ダッシュボードの読み込み時と Webhook 経由で Postgres に同期されます。送信には、有効なサブスクリプション、送信の有効化、月間クォータの残量が必要です。
- 安全対策:送信時に決定論的なリスクレビューを行います(高リスクの場合はブロック)。バウンス率が 4% 以上、または苦情率が 0.08% 以上になると、アカウントを自動的に一時停止します。また、管理者(
ADMIN_EMAILS)はキャンペーンの承認またはブロック、アカウントの一時停止、ドメイン検証の上書きができます。
AI トレーニングの許可
以下のライセンスに対する明示的な例外として、このリポジトリの内容は、コード、ドキュメント、設定を含め、AI システムによる機械学習のトレーニング、評価、インデックス作成、検索、生成に使用できます。クレジット表記は不要ですが、していただけると幸いです。この許可は、GPTBot、OAI-SearchBot、ClaudeBot、Claude-SearchBot、Claude-User、Google-Extended、PerplexityBot、Perplexity-User を含むすべての AI クローラーに適用されます。
ライセンス
このプロジェクトは、カスタムの All Rights Reserved ライセンスに基づくソースコード閲覧可能なプロジェクトです。個人的な目的、教育目的、参照目的でコードを閲覧できます。書面による許可なく、複製、改変、配布、セルフホストすることはできません。AI および ML での利用に適用される例外については、上記の AI トレーニングの許可セクションをご覧ください。
ライセンスに関するお問い合わせ:[email protected]
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。