OpenAI Integration
Relevant source files
The following files were used as context for generating this wiki page:
OpenAI integration within Send Again powers the AI Compose feature, which allows users to generate or revise HTML email fragments based on natural language descriptions. This system, internally referred to as "Vibe," leverages GPT models to transform user instructions into production-ready HTML with inline styles suitable for various email clients.
The integration is scoped to two primary targets: generating the main body of an email and creating or editing workspace-specific footers. By providing context such as current drafts, workspace identifiers, and website URLs, the system ensures that the generated content remains relevant to the user's specific brand identity.
Sources: README.md:9-10, src/app/api/vibe/route.ts:5-13
Architecture and Data Flow
The OpenAI integration is implemented as a specialized API route that acts as a bridge between the frontend application and OpenAI's Chat Completions API. The backend manages prompt construction, security validation, and response sanitization to ensure that the output is safe, raw HTML.
Request Lifecycle
When a user initiates a "Vibe" generation from the UI, the application sends a POST request to /api/vibe. The system performs the following steps:
- Authentication & Authorization: Validates the user's session and confirms they have access to the specified
workspaceId. - Prompt Construction: Builds specialized system and user prompts based on the generation
target(email body or footer). - External API Call: Dispatches a request to
api.openai.com/v1/chat/completionsusing the configured API key and model. - Response Processing: Extracts the generated text, strips any Markdown code fences, and returns the raw HTML to the frontend.
Sources: src/app/api/vibe/route.ts:98-156, src/app/app/page.tsx:1283-1323
Sequence of AI Content Generation
The following diagram illustrates the interaction between the User Interface, the internal Vibe API, and the OpenAI service.
Configuration and Environment
The integration requires specific environment variables to be set in the .env.local file. If the OPENAI_API_KEY is missing, the generation endpoint will return a 500 error, and the UI will reflect the inability to generate drafts.
| Variable | Required | Default | Description |
|---|---|---|---|
OPENAI_API_KEY | No (Optional) | — | The API key used to authenticate requests to OpenAI. |
OPENAI_MODEL | No | gpt-4.1-mini | The specific model version to use for generation. |
Sources: README.md:129-130, src/app/api/vibe/route.ts:118-125
Prompt Engineering Logic
The system uses distinct "System Prompts" to constrain the AI's behavior depending on the intended use of the HTML fragment. This ensures the AI does not include unnecessary tags (like <html> or <body>) that would break email client rendering when combined with other templates.
Target-Based constraints
| Target | Specific Instructions |
|---|---|
| Email Body | Generate HTML body fragments with inline styles; readable in email clients; do not include / tags; do not include footer/unsubscribe sections. |
| Footer | Generate HTML footer fragments with inline styles; must include {{unsubscribe_url}}; may include {{workspace_url}}; do not include / tags. |
Sources: src/app/api/vibe/route.ts:64-88
Prompt Construction Functions
The logic for building the context sent to the AI is handled by two internal functions:
buildSystemPrompt(target: VibeTarget): Defines the personas and technical constraints.buildUserPrompt(data): Aggregates workspace data, the user's instruction, and any existing HTML draft to be revised.
// Example of context aggregation for the User Prompt
function buildUserPrompt({ workspaceId, instruction, currentHtml, from, websiteUrl, target }) {
return [
`Workspace: ${workspaceId}`,
`From: ${from || `noreply@${workspaceId}`}`,
`Website: ${websiteUrl || `https://${workspaceId}`}`,
`Target: ${target}`,
"",
"Instruction:",
instruction,
"",
currentHtml ? `Current HTML draft to revise:\n${currentHtml}` : "No current draft exists. Create from scratch.",
"",
"Return only HTML.",
].join("\n");
}
Sources: src/app/api/vibe/route.ts:90-115
Implementation Details
Response Sanitization
OpenAI models often return code within Markdown blocks (e.g., ```html). The system includes a utility function stripCodeFences to ensure only the inner content is returned to the user, preventing Markdown syntax from appearing in the email preview.
Sources: src/app/api/vibe/route.ts:55-62
Frontend Integration
In the application's Compose and Settings tabs, the "Vibe" feature is exposed via text areas where users provide instructions. The UI manages separate states for "body vibes" and "footer vibes," including loading indicators (bodyVibeBusy) and status messages that indicate which model performed the update.
Sources: src/app/app/page.tsx:1283-1323, src/app/app/page.tsx:1625-1647
Conclusion
The OpenAI integration provides a critical productivity layer for Send Again, automating the complex task of writing email-compatible HTML. By centralizing prompt logic and sanitization on the server, the system maintains a high standard of output quality while ensuring that generated content adheres to the technical requirements of modern email clients.