MuseMVP

MuseMVP Base: Next.js for Node and Cloudflare. MuseMVP Flare: an AI SaaS template that runs entirely on Cloudflare. Authentication, billing and administration included.

Product
  • Home
  • Pricing
  • Templates
Resources
  • Docs
  • Blog
  • Changelog
Legal
  • Privacy
  • Terms
  • Community
Open-Launch Top 1 Daily WinnerOpen-Launch Top 1 Daily WinnerVerified DR - Verified Domain Rating for musemvp.comVerified DR - Verified Domain Rating for musemvp.comMuseMVP - Featured on Startup FameMuseMVP - Featured on Startup FameFazier badgeFazier badgeLiftOff award badgeLiftOff award badge

© 2026 MuseMVP. All rights reserved.

MuseMVP
  • Pricing
  • Docs
  • Blog
  • Changelog
Buy All in One
MuseMVP Docs
MuseMVP Docs
OverviewTech StackQuick Start
Project Structure
EmailObject Storage
Internationalization
SEOAnalytics

Email

Send your first verification email, configure your sender, and customize email templates.

Email enables registration codes, OTP sign-in, password recovery, and contact messages. Configure a real provider when you want these messages delivered to an inbox.

Before You Start

Have a running local app, a test inbox, and a sending domain you can verify. Use Resend for this walkthrough, or configure Cloudflare Email Sending below. Provider limits depend on your account.

1. Connect Your Provider

Node: Resend

In your Resend account, add a sending domain, copy its required DNS records to your DNS provider, and wait for verification. Create an API key authorized to send mail. Set these values in apps/web/.env.local:

MAIL_PROVIDER="resend"
RESEND_API_KEY="YOUR_RESEND_API_KEY"
MAIL_FROM="Acme <[email protected]>"
MAIL_FROM_NEWSLETTER="Acme <[email protected]>"
CONTACT_FORM_TO="[email protected]"
NEXT_PUBLIC_EMAIL_SUPPORT="[email protected]"

Replace example.com with your verified domain. MAIL_FROM is the transactional sender; CONTACT_FORM_TO is the inbox receiving contact messages. Keep the NEWSLETTER_TOKEN_SECRET generated by init.

Cloudflare Email Sending

Configure a sending domain and obtain an API token with the required email-sending access for your account. Set these values in apps/web/.env.local:

MAIL_PROVIDER="cloudflare"
CLOUDFLARE_ACCOUNT_ID="YOUR_ACCOUNT_ID"
CLOUDFLARE_API_TOKEN="YOUR_EMAIL_SENDING_TOKEN"
MAIL_FROM="Acme <[email protected]>"
MAIL_FROM_NEWSLETTER="Acme <[email protected]>"
CONTACT_FORM_TO="[email protected]"
NEXT_PUBLIC_EMAIL_SUPPORT="[email protected]"

Set the same server credentials on your production host. Set the same server credentials on your production host before launch.

2. Receive Your First Email

Restart the dev server. Open the login page and request an email sign-in code for an account you control, or use password recovery for an existing account. Check the inbox and spam folder, then finish that flow with the received code.

Locally, MAIL_PROVIDER=console (the init default, also used when the value is empty) prints mail in the server terminal without delivery. Switch to a real provider before testing deliverability or deploying; production rejects console.

Check Your Result

  • The email arrives with your sender address, product name, and expected language.
  • The code completes the intended sign-in or reset flow.
  • A contact-form message reaches CONTACT_FORM_TO.
  • Newsletter confirmation and signed unsubscribe links work if you use the newsletter feature.

Common Problems

ProblemFix
No message in the inboxCheck server errors, provider logs, spam, and whether MAIL_PROVIDER is still console
Provider rejects the senderVerify the sending domain and token permissions; use a sender on that domain
Links point to localhostSet the deployment's NEXT_PUBLIC_SITE_URL to your HTTPS origin and rebuild

Customize the Email

Edit shared React Email templates under packages/mail/src/templates/. Current template IDs are emailVerification, magicLink, newsletterSignup, verificationCode, verificationCodeSignin, and verificationCodeForgotPassword.

Preview them with:

pnpm --filter @musemvp/web exec email dev --dir ../../packages/mail/src/templates --port 4100

Open http://localhost:4100. Use this explicit directory: the current root mail:preview script still points at the previous template location.

For a new template, register its ID and add mail.<templateId>.subject in both locales' packages/i18n/src/translations/{en,zh}/mvp.json. Package code uses relative or package imports, not app @/ imports.

From app server code, call:

import { sendEmail } from "@/modules/mail";

await sendEmail({
  to: user.email,
  locale,
  templateId: "verificationCodeSignin",
  context: { otp, expiresIn: 300 },
});

user, locale, and otp come from your server flow. sendEmail() also supports raw subject / html / text. To add a welcome email, create a template and connect it to your chosen event; it is not an existing default template. Preview checks appearance, not delivery.

Waffo Pancake

Configure the Waffo Pancake gateway.

Object Storage

Connect object storage, upload an avatar, and check your asset list.

On this page

Before You Start1. Connect Your ProviderNode: ResendCloudflare Email Sending2. Receive Your First EmailCheck Your ResultCommon ProblemsCustomize the Email

One payment. Tax included.

All in One

Base, Flare and every UI template, plus new ones.

$129

Buy All in One