12 Ecommerce Email Templates / Editorial
Free React Email Newsletter Template
Build an editorial newsletter email with React Email — lead article, short stories and an event. Customize and export TSX, free.
- Sample subject
- The Dispatch No. 14
- Format
- React Email TSX · Free

Template details
What this newsletter template includes
Build an editorial newsletter email with React Email — lead article, short stories and an event. Customize and export TSX, free. The source is standard TypeScript and React Email, so it can be sent with Resend or rendered to HTML for another email provider.
- Production-ready editorial email structure
- Editable in the visual React Email playground
- Free TSX source for personal and commercial projects
How to use it
- 1. Customize the copy and styles in the playground above.
- 2. Export or copy the typed TSX source.
- 3. Pass dynamic props and send it from a server route with your email provider.
React Email TSX source
Free for personal, commercial, and client projects under the site license.
View full source code
import * as React from 'react';
import {
Band,
Brand,
Columns,
Display,
EmailImage,
EmailLayout,
Eyebrow,
OutlineButton,
Plate,
Prose,
Rule,
SectionTitle,
Spacer,
Subtitle,
TextLink,
} from './components';
export interface NewsletterStory {
eyebrow: string;
title: string;
body: string;
image: EmailImage;
link: { label: string; href: string };
/** Which side the photograph sits on. */
imageOn?: 'left' | 'right';
}
export interface NewsletterEmailProps {
brand?: Brand;
subject?: string;
preview?: string;
eyebrow?: string;
headline?: React.ReactNode;
/** The long read. Body paragraphs set justified, as the house style asks. */
lead?: {
image: EmailImage;
title: string;
body: string[];
cta: { label: string; href: string };
};
/** Shorter pieces, alternating sides. */
stories?: NewsletterStory[];
/** What is on next. */
event?: {
eyebrow: string;
title: string;
body: string;
cta: { label: string; href: string };
};
}
/**
* Newsletter — a lead article with justified columns, two short pieces that
* alternate sides, and an event at the end. The one template in the bundle
* that is not trying to sell anything directly.
*/
export function NewsletterEmail({
brand,
subject = 'The Dispatch No. 14',
preview = 'On water, on Ethiopian harvests, and on the myth of the perfect grinder.',
eyebrow = 'The Dispatch · No. 14 · August 2026',
headline = (
<>
Notes from
<br />
the roastery
</>
),
lead = {
image: {
src: 'https://images.unsplash.com/photo-1517705008128-361805f42e86?w=1200&h=600&q=75&auto=format&fit=crop',
alt: 'Pour over brewing',
width: 600,
height: 300,
},
title: 'Your water is the problem',
body: [
'A cup of coffee is about 98.5% water, and most people are brewing with whatever comes out of the tap. Hard water flattens acidity and mutes the top of the cup. Very soft water pulls too much and turns everything hollow and sour.',
'The target is roughly 150 ppm total dissolved solids with a little magnesium in it. A cheap filter jug gets most people close enough. We ran the same Ethiopian through four waters last month and the difference was larger than a twenty-degree roast change, which was not the result we expected.',
],
cta: { label: 'Read the whole thing', href: '#' },
},
stories = [
{
eyebrow: 'From origin',
title: 'The Guji harvest came in early',
body: 'Two weeks ahead of last year, and cleaner on the table. Tadesse sent photos of the drying beds at 6am. We bought more than we planned to.',
image: {
src: 'https://images.unsplash.com/photo-1524350876685-274059332603?w=1200&h=420&q=75&auto=format&fit=crop',
alt: 'Green coffee in sacks',
width: 600,
height: 210,
},
link: { label: 'Read the harvest note', href: '#' },
imageOn: 'left',
},
{
eyebrow: 'Equipment',
title: 'You do not need a better grinder',
body: 'You probably need to clean the one you own and stop buying pre-ground on the weeks you are busy. We tested a $60 hand grinder against a $900 machine on filter. It was closer than anyone wanted.',
image: {
src: 'https://images.unsplash.com/photo-1610889556528-9a770e32642f?w=1200&h=420&q=75&auto=format&fit=crop',
alt: 'Grinder and espresso',
width: 600,
height: 210,
},
link: { label: 'See the results', href: '#' },
imageOn: 'right',
},
],
event = {
eyebrow: 'Coming up',
title: 'Public cupping · 12 September',
body: 'Six lots on the table, ten seats, free, and considerably less serious than the word “cupping” suggests. Wythe Avenue, 9am, coffee before speaking.',
cta: { label: 'Reserve a seat', href: '#' },
},
}: NewsletterEmailProps = {}) {
return (
<EmailLayout brand={brand} subject={subject} preview={preview}>
<Band padding="36px 40px 22px" align="center">
<Eyebrow>{eyebrow}</Eyebrow>
<Display size={40}>{headline}</Display>
</Band>
<Band padding="0 40px">
<Rule />
</Band>
<Band padding="26px 40px 30px">
<Plate {...lead.image} />
<Spacer height={20} />
<SectionTitle>{lead.title}</SectionTitle>
{lead.body.map((paragraph, index) => (
<Prose
key={index}
lineHeight={1.68}
margin={index === lead.body.length - 1 ? '0 0 16px' : '0 0 14px'}
justify
>
{paragraph}
</Prose>
))}
<OutlineButton href={lead.cta.href}>{lead.cta.label}</OutlineButton>
</Band>
{stories.map((story, index) => {
const text = (
<>
<Eyebrow>{story.eyebrow}</Eyebrow>
<Subtitle>{story.title}</Subtitle>
<Prose size={14} margin="0 0 12px">
{story.body}
</Prose>
<TextLink href={story.link.href}>{story.link.label}</TextLink>
</>
);
const plate = <Plate {...story.image} />;
const last = index === stories.length - 1;
return (
<React.Fragment key={index}>
<Band padding="0 40px">
<Rule />
</Band>
<Band padding={last ? '28px 40px 34px' : '28px 40px'}>
<Columns
left={story.imageOn === 'right' ? text : plate}
right={story.imageOn === 'right' ? plate : text}
/>
</Band>
</React.Fragment>
);
})}
<Band tone="dark" align="center">
<Eyebrow tone="dark">{event.eyebrow}</Eyebrow>
<SectionTitle tone="dark">{event.title}</SectionTitle>
<Prose
tone="dark"
size={14}
lineHeight={1.65}
margin="0 auto 22px"
maxWidth={400}
>
{event.body}
</Prose>
<OutlineButton href={event.cta.href} tone="dark" align="center">
{event.cta.label}
</OutlineButton>
</Band>
</EmailLayout>
);
}
export default NewsletterEmail;
Related templates
More from 12 Ecommerce Email Templates.


