React Email
An AI-powered email generator that uses OpenUI Lang to render 44 React Email components from natural language descriptions.
OpenUI Lang isn't limited to chat interfaces — it can power any domain-specific UI generator. This example uses React Email components as the rendering target, letting users describe emails in plain English and see them rendered live. The @openuidev/react-email package ships 44 email components built with defineComponent, a ready-to-use emailLibrary, and a system prompt with examples and design rules — so the LLM generates well-structured, email-client-compatible HTML out of the box.
Building an email library with OpenUI Lang
Each email component wraps a React Email primitive with inline styles (required by email clients that strip <style> tags). Here's a simplified example:
const EmailButton = defineComponent({
name: "EmailButton",
props: z.object({
label: z.string(),
href: z.string(),
backgroundColor: z.string().optional(),
}),
description: "Email call-to-action button with link.",
component: ({ props }) => (
<Button
href={props.href as string}
style={{
backgroundColor: (props.backgroundColor as string) ?? "#5F51E8",
color: "#ffffff",
borderRadius: "6px",
padding: "12px 24px",
}}
>
{props.label as string}
</Button>
),
});All 44 components are assembled into emailLibrary via createLibrary. Consumers import the library and prompt options — individual components are internal:
import { emailLibrary, emailPromptOptions } from "@openuidev/react-email";
// Generate the system prompt (includes examples + design rules)
const systemPrompt = emailLibrary.prompt(emailPromptOptions);
// Render streamed OpenUI Lang into email components
<Renderer response={openuiCode} library={emailLibrary} isStreaming={isStreaming} />;Once streaming completes, the useEmailRendering hook calls render() from @react-email/render with { pretty: true } client-side to produce formatted HTML for the "Copy HTML" button.
See Defining Components for the full defineComponent API.
Architecture
Browser (email editor) -- POST /api/chat --> Next.js route --> OpenAI
<-- SSE stream -- (OpenUI Lang)The client sends a conversation to /api/chat. The API route loads a pre-generated system-prompt.txt (built from emailLibrary.prompt(emailPromptOptions)), forwards messages to the LLM with streaming, and returns SSE events. On the client, emailLibrary maps each OpenUI Lang node to a React Email component that renders progressively as tokens arrive.
The key difference from other examples: the output isn't interactive UI — it's static email content. The split-view editor shows a live preview on the right and formatted HTML on the left, with copy buttons for both the HTML and the subject line.
Project layout
examples/react-email/
|- src/app/ # Next.js app (layout, page, API route)
|- src/components/
| |- composePage/ # Landing page with conversation starters
| |- emailEditor/ # Split view (top bar, HTML panel, preview, input)
| |- loadingDots.tsx # Loading animation (shared)
| |- session.ts # Session persistence (shared)
|- src/hooks/ # Theme, clipboard, auto-scroll, email rendering
|- src/generated/ # Auto-generated system prompt
packages/react-email/
|- src/components/ # 44 email components (defineComponent)
|- src/index.ts # Library, groups, examples, rules
|- src/unions.ts # Component type unionsRun the example
Run these commands from examples/react-email.
- Install dependencies:
cd examples/react-email
pnpm install- Create a
.env.localfile with your API key:
OPENAI_API_KEY=sk-...- Start the dev server:
pnpm devThis auto-generates the system prompt from the email component library and starts the Next.js dev server.