Mailgun is a developer-focused email API by Sinch for high-volume transactional and marketing email. To use it in Bolt.new, install the mailgun.js SDK, create a Next.js API route that sends email via Mailgun's REST API, and store your API key in .env. Outbound email works in the Bolt WebContainer preview. Webhook event tracking requires a deployed URL on Netlify or Bolt Cloud.
High-Volume Email for Bolt.new Apps Using Mailgun
Mailgun, now part of Sinch, is one of the most developer-beloved email infrastructure services available. Unlike consumer email services that require a UI or marketing platform, Mailgun is a pure HTTP API — you send a POST request, and Mailgun handles routing, delivery, bounce management, ISP relationships, and compliance. This makes it an ideal match for Bolt.new's API-first architecture. The mailgun.js SDK is a pure JavaScript library with no native modules or C extensions, so it installs and runs in Bolt's WebContainer without any compatibility issues.
Mailgun's key differentiator is its focus on deliverability at scale. When you send through Mailgun's shared IP pool (on the free tier) or a dedicated IP, your email goes through servers with maintained sending reputations, DKIM signing, SPF records, and feedback loops with major inbox providers. For a Bolt.new app sending password reset emails, welcome emails, order confirmations, or notification digests, this means your emails actually reach inboxes rather than spam folders. Mailgun also provides detailed analytics: opens, clicks, bounces, unsubscribes — all queryable via the API or visible in the dashboard.
This guide covers the full integration: creating an account and verifying a sending domain, sending email through a Next.js API route with the mailgun.js SDK, building a contact form in React that triggers an email, using Mailgun's template system for HTML email, and handling event webhooks after deployment. One critical limitation to understand upfront: Mailgun's webhook callbacks require a publicly accessible URL. During development in Bolt's WebContainer, your app has no public URL — so webhook processing can only be tested after deploying to Netlify or Bolt Cloud. Outbound email sending works in the preview without any restrictions.
Integration method
Mailgun integrates with Bolt.new through a Next.js API route that calls Mailgun's REST API using the mailgun.js SDK. The API key is stored securely in .env and never reaches the browser. Outbound email sending works in Bolt's WebContainer during development. Webhook event handling (opens, clicks, bounces) requires deploying to Netlify or Bolt Cloud first, then registering a webhook URL in the Mailgun dashboard.
Prerequisites
- A Mailgun account (mailgun.com) — the free tier allows 1,000 emails per month and includes a sandbox sending domain for testing
- A sending domain verified in Mailgun (or use the sandbox domain provided automatically on signup for initial testing)
- Your Mailgun API key from the Mailgun dashboard under Settings → API Keys — use the Private API Key for server-side use
- A Bolt.new project using Next.js (the API route pattern requires a Node.js server runtime that Next.js provides)
- A deployed URL on Netlify or Bolt Cloud (required only for webhook event handling — not needed for basic sending)
Step-by-step guide
Set up your Mailgun account and get your API key and domain
Set up your Mailgun account and get your API key and domain
Go to mailgun.com and sign up for a free account. Mailgun's free plan provides 1,000 emails per month with no credit card required, which is sufficient for development and small-scale use. After confirming your email, you will land in the Mailgun dashboard. The first thing you need is a sending domain. Mailgun automatically provisions a sandbox domain for you — it looks like sandbox12345abc.mailgun.org. This sandbox domain works immediately and requires no DNS configuration, making it perfect for development. However, it can only send to email addresses you explicitly authorize in the Mailgun dashboard under 'Authorized Recipients.' This restriction exists to prevent abuse on free accounts. For a production app, you will want to verify your own domain (e.g., mail.yourdomain.com). In the Mailgun dashboard, click 'Domains' in the left sidebar, then 'Add New Domain.' Enter your domain, select your region (US or EU), and click 'Add Domain.' Mailgun will provide DNS records — a TXT record for SPF, a TXT record for DKIM, and optionally a CNAME for tracking. Add these records in your domain registrar's DNS settings. Verification typically takes 5-30 minutes. Next, get your API key. In the Mailgun dashboard, go to Settings → API Keys. Copy the Private API Key — it starts with 'key-' and is a long alphanumeric string. This is the key you will add to your .env file. Keep this key confidential; it has full access to your Mailgun account. Also note your sending domain — you will need both the API key and the domain in your environment variables. Finally, note your Mailgun API base URL. If you are on Mailgun's US region (default), use https://api.mailgun.net. If you selected the EU region, use https://api.eu.mailgun.net. The base URL varies by region and must match where your account is hosted.
Pro tip: During development, use Mailgun's sandbox domain and add your own email address as an Authorized Recipient in the Mailgun dashboard. This lets you receive actual test emails without verifying a custom domain.
Expected result: You have a Mailgun account, a private API key, and either a sandbox domain or a verified custom domain. You know whether your account is on the US or EU region.
Install mailgun.js and create the email API route in Bolt
Install mailgun.js and create the email API route in Bolt
With your Mailgun credentials in hand, prompt Bolt to scaffold the entire email integration. The mailgun.js SDK is a pure JavaScript library maintained by Mailgun that wraps the REST API. It is compatible with Bolt's WebContainer because it uses the native fetch API internally — no native Node.js modules or C extensions are needed. The API route you will create lives at app/api/email/route.ts in a Next.js project. This server-side route accepts a POST request from your React components, validates the input, and calls Mailgun's API. By keeping all Mailgun calls in this route, your private API key never reaches the browser bundle. Paste the following prompt into Bolt's chat to generate the complete setup. After Bolt generates the code, review app/api/email/route.ts to confirm it reads from process.env.MAILGUN_API_KEY and process.env.MAILGUN_DOMAIN. Check that no Mailgun credentials appear in any client-side component files. Also verify that Bolt added 'mailgun.js' and 'form-data' to package.json — the form-data package is required as a peer dependency for mailgun.js. Note: Bolt's WebContainer will install mailgun.js from the npm CDN-backed cache, typically completing within a few seconds. If you see an installation error, it may be because a transient WebContainer network issue occurred — try prompting Bolt to 'Reinstall dependencies' or restart the dev server.
Install the mailgun.js npm package and create an email sending service for this Next.js app. Create: (1) A file at lib/mailgun.ts that initializes the Mailgun client using MAILGUN_API_KEY and MAILGUN_DOMAIN from process.env and exports a sendEmail(to, subject, html, text) function. (2) A Next.js API route at app/api/email/route.ts that accepts POST requests with JSON body { to, subject, html, text }, validates all fields are present, calls the mailgun service, and returns 200 on success or 500 on failure. (3) A .env file with MAILGUN_API_KEY=your_key_here and MAILGUN_DOMAIN=your_sandbox_domain.mailgun.org as placeholders. Use TypeScript throughout.
Paste this in Bolt.new chat
1// lib/mailgun.ts2import Mailgun from 'mailgun.js';3import FormData from 'form-data';45const mailgun = new Mailgun(FormData);67const mg = mailgun.client({8 username: 'api',9 key: process.env.MAILGUN_API_KEY ?? '',10 // Use 'https://api.eu.mailgun.net' for EU region accounts11 url: 'https://api.mailgun.net',12});1314const DOMAIN = process.env.MAILGUN_DOMAIN ?? '';15const FROM = process.env.MAILGUN_FROM_EMAIL ?? `noreply@${DOMAIN}`;1617export interface EmailOptions {18 to: string | string[];19 subject: string;20 html: string;21 text: string;22 replyTo?: string;23 template?: string;24 templateVariables?: Record<string, string>;25}2627export async function sendEmail(options: EmailOptions) {28 if (!process.env.MAILGUN_API_KEY || !DOMAIN) {29 throw new Error('Mailgun credentials not configured');30 }3132 const messageData: Record<string, unknown> = {33 from: FROM,34 to: options.to,35 subject: options.subject,36 html: options.html,37 text: options.text,38 };3940 if (options.replyTo) {41 messageData['h:Reply-To'] = options.replyTo;42 }4344 if (options.template) {45 messageData.template = options.template;46 messageData['h:X-Mailgun-Variables'] = JSON.stringify(options.templateVariables ?? {});47 }4849 return mg.messages.create(DOMAIN, messageData as Parameters<typeof mg.messages.create>[1]);50}Pro tip: Mailgun's sandbox domain can only send to Authorized Recipients — add your own email in the Mailgun dashboard before testing. For production, you must verify a custom domain to send to any address.
Expected result: The mailgun.js package is installed in package.json, lib/mailgun.ts exports a working sendEmail function, and app/api/email/route.ts handles POST requests. The .env file has placeholder values ready for your real credentials.
Add real credentials to .env and test with a contact form
Add real credentials to .env and test with a contact form
Open the .env file in Bolt's file explorer and replace the placeholder values with your actual Mailgun credentials. You need three values: MAILGUN_API_KEY (your private API key starting with 'key-'), MAILGUN_DOMAIN (your sandbox or custom domain like sandbox12345.mailgun.org or mail.yourdomain.com), and optionally MAILGUN_FROM_EMAIL (the 'from' address for outgoing emails — must match or be a subdomain of your sending domain). With the credentials in place, prompt Bolt to build a contact form component that calls the /api/email route. The contact form should be a standard React component with controlled inputs for name, email, and message, a submit handler that calls fetch('/api/email', { method: 'POST', ... }), and state management for loading and success/error states. After Bolt generates the form, click the Bolt preview to test it. Fill in the form fields and click submit. In Bolt's terminal panel at the bottom, you should see the Next.js dev server log the API route being called. After a few seconds, check your inbox (if you added your email as an Authorized Recipient in Mailgun). You should receive the test email. If no email arrives within 2 minutes, go to your Mailgun dashboard → Logs → see if the message was accepted or rejected. The Mailgun Logs panel is excellent for debugging — it shows the exact delivery status and any error messages. Outbound email from the Next.js API route works in Bolt's WebContainer without any deployment step. This is because outbound HTTPS calls to Mailgun's API servers are just regular fetch() calls — they work from any Node.js runtime, including WebContainers. This is a significant advantage over services that require webhooks for even basic sending.
Build a contact form component at components/ContactForm.tsx with fields for name, email, and message (all required). On submit, call POST /api/email with the form data as JSON. Show a loading spinner during submission, a green success message after sending, and a red error message if the API call fails. Add basic validation: email must match a valid format, name and message must be at least 2 characters. Use Tailwind CSS for styling and shadcn/ui Form components.
Paste this in Bolt.new chat
1# .env2# Mailgun credentials — server-side only, never use NEXT_PUBLIC_ prefix3MAILGUN_API_KEY=key-your_private_api_key_here4MAILGUN_DOMAIN=sandboxABCDEF123456.mailgun.org5MAILGUN_FROM_EMAIL=noreply@sandboxABCDEF123456.mailgun.org67# For EU region accounts, update the url in lib/mailgun.ts:8# url: 'https://api.eu.mailgun.net'Pro tip: Mailgun's Logs panel in the dashboard shows every outbound message attempt with delivery status, ISP response codes, and timestamps. If email is not arriving, check Logs before spending time debugging your code — it is almost always a credential or domain configuration issue that Mailgun reports clearly.
Expected result: The contact form appears in the Bolt preview. Submitting the form sends a real email via Mailgun that arrives in your inbox within 30 seconds. The Mailgun dashboard Logs panel shows the message as 'Delivered'.
Use Mailgun templates for branded HTML email
Use Mailgun templates for branded HTML email
Hardcoding HTML in your API route is fine for simple one-off emails, but for an app sending multiple types of transactional email — welcome messages, password resets, order confirmations — Mailgun's template system is a much better approach. Templates are managed in the Mailgun dashboard, support Handlebars syntax for variable substitution, can be version-controlled, and let non-developers update email copy without touching code. To create a template, go to your Mailgun dashboard → Email Templates → Create Message. Give it a name like 'welcome-email.' Use Mailgun's visual template builder or paste in raw HTML. Add Handlebars variable placeholders like {{name}}, {{confirm_link}}, and {{company_name}} where you want dynamic content. Save the template. In your Bolt app, update the sendEmail function in lib/mailgun.ts to support template-based sending. When a template name is provided, Mailgun's API uses the stored template instead of the html/text fields, substituting the variables you pass as 'h:X-Mailgun-Variables.' The template system also handles plain-text fallback automatically when configured in the template settings. Template versioning is a powerful feature: create multiple versions of a template (version 1, version 2, etc.) and deploy them independently. The API always uses the 'active' version, so you can test new designs by activating a draft without changing code. This separation of email design from application logic is a significant advantage for teams where designers and developers work independently.
Update lib/mailgun.ts to support Mailgun template-based sending. Add a sendTemplateEmail(to, templateName, variables) exported function that calls Mailgun's API with the template name and recipient variables object. Then create a sendWelcomeEmail(to, name, confirmLink) function that calls sendTemplateEmail with the 'welcome-email' template and the correct variables. Add TypeScript interfaces for the template variables. Show me the code for how to create the 'welcome-email' Mailgun template with {{name}} and {{confirm_link}} placeholders.
Paste this in Bolt.new chat
1// lib/email-templates.ts2import { sendEmail } from './mailgun';34// Welcome email using Mailgun template5export async function sendWelcomeEmail(to: string, name: string, confirmLink: string) {6 return sendEmail({7 to,8 subject: `Welcome to our app, ${name}!`,9 // html and text are ignored when using a template10 html: '',11 text: `Welcome ${name}! Confirm your email: ${confirmLink}`,12 template: 'welcome-email',13 templateVariables: {14 name,15 confirm_link: confirmLink,16 company_name: 'My App',17 },18 });19}2021// Password reset email22export async function sendPasswordResetEmail(to: string, resetLink: string) {23 return sendEmail({24 to,25 subject: 'Reset your password',26 html: '',27 text: `Click this link to reset your password: ${resetLink}`,28 template: 'password-reset',29 templateVariables: {30 reset_link: resetLink,31 expiry_hours: '2',32 },33 });34}Pro tip: Mailgun templates support Handlebars conditionals and loops: {{#if isPremium}}... {{/if}}. This lets a single template render different content for free vs. paid users without duplicating templates.
Expected result: The app can send template-based emails from Mailgun. Welcome emails and password reset emails render using the HTML template stored in the Mailgun dashboard, with dynamic name and link variables filled in correctly.
Deploy and configure Mailgun webhooks for email event tracking
Deploy and configure Mailgun webhooks for email event tracking
Mailgun can notify your app in real time when email events occur: a recipient opened your email, clicked a link, unsubscribed, or — most importantly — when an email bounced or a recipient marked it as spam. These event notifications are delivered via webhooks — HTTP POST requests that Mailgun sends to a URL you specify. Because webhooks require a publicly accessible URL, they cannot be tested in Bolt's WebContainer, which has no public endpoint. This is the one part of the Mailgun integration that requires a deployment step first. Deploy your app to Netlify (using Bolt's native Netlify integration under Settings → Applications) or Bolt Cloud (click the Publish button). Once deployed, you will have a public URL like yourapp.netlify.app or yourapp.bolt.host. In the Bolt terminal, run the build to verify there are no errors: this is a good check before deploying. After deployment, go to your Netlify or Bolt Cloud dashboard and add the environment variables: MAILGUN_API_KEY, MAILGUN_DOMAIN, and MAILGUN_FROM_EMAIL. Without these, the deployed app's email API route will return 500 errors. Trigger a redeploy after adding variables. Then create a webhook handler. In Bolt, add an API route at app/api/webhooks/mailgun/route.ts. This route accepts POST requests from Mailgun containing event data. Mailgun sends a signed webhook with a timestamp, token, and HMAC-SHA256 signature using your webhook signing key (found in Mailgun Settings → Webhooks → Webhook signing key). You should verify this signature before processing events to prevent abuse. Finally, register the webhook URL in the Mailgun dashboard: Settings → Webhooks → Add webhook. Enter your deployed URL (https://yourapp.netlify.app/api/webhooks/mailgun) and select the events you want to track. Click Test Webhook to verify Mailgun can reach your endpoint.
Create a Mailgun webhook handler at app/api/webhooks/mailgun/route.ts. It should accept POST requests from Mailgun, verify the webhook signature using MAILGUN_WEBHOOK_KEY from process.env (using HMAC-SHA256 — the signature is in the request body as 'signature.signature', timestamp as 'signature.timestamp', token as 'signature.token'). Log the event type and recipient to the console. Handle event types: 'delivered', 'opened', 'clicked', 'bounced', 'complained', 'unsubscribed'. Return 200 for all valid requests. Add MAILGUN_WEBHOOK_KEY to the .env file as a placeholder.
Paste this in Bolt.new chat
1// app/api/webhooks/mailgun/route.ts2import { NextResponse } from 'next/server';3import crypto from 'crypto';45function verifyMailgunSignature(6 signingKey: string,7 timestamp: string,8 token: string,9 signature: string10): boolean {11 const value = timestamp + token;12 const hmac = crypto.createHmac('sha256', signingKey).update(value).digest('hex');13 return hmac === signature;14}1516export async function POST(request: Request) {17 const signingKey = process.env.MAILGUN_WEBHOOK_KEY;18 if (!signingKey) {19 return NextResponse.json({ error: 'Webhook key not configured' }, { status: 500 });20 }2122 const body = await request.json();23 const { signature, 'event-data': eventData } = body;2425 // Verify webhook authenticity26 const isValid = verifyMailgunSignature(27 signingKey,28 signature.timestamp,29 signature.token,30 signature.signature31 );3233 if (!isValid) {34 return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });35 }3637 const eventType = eventData?.event;38 const recipient = eventData?.recipient;3940 console.log(`Mailgun event: ${eventType} for ${recipient}`);4142 // Handle specific events43 switch (eventType) {44 case 'bounced':45 // Mark email as undeliverable in your database46 break;47 case 'complained':48 // Unsubscribe user from future emails49 break;50 case 'unsubscribed':51 // Update user preferences in database52 break;53 }5455 return NextResponse.json({ received: true });56}Pro tip: Always process Mailgun bounce events to remove undeliverable addresses from your send list. Continuing to send to bounced addresses harms your sender reputation and can eventually cause legitimate emails to end up in spam folders.
Expected result: The app is deployed to Netlify or Bolt Cloud. Mailgun webhooks are registered pointing to your deployed API route URL. Sending a test email and clicking an open/click pixel triggers a webhook event that appears in your server logs.
Common use cases
Contact Form Email Notifications
A standard contact form on a marketing site or SaaS app that sends the submitted message to a business email address and auto-replies to the sender. The form submits to a Next.js API route, which calls Mailgun to send both emails in parallel. Runs in the Bolt WebContainer preview without any deployment required.
Build a contact form page in Next.js with fields for name, email, and message. Create an API route at /api/contact that uses the mailgun.js SDK to (1) send the form contents to contact@mybusiness.com and (2) send an auto-reply to the submitter. Store MAILGUN_API_KEY and MAILGUN_DOMAIN in .env. Add validation — all fields required, valid email format. Show a success message after submission. Use Tailwind for styling.
Copy this prompt to try it in Bolt.new
Transactional Email for User Authentication
Welcome emails on signup, password reset links, and email verification tokens sent automatically when authentication events fire. Integrates with Bolt Database or Supabase Auth triggers. Uses Mailgun's template system for consistent HTML branding across all transactional emails.
Create a Mailgun email service module at lib/email.ts that exports sendWelcomeEmail(to, name) and sendPasswordReset(to, resetLink) functions. Both should use the mailgun.js SDK with MAILGUN_API_KEY and MAILGUN_DOMAIN from process.env. sendWelcomeEmail should use a Mailgun template named 'welcome-email'. Create a Next.js API route at /api/auth/register that creates a user in the database and triggers sendWelcomeEmail. Include error handling that returns 500 if the email fails but still creates the user account.
Copy this prompt to try it in Bolt.new
Bulk Newsletter Digest
A weekly or daily digest email sent to a list of subscribers, with personalized variable substitution for each recipient's name and preferences. Uses Mailgun's batch sending endpoint with recipient variables to personalize each message without sending individual requests.
Build a newsletter sending system using Mailgun. Create an API route at /api/newsletter/send that accepts a JSON body with 'subject', 'htmlContent', and 'recipients' (array of {email, name} objects). Use Mailgun's batch sending with recipient-variables to personalize the 'Hi {name}' greeting in each email. Add an unsubscribe link using Mailgun's built-in %unsubscribe_url% tag. Store all credentials in .env. Add a simple admin UI page at /admin/newsletter with a form to compose and send.
Copy this prompt to try it in Bolt.new
Troubleshooting
Email API route returns 401 Unauthorized or 'Forbidden' from Mailgun
Cause: The MAILGUN_API_KEY in your .env file is incorrect, or you are using the wrong type of API key. Mailgun has both Private API Keys and Sending API Keys — the Mailgun.js SDK requires the Private API Key.
Solution: Go to your Mailgun dashboard → Settings → API Keys. Copy the Private API Key (not a Sending API Key or Domain Key). In your .env file, ensure the key is on a single line with no extra spaces: MAILGUN_API_KEY=key-yourkeyhere. Also verify you did not accidentally add NEXT_PUBLIC_ prefix — that would expose the key client-side and also not work in the API route.
1# Correct: Private API key, no prefix2MAILGUN_API_KEY=key-1234567890abcdef1234567890abcdef34# Wrong: do not use NEXT_PUBLIC_ for API keys5# NEXT_PUBLIC_MAILGUN_API_KEY=... <- NEVER do thisEmail is accepted by Mailgun API (200 response) but never arrives in inbox
Cause: For sandbox domains, Mailgun only delivers to Authorized Recipients — email addresses you have explicitly whitelisted in the Mailgun dashboard. Sending to any other address is silently accepted by the API but never actually delivered.
Solution: Go to Mailgun dashboard → Sending → Domains → click your sandbox domain → Authorized Recipients. Add the email address you are testing with and click 'Invite.' The recipient will receive an authorization email — they must click the confirmation link. Once authorized, emails will deliver normally. For production use, verify a custom domain to remove this restriction.
Mailgun webhook handler returns 200 but Mailgun keeps retrying the same event
Cause: Mailgun expects a 200 response within 5 seconds. If your webhook handler takes longer than 5 seconds (e.g., due to database writes or slow processing), Mailgun treats it as a timeout and retries. The handler may also be throwing an error that is caught and converted to a non-200 status.
Solution: Respond immediately with 200 and process the event asynchronously. In Next.js, you can use waitUntil() (available in Vercel Edge Runtime) or simply kick off processing without awaiting it. Keep the webhook handler fast — acknowledge receipt immediately, then queue the actual work.
1// Respond immediately, process asynchronously2export async function POST(request: Request) {3 const body = await request.json();4 // ... verify signature ...56 // Start processing without awaiting (fire-and-forget)7 processMailgunEvent(body).catch(console.error);89 // Respond immediately so Mailgun does not retry10 return NextResponse.json({ received: true });11}Module not found: 'form-data' when importing mailgun.js
Cause: mailgun.js requires form-data as a peer dependency but it may not be installed automatically. In Bolt's WebContainer, missing peer dependencies cause import failures at runtime.
Solution: In Bolt's chat, type: 'Install the form-data package as a dependency.' Alternatively, manually add 'form-data': '^4.0.0' to the dependencies section of package.json and prompt Bolt to reinstall dependencies. The form-data package is a pure JavaScript library and installs without issues in WebContainers.
1// package.json — ensure both packages are in dependencies2{3 "dependencies": {4 "mailgun.js": "^10.0.0",5 "form-data": "^4.0.0"6 }7}Best practices
- Always proxy Mailgun API calls through a Next.js API route — never call Mailgun's API directly from React components where your private API key would be exposed in the browser
- Use Mailgun's template system for all transactional emails rather than hardcoding HTML in API routes — this separates email design from code and lets you update copy without deployments
- Process Mailgun bounce and complaint webhooks to maintain a clean sending list — high bounce rates hurt your sender reputation and can get your domain blacklisted
- Set MAILGUN_FROM_EMAIL to a no-reply address at your verified domain (e.g., noreply@yourapp.com) rather than using personal email addresses for the 'from' field
- Add a rate limit to your email API route to prevent abuse — a malicious user could hammer your /api/email endpoint to exhaust your Mailgun quota
- Test with Mailgun's sandbox domain during development, but switch to a verified custom domain before launch — sandbox domains are limited to Authorized Recipients only
- Verify Mailgun webhook signatures using HMAC-SHA256 before processing any event — unverified webhooks are a security risk that could allow attackers to fake events
- For high-volume sends (newsletters, digests), use Mailgun's batch sending endpoint with recipient variables instead of making individual API calls per recipient
Alternatives
Choose SendGrid if you need a more established provider with a larger free tier (100 emails/day free), a visual email design tool, and Twilio ecosystem integration.
Choose Twilio if you need SMS and voice communication alongside email, since Mailgun (owned by Sinch) is email-only while Twilio covers the full communications stack.
Choose Mailchimp if your primary need is marketing email campaigns with audience segmentation and A/B testing, rather than developer-focused transactional email.
Choose ConvertKit if you are building a creator-focused newsletter or content business and need subscriber management and automation sequences rather than pure API-driven email.
Frequently asked questions
Does Mailgun work in Bolt.new's WebContainer during development?
Yes — outbound email sending via the mailgun.js SDK works in Bolt's WebContainer because it uses standard HTTPS fetch calls. You can send test emails from the Bolt preview without deploying. The only functionality that requires deployment is webhook event handling (opens, clicks, bounces), which needs a publicly accessible URL that the WebContainer cannot provide.
How do I connect Bolt.new to Mailgun?
Install the mailgun.js package, create a Next.js API route that reads your Mailgun API key and domain from process.env, and use the Mailgun client to call mg.messages.create(). Store MAILGUN_API_KEY and MAILGUN_DOMAIN in your .env file during development. When deploying to Netlify or Bolt Cloud, add these same variables in the hosting platform's environment variable settings.
Can I send email from a client-side React component in Bolt.new?
No — you should never call Mailgun's API directly from React components. Your Mailgun Private API Key would be exposed in the browser bundle, visible to anyone who inspects your app. Always route email sending through a server-side Next.js API route that reads the key from process.env.
What is the difference between Mailgun's sandbox domain and a verified domain?
Mailgun's sandbox domain is automatically provisioned when you create an account and requires no DNS setup. It can only send to email addresses you explicitly authorize in the Mailgun dashboard — ideal for development and testing. A verified custom domain (like mail.yourdomain.com) lets you send to any email address and is required for production use. Custom domain verification involves adding DNS TXT records for SPF and DKIM, which typically takes 5-30 minutes.
How do I deploy a Bolt.new Mailgun app to Netlify?
Use Bolt's native Netlify integration (Settings → Applications → Connect Netlify) or push your code to GitHub and connect the repo to Netlify manually. After deploying, go to your Netlify site's Environment variables settings and add MAILGUN_API_KEY, MAILGUN_DOMAIN, MAILGUN_FROM_EMAIL, and MAILGUN_WEBHOOK_KEY. Trigger a redeploy. Your Next.js API routes run as Netlify Functions and will correctly read these environment variables.
Can Mailgun handle 10,000 or more emails per month in Bolt.new?
Mailgun is designed for high-volume sending — it handles millions of emails per day for enterprise customers. The free plan covers 1,000 emails per month. For higher volumes, Mailgun offers paid plans starting at $15/month for 10,000 emails. The integration code in Bolt.new is identical regardless of volume — Mailgun's infrastructure handles the scaling on their end.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation