To use SendGrid with V0, generate your email-triggered UI in V0 (contact form, password reset, order confirmation), then create a Next.js API route at app/api/sendgrid/route.ts that uses the @sendgrid/mail package to send transactional emails. Store your SendGrid API key in Vercel Dashboard → Settings → Environment Variables as SENDGRID_API_KEY without any NEXT_PUBLIC_ prefix.
Sending Transactional Emails from Your V0 App with SendGrid
Transactional emails — the messages that go out automatically when users do something in your app — are one of the most common integration requirements for any web application. Contact form confirmations, welcome emails, password reset links, order receipts, and notification alerts all fall into this category. SendGrid, part of the Twilio family, is one of the most widely used platforms for transactional email delivery because of its reputation, deliverability infrastructure, and straightforward Node.js SDK.
For V0 applications, the integration pattern is clean: V0 generates the UI element that triggers the email (a form, a button, a confirmation page), and a Next.js API route handles the SendGrid SDK call. The React component collects the necessary data (recipient email, user name, form content) and sends it to your API route via a POST request. The API route uses the @sendgrid/mail package to construct and send the email. Because the API key lives in a Vercel environment variable and the route runs server-side, there is no risk of exposing credentials to the browser.
SendGrid's free tier allows 100 emails per day permanently, which is sufficient for most early-stage apps. For higher volumes, plans start at $19.95/month for 50,000 emails. One important configuration step is domain authentication — verifying that your emails come from your actual domain rather than a SendGrid shared domain. This dramatically improves deliverability and prevents your messages from landing in spam folders.
Integration method
V0 generates the UI components that trigger emails — contact forms, signup flows, order confirmations — while a Next.js API route handles all SendGrid API calls server-side, keeping your API key out of the browser. When a user submits a form, the React component POSTs to your API route, which calls @sendgrid/mail to deliver the email through SendGrid's infrastructure.
Prerequisites
- A V0 account with a Next.js project at v0.dev
- A SendGrid account at sendgrid.com (free tier includes 100 emails/day permanently)
- A SendGrid API key created at SendGrid Dashboard → Settings → API Keys with at least Mail Send permission
- A verified sender identity in SendGrid (either a single sender address or a full domain authentication)
- A Vercel account with your V0 project deployed via GitHub
Step-by-step guide
Generate Your Email-Triggering UI in V0
Generate Your Email-Triggering UI in V0
Start by prompting V0 to create the interface that will trigger email sending. This could be a contact form, a newsletter signup widget, a 'Forgot Password' form, or a post-purchase confirmation screen. V0 excels at generating clean, well-styled forms with Tailwind CSS, and it will wire up the fetch POST request to your API route when you specify the endpoint. The critical details to include in your V0 prompt are: the form fields you need, the API endpoint to POST to (/api/sendgrid/contact or similar), the loading state while the request is in progress, the success state shown after a successful email send, and the error state shown when the API call fails. For a contact form, typical fields are name, email address, subject (optional), and message. For a newsletter signup, just an email field is common. For a password reset flow, just the email address. Make the V0 UI specific enough to be realistic — include character limits on message fields, email validation patterns, and a clear call to action button label. V0 generates React components with controlled inputs and fetch-based form submission. Review the generated fetch call to ensure it is posting to the correct endpoint and including all the fields your API route will need. The request body should be JSON with the email address and any other dynamic content you want to include in the email.
Create a contact form component with four fields: Full Name (text input), Email Address (email input), Subject (text input, optional), and Message (textarea, min 20 characters, max 500 with character counter). Add a Send Message button. On submit, POST to /api/sendgrid/contact with { name, email, subject, message }. Show a green success card with a checkmark icon and message 'Your message has been sent!' on success. Show a red error banner with the error text on failure. Include client-side validation: email format check, required fields highlighted if empty on submit.
Paste this in V0 chat
Pro tip: Ask V0 to disable the submit button after a successful send to prevent duplicate submissions. A simple boolean state variable controls this — once the success state is shown, the button should stay disabled or hidden.
Expected result: V0 generates a polished contact form with proper validation, loading state, and success/error feedback. The form POSTs JSON data to /api/sendgrid/contact.
Create the SendGrid Email API Route
Create the SendGrid Email API Route
Create the server-side API route that receives form data and sends email via SendGrid. The file goes at app/api/sendgrid/route.ts (or a more specific path like app/api/sendgrid/contact/route.ts if you have multiple email types). The @sendgrid/mail package is the official SendGrid Node.js SDK for sending email. Install it by adding @sendgrid/mail to your package.json dependencies. The SDK has a simple interface: call sgMail.setApiKey() with your API key, then call sgMail.send() with a message object containing to, from, subject, text, and html fields. The from address must match a verified sender identity in your SendGrid account — either a single verified sender email or an email at your authenticated domain. If the from address is not verified, SendGrid will reject the send request with a 403 error. For the to address, this is typically dynamic — either passed from the form (to notify the user) or hardcoded as your own email (to notify yourself of form submissions). A common pattern for contact forms is to send two emails: one to yourself with the form contents, and one to the user confirming receipt. The @sendgrid/mail package accepts an array of messages or a single message with multiple recipients. Handle errors explicitly and return meaningful HTTP status codes. If the user provides an invalid email format, return 400. If SendGrid rejects the request (wrong API key, unverified sender, etc.), catch the error, log it, and return 500. A caught error from the @sendgrid/mail SDK includes a response object with the HTTP status and body from SendGrid's API.
Create a Next.js API route at app/api/sendgrid/route.ts that accepts POST requests with { name, email, subject, message } in the body. Use @sendgrid/mail to send a notification email to the site owner (use SENDGRID_TO_EMAIL env var) with the form contents formatted in the HTML body, and a confirmation email to the user's email address. Set the API key from SENDGRID_API_KEY env var and the from address from SENDGRID_FROM_EMAIL env var. Return 200 on success or a descriptive error on failure.
Paste this in V0 chat
1import sgMail from '@sendgrid/mail';2import { NextRequest, NextResponse } from 'next/server';34sgMail.setApiKey(process.env.SENDGRID_API_KEY!);56export async function POST(request: NextRequest) {7 try {8 const { name, email, subject, message } = await request.json();910 if (!name || !email || !message) {11 return NextResponse.json(12 { error: 'name, email, and message are required' },13 { status: 400 }14 );15 }1617 // Email to site owner with form contents18 const ownerEmail = {19 to: process.env.SENDGRID_TO_EMAIL!,20 from: process.env.SENDGRID_FROM_EMAIL!,21 subject: `New contact form: ${subject || 'No subject'}`,22 html: `23 <h2>New Contact Form Submission</h2>24 <p><strong>From:</strong> ${name} (${email})</p>25 <p><strong>Subject:</strong> ${subject || 'None'}</p>26 <hr />27 <p><strong>Message:</strong></p>28 <p>${message.replace(/\n/g, '<br />')}</p>29 `,30 text: `From: ${name} (${email})\nSubject: ${subject || 'None'}\n\n${message}`,31 };3233 // Confirmation email to the person who submitted the form34 const confirmationEmail = {35 to: email,36 from: process.env.SENDGRID_FROM_EMAIL!,37 subject: `We received your message, ${name}!`,38 html: `39 <h2>Thanks for reaching out, ${name}!</h2>40 <p>We received your message and will get back to you within 24 hours.</p>41 <p>Here's a copy of what you sent:</p>42 <blockquote style="border-left: 3px solid #ccc; padding-left: 16px; color: #555;">43 ${message.replace(/\n/g, '<br />')}44 </blockquote>45 `,46 text: `Thanks for reaching out, ${name}! We received your message: ${message}`,47 };4849 await sgMail.send([ownerEmail, confirmationEmail]);5051 return NextResponse.json({ success: true });52 } catch (error: any) {53 console.error('SendGrid error:', error?.response?.body || error);54 return NextResponse.json(55 { error: 'Failed to send email' },56 { status: 500 }57 );58 }59}Pro tip: SendGrid's sgMail.send() accepts both a single message object and an array of messages. Sending both the owner notification and user confirmation in one API call (as an array) is more efficient than two separate API calls.
Expected result: The API route receives form data and successfully sends both the owner notification email and the user confirmation email via SendGrid. Both arrive in the respective inboxes within 1–2 seconds.
Add Environment Variables in Vercel
Add Environment Variables in Vercel
Your API route reads three environment variables: SENDGRID_API_KEY, SENDGRID_FROM_EMAIL, and SENDGRID_TO_EMAIL. Add all three to Vercel before deploying. Open your Vercel Dashboard, select your project, click the Settings tab, then Environment Variables in the sidebar. Add: SENDGRID_API_KEY: Your SendGrid API key from SendGrid Dashboard → Settings → API Keys. The key starts with SG. — make sure to copy the full key including that prefix. Do not add NEXT_PUBLIC_ — this key is server-only. If you lose the key, you cannot view it again in SendGrid; you must generate a new one. SENDGRID_FROM_EMAIL: The email address your emails will appear to come from. This must be a verified sender in SendGrid — either added as a Single Sender (SendGrid Dashboard → Settings → Sender Authentication → Single Sender Verification) or from a domain you have authenticated (recommended for production). If the from address is not verified, every send will fail with a 403 Forbidden error. SENDGRID_TO_EMAIL: Your notification email address — where you want to receive contact form submissions and other notifications. This is typically your business email. After adding all variables, click Save and trigger a new Vercel deployment by pushing a commit to GitHub. Environment variables in Vercel only take effect after redeployment — existing deployments continue using their old variable values.
Pro tip: For production, use SendGrid's Domain Authentication (SendGrid Dashboard → Settings → Sender Authentication → Domain Authentication) instead of Single Sender Verification. Authenticated domains dramatically improve email deliverability and let you send from any address at your domain.
Expected result: All three SendGrid environment variables appear in Vercel Dashboard. After redeployment, the API route accesses process.env.SENDGRID_API_KEY without errors and emails are successfully delivered.
Use SendGrid Dynamic Templates for Branded Emails
Use SendGrid Dynamic Templates for Branded Emails
For professional applications, hard-coding HTML in your API route works but is fragile. SendGrid's Dynamic Templates let you design beautiful, responsive email templates using a drag-and-drop editor in the SendGrid Dashboard, then use them from your API route by passing a template ID and data variables. In SendGrid Dashboard, go to Email API → Dynamic Templates and click Create Template. Name your template (e.g., 'Contact Form Confirmation') and click Create. Then click Add Version, choose a design (blank or use a template), and build your email layout in the visual editor. Use Handlebars syntax for dynamic variables: {{name}}, {{message}}, {{subject}}. Preview the template with sample data to see how it renders. Once your template is created, copy the Template ID (it looks like d-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX). Update your API route to use sgMail.send() with templateId and dynamicTemplateData instead of inline HTML. The dynamicTemplateData object maps template variables to their values. Dynamic Templates are version-controlled in SendGrid — you can update the design without changing your code. This is useful when non-technical team members need to update email copy or styling. They can edit the template in SendGrid's visual editor, and the updated design goes live immediately for the next send without any code deployment needed.
1// Using a SendGrid Dynamic Template instead of inline HTML2import sgMail from '@sendgrid/mail';3import { NextRequest, NextResponse } from 'next/server';45sgMail.setApiKey(process.env.SENDGRID_API_KEY!);67export async function POST(request: NextRequest) {8 try {9 const { name, email, subject, message } = await request.json();1011 const msg = {12 to: email,13 from: process.env.SENDGRID_FROM_EMAIL!,14 templateId: process.env.SENDGRID_TEMPLATE_ID!, // d-XXXXXXXXXXXXXXXX15 dynamicTemplateData: {16 name,17 email,18 subject: subject || 'Your inquiry',19 message,20 current_year: new Date().getFullYear(),21 },22 };2324 await sgMail.send(msg);25 return NextResponse.json({ success: true });26 } catch (error: any) {27 console.error('SendGrid template error:', error?.response?.body || error);28 return NextResponse.json({ error: 'Email send failed' }, { status: 500 });29 }30}Pro tip: Test your Dynamic Template by clicking 'Send Test' in SendGrid's template editor. This lets you verify the rendering and variable substitution before connecting it to your V0 app.
Expected result: Emails sent via Dynamic Templates use your custom-designed template from SendGrid. Updating the email design in the SendGrid visual editor takes effect immediately without code changes.
Test Delivery and Monitor in SendGrid
Test Delivery and Monitor in SendGrid
Before going live, test the complete email flow end to end. With your environment variables set and your Vercel deployment running, open your V0-generated contact form, fill in the fields, and submit. The email should arrive in your inbox within a few seconds. If the email does not arrive, check three places. First, Vercel function logs: Vercel Dashboard → your project → Functions → View Logs. Look for console.error() output from the catch block in your API route — it includes SendGrid's error response. Second, the SendGrid Activity Feed: SendGrid Dashboard → Activity Feed shows every attempted send with delivery status, click events, and error codes. Third, your spam folder — unverified sender domains often land in spam until domain authentication is configured. Common issues at this stage: 403 Forbidden means the from address is not a verified sender. 401 Unauthorized means the API key is invalid or missing. 400 Bad Request usually means a malformed message object (missing required fields, invalid email format). For ongoing monitoring in production, SendGrid's Dashboard provides delivery rate, bounce rate, spam report rate, and open rate metrics. Set up Email Notifications in SendGrid settings to alert you if delivery rates drop below a threshold — this is a sign that your emails are being filtered as spam, which usually requires domain authentication to fix. SendGrid also offers Inbound Parse (webhook for receiving emails) if you want to build two-way email workflows.
Pro tip: For complex email workflows with personalization, A/B testing, and detailed analytics, RapidDev's team can help configure SendGrid beyond basic transactional sends — including suppression list management, unsubscribe groups, and delivery optimization.
Expected result: Contact form submissions deliver emails successfully. SendGrid Activity Feed shows delivered status. Owner notification and user confirmation both arrive within seconds. Vercel function logs show no errors.
Common use cases
Contact Form with Auto-Confirmation
A V0-generated landing page includes a contact form. When submitted, the API route sends two emails: a notification to the site owner with the form contents, and a confirmation to the user acknowledging their message was received. This pattern is standard for agency sites, product pages, and service businesses.
Create a contact form with fields for name, email, subject, and message. Include a Submit button with a loading spinner. On successful submission, replace the form with a thank you message: 'Thanks [name]! We'll get back to you within 24 hours.' On error, show a red banner with 'Something went wrong, please try again.' POST the form data to /api/sendgrid/contact.
Copy this prompt to try it in V0
User Onboarding Welcome Email
When a new user signs up for a SaaS app built with V0, the signup API route sends a welcome email via SendGrid. The email includes the user's name, a getting-started guide, and a call to action button. Dynamic Templates in SendGrid allow designing these emails visually while keeping the API route code simple — just pass the template ID and substitution variables.
Build a signup form with name, email, and password fields. After successful form submission to /api/auth/signup, show a confirmation screen saying 'Check your email! We sent a welcome message to {email}.' Include a Resend Email link that POSTs to /api/sendgrid/welcome with the user's email.
Copy this prompt to try it in V0
Order Confirmation Email
After a successful Stripe payment, the webhook handler triggers a SendGrid email to confirm the order. The email includes the product name, amount charged, order ID, and a receipt link. This automated confirmation reassures customers immediately after purchase without requiring manual follow-up.
Create an order success page that displays the order summary including product name, quantity, subtotal, and total amount. Show a message 'A confirmation email has been sent to {email}'. Include a Download Receipt button and a Back to Shop button. The page should accept order data as URL query parameters from the Stripe redirect.
Copy this prompt to try it in V0
Troubleshooting
API route returns 403 Forbidden with 'The from address does not match a verified Sender Identity'
Cause: The email address in your SENDGRID_FROM_EMAIL environment variable is not verified in SendGrid. SendGrid requires all sending addresses to be either Single Sender verified or from an authenticated domain.
Solution: Go to SendGrid Dashboard → Settings → Sender Authentication → Single Sender Verification and add your from email address. Follow the verification link SendGrid sends to that address. For production, complete Domain Authentication instead for better deliverability.
Emails are sent successfully (API returns 200) but arrive in spam or promotions folder
Cause: Your sending domain is not authenticated in SendGrid, so emails appear to come from a SendGrid shared domain. Email clients flag these as likely spam.
Solution: Set up Domain Authentication in SendGrid Dashboard → Settings → Sender Authentication → Domain Authentication. This involves adding DNS records (CNAME, DKIM) to your domain's DNS settings. After verification, emails appear to come from your domain and have much better deliverability.
'Module not found: Can't resolve @sendgrid/mail' in Vercel build
Cause: The @sendgrid/mail package is not in your package.json dependencies, so Vercel's build process does not install it.
Solution: Add @sendgrid/mail to your package.json dependencies section. Commit and push to trigger a new Vercel build with the package installed.
1// package.json2{3 "dependencies": {4 "@sendgrid/mail": "^8.0.0",5 "next": "15.0.0",6 "react": "^19.0.0"7 }8}Dynamic Template variables show as literal {{name}} text in the received email
Cause: The dynamicTemplateData property is missing from the send call, or the variable names do not match the Handlebars {{variable}} syntax used in the template design.
Solution: Verify that your sgMail.send() call includes a dynamicTemplateData object with keys that exactly match the Handlebars variable names in your template. Variable names are case-sensitive — {{Name}} and {{name}} are different variables.
Best practices
- Never add NEXT_PUBLIC_ prefix to SENDGRID_API_KEY — this would expose your API key in the browser's JavaScript bundle.
- Set up Domain Authentication in SendGrid (not just Single Sender Verification) for production apps to maximize deliverability and avoid spam filtering.
- Always log SendGrid error responses using error?.response?.body — this gives the specific error message from SendGrid rather than just a generic JavaScript error.
- Use SendGrid Dynamic Templates for transactional emails so non-technical team members can update email content without code changes.
- Implement rate limiting on your email API routes to prevent form submission spam from burning through your SendGrid quota.
- Monitor SendGrid's Activity Feed weekly — a rising bounce rate or spam report rate is an early warning that domain reputation is declining.
- For order confirmation and financial emails, include a plain text version alongside the HTML to ensure delivery in environments that block HTML email.
- Use SendGrid's suppression groups to let users manage their own email preferences and unsubscribe from specific email types without unsubscribing from all communications.
Alternatives
Mailchimp is a better fit if you need a combined transactional plus marketing email platform with audience management and campaign builder, rather than a pure API-first email delivery service.
Mailgun is a developer-focused alternative with similar API patterns if you prefer its pricing model or need EU data residency for GDPR compliance.
Drip is an alternative if your email needs are primarily marketing automation and customer journeys for e-commerce rather than transactional triggered emails.
Frequently asked questions
Does V0 generate SendGrid integration code automatically?
V0 can generate the UI components and API route boilerplate when you describe the SendGrid integration in your prompt. Specify the API endpoint, request body shape, and that you want to use @sendgrid/mail. V0 will scaffold the import, setApiKey call, and send call. You still need to set your environment variables in Vercel manually and verify your sender identity in SendGrid.
How many emails can I send for free with SendGrid?
SendGrid's free tier allows 100 emails per day permanently — there is no monthly cap reset, it is 100 per day every day. This is enough for small contact forms and low-traffic apps. The Essentials plan starts at $19.95/month for 50,000 emails/month. For higher volumes, Pro plans are available. Note that the free tier does not include email scheduling, A/B testing, or dedicated IP addresses.
What is the difference between SendGrid and Mailgun for V0 projects?
Both have similar Node.js SDKs and API patterns for basic transactional email. SendGrid is owned by Twilio and is known for its deliverability reputation, visual email template editor, and marketing email features. Mailgun is more developer-focused with powerful log and analytics APIs. For pure transactional email in a V0 app, either works equally well — the choice often comes down to whether you want marketing email features (SendGrid) or detailed email logs (Mailgun).
Why do my emails land in spam even though SendGrid says they were delivered?
SendGrid marking an email as 'Delivered' means the receiving mail server accepted it, not that it reached the inbox. ISPs route emails to spam based on sender domain reputation, content, and authentication. Set up Domain Authentication in SendGrid to improve inbox placement. Also avoid spam trigger words in subject lines and ensure your content has a good text-to-image ratio.
Can I send attachments with SendGrid from my V0 app?
Yes, the @sendgrid/mail package supports file attachments via the attachments property in the message object. Provide the file content as a base64-encoded string, the MIME type, and the filename. Be aware that large attachments significantly increase email delivery time and may be blocked by receiving mail servers. For large files, consider sending a download link instead.
How do I test SendGrid emails locally without deploying to Vercel?
Create a .env.local file in your project root with SENDGRID_API_KEY, SENDGRID_FROM_EMAIL, and SENDGRID_TO_EMAIL set to your real SendGrid credentials. Run npm run dev and trigger email sends from the local development server at localhost:3000. Real emails are sent through SendGrid even in local development as long as the API key is valid — there is no sandbox mode by default.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation