12 Ecommerce Email Templates / Lifecycle
Free React Email Abandoned Cart Template
Build an abandoned cart recovery email with React Email. Line items, totals and objection handling — customize and export TSX for free.
- Sample subject
- You left two bags in the cart
- Format
- React Email TSX · Free

Template details
What this abandoned cart template includes
Build an abandoned cart recovery email with React Email. Line items, totals and objection handling — customize and export TSX for 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 lifecycle 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,
Centered,
Display,
EmailLayout,
Eyebrow,
LineItem,
LineItems,
Note,
NumberedList,
OutlineButton,
Prose,
SectionTitle,
Spacer,
TotalRow,
Totals,
} from './components';
export interface AbandonedCartEmailProps {
brand?: Brand;
subject?: string;
preview?: string;
eyebrow?: string;
headline?: React.ReactNode;
intro?: string;
items?: LineItem[];
totals?: TotalRow[];
cta?: { label: string; href: string };
/** The line under the button — how long the cart is held. */
hold?: string;
/** Objection handling, on the deep ground. */
reasons?: {
eyebrow: string;
title: string;
items: string[];
};
signoff?: string;
}
/**
* Abandoned cart — the cart itemised and totalled, the reasons to finish it,
* and an offer to fix whatever stopped them. No countdown, no manufactured
* scarcity beyond what is true.
*/
export function AbandonedCartEmail({
brand,
subject = 'You left two bags in the cart',
preview = 'We held them. We are not saving them forever, but we held them.',
eyebrow = 'Still warm',
headline = (
<>
Your cart is
<br />
getting stale
</>
),
intro = 'Nothing has been charged. Everything is still in stock, for now. Solstice is down to the last of the first roast.',
items = [
{
image: {
src: 'https://images.unsplash.com/photo-1559056199-641a0ac8b55e?w=168&h=168&q=75&auto=format&fit=crop',
alt: 'Solstice',
},
name: 'Solstice',
meta: '12 oz · Whole bean',
quantity: 1,
price: '$21.00',
},
{
image: {
src: 'https://images.unsplash.com/photo-1447933601403-0c6688de566e?w=168&h=168&q=75&auto=format&fit=crop',
alt: 'Night Shift',
},
name: 'Night Shift',
meta: '12 oz · Ground for filter',
quantity: 2,
price: '$38.00',
},
],
totals = [
{ label: 'Subtotal', value: '$59.00' },
{ label: 'Shipping', value: 'Free over $45' },
{ label: 'Total', value: '$59.00', emphasis: true },
],
cta = { label: 'Finish checkout', href: '#' },
hold = 'Cart held until Thursday.',
reasons = {
eyebrow: 'If you were hesitating',
title: 'Three reasons to just do it',
items: [
'Free shipping over $45. You are already there.',
'Roasted the morning it ships, never before.',
'If you do not like it, we replace it. No form, no photo of the beans.',
],
},
signoff = 'Changed your mind about the grind? Reply and we will fix it before it ships.',
}: AbandonedCartEmailProps = {}) {
return (
<EmailLayout brand={brand} subject={subject} preview={preview}>
<Band padding="36px 40px 28px" align="center">
<Eyebrow>{eyebrow}</Eyebrow>
<Display>{headline}</Display>
<Prose margin="16px auto 0" maxWidth={400}>
{intro}
</Prose>
</Band>
<Band padding="0 40px 34px">
<LineItems items={items} leadingRule />
<Totals rows={totals} />
<Spacer height={22} />
<Centered>
<OutlineButton href={cta.href} align="center">
{cta.label}
</OutlineButton>
{hold ? <Note margin="10px 0 0">{hold}</Note> : null}
</Centered>
</Band>
<Band tone="dark">
<Centered>
<Eyebrow tone="dark">{reasons.eyebrow}</Eyebrow>
<SectionTitle tone="dark">{reasons.title}</SectionTitle>
</Centered>
<Spacer height={10} />
<NumberedList items={reasons.items} />
</Band>
<Band tone="paper" padding="24px 40px 28px">
<Centered>
<Prose size={14} margin="0 0 16px">
{signoff}
</Prose>
</Centered>
</Band>
</EmailLayout>
);
}
export default AbandonedCartEmail;
Related templates
More from 12 Ecommerce Email Templates.


