A proof-of-concept sandbox for adopting react-email with custom reusable email components and Storybook integration.
- Custom Email Components: Pre-built Header, Footer, and Button components
- Storybook Integration: Visual documentation and interactive playground for email components
- Live Preview Sandbox: Real-time email preview with configurable props
- Tailwind CSS Support: Modern styling with email-safe Tailwind classes
- Node.js 18+
- npm
npm installStart the development server:
npm run devOpen http://localhost:5173 to view the email preview sandbox.
Launch Storybook for component development:
npm run storybookOpen http://localhost:6006 to view the component library.
src/
├── components/
│ └── email/
│ ├── Header.tsx # Email header with logo and navigation
│ ├── Footer.tsx # Email footer with social links and legal
│ ├── Button.tsx # CTA button with multiple variants
│ └── index.ts # Component exports
├── emails/
│ └── WelcomeEmail.tsx # Example email template
├── App.tsx # Preview sandbox application
└── main.tsx
stories/
├── EmailPreview.tsx # Storybook email preview wrapper
├── Header.stories.tsx # Header component stories
├── Footer.stories.tsx # Footer component stories
└── Button.stories.tsx # Button component stories
import { Header } from "./components/email";
<Header
companyName="Acme Inc"
logoUrl="https://example.com/logo.png"
links={[
{ label: "Products", href: "https://example.com/products" },
{ label: "Support", href: "https://example.com/support" },
]}
/>Props:
companyName(required): Company or brand namelogoUrl: URL to logo imagelogoAlt: Alt text for logolinks: Array of navigation linksbackgroundColor: Background color (default: white)
import { Footer } from "./components/email";
<Footer
companyName="Acme Inc"
address="123 Main St, San Francisco, CA"
socialLinks={[
{ platform: "twitter", href: "https://twitter.com/acme" },
{ platform: "linkedin", href: "https://linkedin.com/company/acme" },
]}
privacyUrl="https://example.com/privacy"
unsubscribeUrl="https://example.com/unsubscribe"
/>Props:
companyName(required): Company nameaddress: Physical addresssocialLinks: Array of social media linksunsubscribeUrl: Unsubscribe linkprivacyUrl: Privacy policy linktermsUrl: Terms of service linkyear: Copyright year
import { Button } from "./components/email";
<Button href="https://example.com" variant="primary" size="lg">
Get Started
</Button>Props:
href(required): Button link URLvariant:"primary"|"secondary"|"outline"|"ghost"size:"sm"|"md"|"lg"fullWidth: Make button full widthchildren: Button label
- Create a new file in
src/emails/:
// src/emails/NewsletterEmail.tsx
import { Html, Head, Body, Container } from "@react-email/components";
import { Tailwind } from "@react-email/tailwind";
import { Header, Footer, Button } from "../components/email";
export const NewsletterEmail = () => {
return (
<Html>
<Head />
<Tailwind>
<Body className="bg-gray-100">
<Container className="mx-auto max-w-xl bg-white">
<Header companyName="My Company" />
{/* Your email content */}
<Footer companyName="My Company" />
</Container>
</Body>
</Tailwind>
</Html>
);
};- Add it to the sandbox in
App.tsxor create a story instories/.
| Command | Description |
|---|---|
npm run dev |
Start development server |
npm run build |
Build for production |
npm run preview |
Preview production build |
npm run storybook |
Start Storybook |
npm run build-storybook |
Build Storybook static site |
npm run lint |
Run ESLint |
- React Email - Email component framework
- Vite - Build tool
- Storybook - Component documentation
- Tailwind CSS - Utility-first CSS
MIT