Antigravity transactional email does not need to become a side quest. When your agent-built app reaches the point where a new user needs a welcome message or a password-reset link, the practical requirement is simple: keep the email API key on the server, call a documented sending endpoint, and make the workflow safe to retry.
This page gives you a prompt you can paste into Antigravity, the resulting TypeScript pattern, and the production details that separate “an email appeared once” from an integration you can keep.
The small feature that makes an app feel real
A lot of apps are now created through a fast loop: describe a product idea, let an agent scaffold screens and data models, connect authentication, then refine the workflow in the browser. That is an excellent way to get from blank repository to usable prototype. But email is often the first feature that leaves your app and reaches a person somewhere else.
A welcome email confirms that registration worked. A password reset is the recovery path when a customer cannot get back in. A receipt or account alert can be the record a person relies on after they close the tab. These messages are transactional because they are triggered by a person’s account activity or an application event—not because a marketer selected a list.
That distinction affects implementation. You do not need a giant campaign system just to tell a new customer that their account is ready. You need a small, explicit server-side capability that your application can call with a recipient, sender, subject, HTML body, and plain-text fallback.
The goal is not to make Antigravity send email directly from a chat panel. The goal is to have Antigravity build a normal, reviewable application feature: a server route or server function that calls Volanea’s transactional API without exposing a secret in the browser.
What Antigravity changes—and what it does not
Antigravity is designed around agents that can reason over a codebase, use tools, work through tasks, and produce artifacts. That changes the speed at which you can add a feature, because you can describe the behavior, constraints, files, and acceptance criteria rather than typing every line yourself.
It does not change the basic security boundary of a web application. A browser bundle is visible to every visitor. An email API key placed in client-side JavaScript, a mobile app bundle, a public repository, or a pasted screenshot should be treated as compromised. Your coding agent can write a fetch() call quickly, but it still needs to place that call in code that runs only on your server, serverless function, or trusted worker.
That gives you a useful division of responsibilities:
- Antigravity helps plan, generate, edit, and test the implementation.
- Your app server decides whether an event is legitimate enough to send an email.
- Volanea accepts the transactional send request and handles the email-sending pipeline.
- You own the sender domain, user-facing copy, secrets, and final review.
This is intentionally ordinary architecture. The emerging ecosystem around agent coding can make it tempting to look for a native integration for every service. You do not need to wait for a dedicated Antigravity plugin to send email. A documented HTTPS API is enough for an agent to build a dependable integration.
The fastest safe path for Antigravity transactional email
Before asking an agent to edit your project, make three decisions. They remove ambiguity, make the generated code more consistent, and reduce the odds that the agent invents assumptions about your stack.
1. Pick the event that sends the email
Start with one event. Good first choices include:
- A user completes signup and verifies their email address.
- A user requests a password-reset email.
- A checkout succeeds and the purchaser needs a receipt.
- An account owner needs an important security or billing alert.
Avoid making the first task “add all email.” It is too vague. A focused request lets the agent find the correct registration action, identify where the user record is available, and add a single call with a clear success and failure behavior.
2. Decide where server code lives
The exact file depends on your framework, but the pattern is universal. Next.js might use a route handler or server action. Remix might use an action. Express or Fastify might use a route. A worker-based app might call Volanea from a protected worker endpoint. The important condition is that VOLANEA_API_KEY is read only in server-side code.
If your project does not have a backend yet, ask Antigravity to create the smallest server endpoint that fits the existing deployment model. Do not ask it to add a separate long-running service solely to send one welcome email unless your architecture genuinely requires it.
3. Use a sender you control
Your from address must use a domain you have verified for sending. That means a placeholder such as hello@yourapp.example belongs in the code example only until you configure your real domain. A sender identity is part of deliverability, support, and brand trust—not just a string displayed in an inbox.
For setup steps, endpoint details, and current API fields, keep the agent pointed at the email API reference and setup guides. Documentation is a better source of truth than an agent’s memory, especially when a feature is being built quickly.
A prompt to paste into Antigravity
A productive agent prompt describes the desired outcome, limits, security boundary, and proof of completion. Here is a framework-neutral prompt for a TypeScript app. Replace the bracketed terms with the names used in your project.
Add transactional welcome email sending with Volanea after a new user is successfully created in this app.
First inspect the repository and identify:
- the framework and server-side routing convention,
- the signup or user-creation flow,
- how environment variables are loaded,
- the project’s existing validation and test style.
Then implement the smallest production-safe solution:
1. Create a server-only email helper named sendWelcomeEmail.
2. Read VOLANEA_API_KEY and EMAIL_FROM from server environment variables only.
3. Send through POST https://api.volanea.com/v1/send using Authorization: Bearer <key>.
4. Include a stable Idempotency-Key derived from the new user ID so a retry does not create duplicate welcome emails.
5. Send to the new user’s email address with a clear subject, HTML body, and plain-text fallback.
6. Do not expose the API key in browser code, logs, client responses, or tests.
7. If sending fails, log a redacted server-side error and preserve the successful signup result; do not block account creation unless the existing project has an explicit transactional-outbox pattern.
8. Add a focused test that mocks fetch and verifies the endpoint, authorization header, idempotency key, and request payload.
9. Show me the files changed, explain where the email is triggered, and list the environment variables I must configure.
Use the existing code style and do not add an SDK unless the repository already uses one.
This prompt is detailed on purpose. It tells the agent not merely to produce a request, but to inspect the existing application before deciding where it belongs. It also makes clear that a welcome email is usually secondary to a successful account creation. A transient email-provider error should not normally tell a legitimate new customer that signup failed.
If you are implementing password resets, alter the acceptance criteria. The email should be sent only after the app creates a short-lived, single-use reset token or link. The reset token should not be logged, and the endpoint should return the same generic response whether an account exists or not. That reduces account-enumeration risk.
The resulting server-side TypeScript code
Below is a compact helper that an Antigravity task can adapt to a server route, action, or service in a TypeScript application. It uses the Volanea single-message send endpoint, bearer authentication, and an idempotency key. The from, to, subject, html, and text fields keep the message readable across mail clients and accessible when HTML is unavailable.
// src/server/email/send-welcome-email.ts
type WelcomeEmailInput = {
userId: string;
email: string;
firstName?: string | null;
};
function requiredEnv(name: string): string {
const value = process.env[name];
if (!value) {
throw new Error(`Missing required environment variable: ${name}`);
}
return value;
}
function escapeHtml(value: string): string {
return value
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
export async function sendWelcomeEmail({
userId,
email,
firstName,
}: WelcomeEmailInput): Promise<void> {
const apiKey = requiredEnv("VOLANEA_API_KEY");
const from = requiredEnv("EMAIL_FROM");
const name = firstName?.trim() || "there";
const safeName = escapeHtml(name);
const response = await fetch("https://api.volanea.com/v1/send", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
"Idempotency-Key": `welcome-email:${userId}`,
},
body: JSON.stringify({
from,
to: [email],
subject: "Welcome to Acme",
html: `
<main style="font-family: Arial, sans-serif; line-height: 1.5; color: #171717;">
<h1>Welcome, ${safeName}.</h1>
<p>Your Acme account is ready.</p>
<p><a href="https://app.example.com">Open your dashboard</a></p>
</main>
`,
text: `Welcome, ${name}. Your Acme account is ready. Open your dashboard: https://app.example.com`,
}),
});
if (!response.ok) {
const details = await response.text();
throw new Error(
`Volanea welcome email request failed with ${response.status}: ${details.slice(0, 500)}`,
);
}
}
Then call it after the user has been created and committed successfully. The following is intentionally pseudocode around the database call because every authentication stack has a different user-creation API:
const user = await users.create({ email, passwordHash, firstName });
try {
await sendWelcomeEmail({
userId: user.id,
email: user.email,
firstName: user.firstName,
});
} catch (error) {
logger.error({ err: error, userId: user.id }, "Welcome email was not accepted");
}
return user;
The ordering matters. Create the account first. Then attempt to send. If the send fails, the user record still exists and your application can retry from a job, an outbox table, or an operations workflow. Do not accidentally make email delivery a hidden dependency of your core signup transaction.
Environment variables
Use server-side environment variables such as:
VOLANEA_API_KEY=sk_live_replace_with_your_secret
EMAIL_FROM=Acme <hello@your-verified-domain.com>
Never prefix the API key with a convention that makes it available to the browser bundle. The exact prefix varies by framework—some expose variables with names such as NEXT_PUBLIC_ or VITE_—but the rule is uncomplicated: a secret email key should not have a public prefix.
Why idempotency matters when agents add integrations
An agent-generated feature can be perfectly valid code and still create duplicate messages if retries are not considered. Network requests fail in ambiguous ways. Your server might time out after Volanea accepted a request. A serverless platform might retry an invocation. A webhook provider might deliver the same event more than once.
The Idempotency-Key header gives one logical action a stable identity. In the welcome-email example, welcome-email:${userId} means that repeated attempts to send the same user’s initial welcome message can be recognized as the same operation rather than separate sends.
The key should represent the business event, not a random request attempt. These are useful patterns:
welcome-email:user_123password-reset:user_123:reset_456receipt:order_987security-alert:session_123:login
Do not reuse the same key for messages that should be distinct. If a customer places two orders, each receipt needs its own key. If they request a reset twice, each separately issued reset token should have a separate key.
This is a particularly important instruction for agent coding because agents often add generic retry logic. Retries can be good. Retrying without idempotency can turn a temporary network problem into three welcome emails, three receipts, or three security alerts.
Welcome email versus password-reset email
Both are transactional emails, but they have different failure modes and security requirements.
Welcome emails can be helpful, not authoritative
A welcome email may introduce the product, point to the dashboard, or explain the next step. It should not contain a secret that gives someone control of the account. If the welcome email fails, the user should still be able to sign in or request help.
Keep the copy short. Email clients crop long messages, and a new user does not need an onboarding manual in their inbox. One clear action is usually enough: open the app, confirm the address, complete a profile, or invite a teammate.
Password resets are security workflows
A password reset should use an expiring, single-use token generated and stored by your own application. The email merely carries a link to the reset page. Volanea delivers the message; it should not be treated as the system that decides whether a token is valid.
Your Antigravity prompt for resets should additionally require:
- a cryptographically strong token or token-derived URL created on the server;
- a short expiration time appropriate to your security policy;
- one-time use after a successful password change;
- generic request responses such as “If an account exists, we sent instructions”; and
- no reset tokens, raw API keys, or full URLs with secrets in application logs.
Do not put a password, temporary password, or long-lived access token in an email. An inbox is not a secret vault.
Testing the integration before you call it done
The first proof is not “the build passed.” The first proof is that the server code produces the correct request without exposing the key. Start with a unit test that mocks fetch, then run a controlled end-to-end send to an inbox you own.
Here is the shape of a focused test in a Vitest-style project:
import { describe, expect, it, vi } from "vitest";
import { sendWelcomeEmail } from "./send-welcome-email";
describe("sendWelcomeEmail", () => {
it("sends a retry-safe Volanea request", async () => {
process.env.VOLANEA_API_KEY = "sk_test_example";
process.env.EMAIL_FROM = "Acme <hello@example.com>";
const fetchMock = vi.fn().mockResolvedValue({
ok: true,
status: 200,
text: async () => "",
});
vi.stubGlobal("fetch", fetchMock);
await sendWelcomeEmail({
userId: "user_123",
email: "person@example.com",
firstName: "Sam",
});
expect(fetchMock).toHaveBeenCalledWith(
"https://api.volanea.com/v1/send",
expect.objectContaining({
method: "POST",
headers: expect.objectContaining({
Authorization: "Bearer sk_test_example",
"Idempotency-Key": "welcome-email:user_123",
}),
}),
);
});
});
A test like this catches accidental changes to the endpoint, authentication, or idempotency behavior. It should never print a real secret to test output. In continuous integration, use a test key or mock the network entirely.
Then test the live path deliberately. Confirm the sender domain is configured, send to an address you control, inspect the rendered HTML and plain-text version, click the link, and check that the application behavior matches the message. A request accepted by an API is not automatically proof that a recipient saw it in their inbox, so review delivery events and your own mailbox testing as part of the release.
A practical delivery checklist for vibe-coded apps
Agent-built applications can move quickly enough that operational details get deferred. That is understandable during a prototype, but transactional email is often the first customer-facing system where those deferred details surface.
Before you call the feature production-ready, verify the following:
- Your sender domain is authenticated and the
EMAIL_FROMaddress uses that domain. - The Volanea key exists only in the server runtime’s secret store or environment configuration.
- The browser never calls the Volanea endpoint directly.
- Each event has a meaningful idempotency key.
- Welcome emails, receipts, and alerts include a plain-text fallback.
- User-provided values inserted into HTML are escaped or rendered through a trusted templating system.
- Password-reset links are short-lived and single-use.
- You have a decision for failed sends: log, queue, retry, or alert.
- Your logging redacts authorization headers, API keys, reset tokens, and personal data where appropriate.
- You test with an inbox you control before enabling the flow for customers.
You can also run candidate addresses through the free email address verification tool when validating user input or cleaning a pre-launch list. Verification can help catch obvious address problems, but it does not replace permission, suppression handling, or a real opt-in process.
Should you use MCP or tool calling?
Model Context Protocol and similar tool-calling approaches can be useful in an agentic workflow. An MCP server can expose narrowly defined tools—such as checking a sending-domain status, rendering a template, or performing a controlled test send—after authentication. That can save context switching while you build.
But it is not a reason to remove the server-side integration from your app. Tool calling is primarily a development workflow capability. Your deployed product still needs its own secure path from a signup event or reset request to the email API. The customer’s browser should not receive an agent credential, an MCP credential, or your production sending key.
Treat an MCP connection as optional assistance, not application architecture. Before granting an agent access to any email account or production keys, understand what tools it can invoke, what permissions it receives, whether it can send live messages, and how it records activity. Start with least privilege and non-production credentials whenever possible.
For a thin, emerging Antigravity integration ecosystem, this conservative approach is an advantage. You can use Antigravity today because the core integration is portable: standard server code, an environment variable, an HTTPS request, and tests. If your preferred agent tooling changes later, the email feature remains ordinary code in your repository.
From one send to a durable email capability
A welcome email is a useful first integration, not the finish line. As your app grows, a few engineering choices keep email from becoming a collection of unrelated fetch() calls scattered through route handlers.
Centralize the provider boundary
Keep Volanea calls in one small module or service. Product features should call functions such as sendWelcomeEmail, sendPasswordResetEmail, or sendReceiptEmail, rather than assembling raw request bodies everywhere. This makes it easier to test message content, update sender rules, and introduce templates later.
Separate event creation from delivery attempts
For a more durable system, write an event to a database outbox when the business transaction succeeds. A worker reads the outbox and sends the message. If the worker encounters a temporary failure, it can retry with the same idempotency key. This pattern is not mandatory for an early product, but it becomes valuable when email is tied to orders, account security, or other events you cannot casually lose.
Make failure visible without alarming users unnecessarily
A welcome email failure can be an internal alert or a retry job. A password-reset failure may require stronger monitoring because it blocks account recovery. Think about the user impact of each message type, then choose alerting and retry behavior accordingly.
The important second-order implication is that “email works” is not a boolean. There is acceptance by the API, queueing, provider handoff, bounce handling, suppression handling, and eventually recipient mailbox placement. Build enough observability to answer a support question without manually searching through server logs.
Conclusion: give your agent a clear boundary
The best Antigravity transactional email setup is deliberately unglamorous. Ask the agent to inspect your project, add a server-only Volanea helper, use a verified sender, include text and HTML, apply an idempotency key, test the request, and keep the signup or reset flow secure.
That approach gets you to the outcome that matters: a person signs up, requests recovery, or completes a purchase—and receives the right message without your credentials leaking into the client or retries creating confusing duplicates. Antigravity accelerates the implementation; clear constraints make the result trustworthy.
FAQ
Can Antigravity send Volanea email directly from the browser?
No. Your browser should not hold a Volanea API key. Have Antigravity create server-side code that reads the secret from the server environment and calls the email API there.
Do I need a native Antigravity plugin to use Volanea?
No. A standard HTTPS API integration works without a dedicated plugin. MCP or tool-calling connections can be optional development aids, but your shipped application should still use a normal server-side email integration.
What is the first transactional email I should add?
A welcome email is usually the simplest first feature because it is low risk and easy to test. Password resets are also essential, but require careful token creation, expiration, single-use behavior, and generic responses to avoid account enumeration.
Why does the example include an Idempotency-Key?
Retries and duplicate event delivery happen. A stable idempotency key lets repeated attempts represent one logical send instead of creating duplicate emails for the same welcome event, order, or reset request.
Can I use the same code for receipts and alerts?
Yes. Keep the provider call in one server-side module, then create focused functions for each event type. Use a distinct idempotency key for each business event, tailor failure handling to the message’s importance, and keep sensitive data out of logs and email bodies.