ui: Polish marketing website

This commit is contained in:
Dries Augustyns
2026-04-18 13:39:22 +02:00
parent 3bb3411994
commit c91d8c2e29
36 changed files with 5373 additions and 7508 deletions
+12 -17
View File
@@ -13,26 +13,21 @@ interface ComparisonTableProps {
rows: ComparisonRow[]; rows: ComparisonRow[];
} }
/**
* Reusable comparison table component for competitor pages
*/
export function ComparisonTable({competitorName, rows}: ComparisonTableProps) { export function ComparisonTable({competitorName, rows}: ComparisonTableProps) {
return ( return (
<div className={'overflow-hidden rounded-xl border border-neutral-200'}> <div className={'overflow-hidden rounded-[24px] border border-neutral-200'}>
{/* Header */}
<div className={'grid grid-cols-3 gap-px bg-neutral-200'}> <div className={'grid grid-cols-3 gap-px bg-neutral-200'}>
<div className={'bg-white p-6'}> <div className={'bg-neutral-50 p-6'}>
<span className={'text-sm font-semibold text-neutral-900'}>Feature</span> <span style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>Feature</span>
</div> </div>
<div className={'bg-white p-6 text-center'}> <div className={'bg-neutral-900 p-6 text-center'}>
<span className={'text-sm font-semibold text-neutral-900'}>Plunk</span> <span style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-white'}>Plunk</span>
</div> </div>
<div className={'bg-white p-6 text-center'}> <div className={'bg-neutral-50 p-6 text-center'}>
<span className={'text-sm font-semibold text-neutral-900'}>{competitorName}</span> <span style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>{competitorName}</span>
</div> </div>
</div> </div>
{/* Rows */}
<div className={'grid gap-px bg-neutral-200'}> <div className={'grid gap-px bg-neutral-200'}>
{rows.map((row, index) => ( {rows.map((row, index) => (
<motion.div <motion.div
@@ -40,7 +35,7 @@ export function ComparisonTable({competitorName, rows}: ComparisonTableProps) {
initial={{opacity: 0, y: 10}} initial={{opacity: 0, y: 10}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.05, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.4, delay: index * 0.04, ease: [0.22, 1, 0.36, 1]}}
className={'grid grid-cols-3 gap-px bg-neutral-200'} className={'grid grid-cols-3 gap-px bg-neutral-200'}
> >
<div className={'bg-white p-6'}> <div className={'bg-white p-6'}>
@@ -52,10 +47,10 @@ export function ComparisonTable({competitorName, rows}: ComparisonTableProps) {
row.plunk ? ( row.plunk ? (
<Check className="h-5 w-5 text-neutral-900" strokeWidth={2} /> <Check className="h-5 w-5 text-neutral-900" strokeWidth={2} />
) : ( ) : (
<X className="h-5 w-5 text-neutral-400" strokeWidth={2} /> <X className="h-5 w-5 text-neutral-300" strokeWidth={2} />
) )
) : ( ) : (
<span className={'text-sm text-neutral-900'}>{row.plunk}</span> <span className={'text-sm font-medium text-neutral-900'}>{row.plunk}</span>
)} )}
</div> </div>
</div> </div>
@@ -65,10 +60,10 @@ export function ComparisonTable({competitorName, rows}: ComparisonTableProps) {
row.competitor ? ( row.competitor ? (
<Check className="h-5 w-5 text-neutral-900" strokeWidth={2} /> <Check className="h-5 w-5 text-neutral-900" strokeWidth={2} />
) : ( ) : (
<X className="h-5 w-5 text-neutral-400" strokeWidth={2} /> <X className="h-5 w-5 text-neutral-300" strokeWidth={2} />
) )
) : ( ) : (
<span className={'text-sm text-neutral-900'}>{row.competitor}</span> <span className={'text-sm text-neutral-600'}>{row.competitor}</span>
)} )}
</div> </div>
</div> </div>
+20 -13
View File
@@ -12,9 +12,6 @@ interface FAQSectionProps {
schemaId?: string; schemaId?: string;
} }
/**
* Reusable FAQ section component with structured data support
*/
export function FAQSection({faqs, schemaId = 'faq-schema'}: FAQSectionProps) { export function FAQSection({faqs, schemaId = 'faq-schema'}: FAQSectionProps) {
return ( return (
<> <>
@@ -37,34 +34,44 @@ export function FAQSection({faqs, schemaId = 'faq-schema'}: FAQSectionProps) {
}} }}
/> />
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl'} className={'mb-16'}
>
<h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
> >
<h2 className={'mb-16 text-center text-5xl font-bold tracking-tight text-neutral-900'}>
Frequently asked questions Frequently asked questions
</h2> </h2>
</motion.div>
<div className={'space-y-8'}> <div className={'mx-auto max-w-3xl divide-y divide-neutral-200'}>
{faqs.map((faq, index) => ( {faqs.map((faq, index) => (
<motion.div <motion.div
key={index} key={index}
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: index * 0.06, ease: [0.22, 1, 0.36, 1]}}
className={'border-b border-neutral-200 pb-8 last:border-b-0'} className={'py-8'}
> >
<h3 className={'text-xl font-semibold text-neutral-900'}>{faq.question}</h3> <h3
<p className={'mt-4 leading-relaxed text-neutral-600'}>{faq.answer}</p> style={{fontFamily: 'var(--font-display)'}}
className={'text-lg font-bold tracking-[-0.02em] text-neutral-900'}
>
{faq.question}
</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>{faq.answer}</p>
</motion.div> </motion.div>
))} ))}
</div> </div>
</motion.div> </div>
</section> </section>
</> </>
); );
@@ -10,7 +10,7 @@ export default function Footer() {
return ( return (
<> <>
<footer className={'border-t border-neutral-200 bg-white'}> <footer className={'border-t border-neutral-200 bg-white'}>
<div className="mx-auto max-w-7xl px-8 py-20 xl:px-0"> <div className="mx-auto max-w-[88rem] px-6 py-20 sm:px-10">
<div className="grid gap-12 lg:grid-cols-12"> <div className="grid gap-12 lg:grid-cols-12">
{/* Logo and description */} {/* Logo and description */}
<div className="space-y-6 lg:col-span-3"> <div className="space-y-6 lg:col-span-3">
@@ -59,7 +59,7 @@ export default function Footer() {
{/* Links */} {/* Links */}
<div className="grid grid-cols-2 gap-8 lg:col-span-9 lg:grid-cols-5"> <div className="grid grid-cols-2 gap-8 lg:col-span-9 lg:grid-cols-5">
<div> <div>
<h3 className="text-sm font-semibold text-neutral-900">Product</h3> <h3 style={{fontFamily: 'var(--font-mono)'}} className="text-[11px] font-semibold uppercase tracking-[0.18em] text-neutral-500">Product</h3>
<ul role="list" className="mt-6 space-y-4"> <ul role="list" className="mt-6 space-y-4">
<li> <li>
<Link href={'/pricing'} className="text-sm text-neutral-600 transition hover:text-neutral-900"> <Link href={'/pricing'} className="text-sm text-neutral-600 transition hover:text-neutral-900">
@@ -90,7 +90,7 @@ export default function Footer() {
</div> </div>
<div> <div>
<h3 className="text-sm font-semibold text-neutral-900">Features</h3> <h3 style={{fontFamily: 'var(--font-mono)'}} className="text-[11px] font-semibold uppercase tracking-[0.18em] text-neutral-500">Features</h3>
<ul role="list" className="mt-6 space-y-4"> <ul role="list" className="mt-6 space-y-4">
<li> <li>
<Link href={'/features/email-editor'} className="text-sm text-neutral-600 transition hover:text-neutral-900"> <Link href={'/features/email-editor'} className="text-sm text-neutral-600 transition hover:text-neutral-900">
@@ -121,7 +121,7 @@ export default function Footer() {
</div> </div>
<div> <div>
<h3 className="text-sm font-semibold text-neutral-900">Compare</h3> <h3 style={{fontFamily: 'var(--font-mono)'}} className="text-[11px] font-semibold uppercase tracking-[0.18em] text-neutral-500">Compare</h3>
<ul role="list" className="mt-6 space-y-4"> <ul role="list" className="mt-6 space-y-4">
<li> <li>
<Link href={'/vs'} className="text-sm text-neutral-600 transition hover:text-neutral-900"> <Link href={'/vs'} className="text-sm text-neutral-600 transition hover:text-neutral-900">
@@ -162,7 +162,7 @@ export default function Footer() {
</div> </div>
<div> <div>
<h3 className="text-sm font-semibold text-neutral-900">Community</h3> <h3 style={{fontFamily: 'var(--font-mono)'}} className="text-[11px] font-semibold uppercase tracking-[0.18em] text-neutral-500">Community</h3>
<ul role="list" className="mt-6 space-y-4"> <ul role="list" className="mt-6 space-y-4">
<li> <li>
<Link href={'/discord'} className="text-sm text-neutral-600 transition hover:text-neutral-900"> <Link href={'/discord'} className="text-sm text-neutral-600 transition hover:text-neutral-900">
@@ -181,7 +181,7 @@ export default function Footer() {
</li> </li>
</ul> </ul>
<h3 className="mt-8 text-sm font-semibold text-neutral-900">Legal</h3> <h3 style={{fontFamily: 'var(--font-mono)'}} className="mt-8 text-[11px] font-semibold uppercase tracking-[0.18em] text-neutral-500">Legal</h3>
<ul role="list" className="mt-6 space-y-4"> <ul role="list" className="mt-6 space-y-4">
<li> <li>
<Link href={'/privacy'} className="text-sm text-neutral-600 transition hover:text-neutral-900"> <Link href={'/privacy'} className="text-sm text-neutral-600 transition hover:text-neutral-900">
@@ -202,7 +202,7 @@ export default function Footer() {
</div> </div>
<div> <div>
<h3 className="text-sm font-semibold text-neutral-900">Guides</h3> <h3 style={{fontFamily: 'var(--font-mono)'}} className="text-[11px] font-semibold uppercase tracking-[0.18em] text-neutral-500">Guides</h3>
<ul role="list" className="mt-6 space-y-4"> <ul role="list" className="mt-6 space-y-4">
<li> <li>
<Link href={'/guides/email-deliverability'} className="text-sm text-neutral-600 transition hover:text-neutral-900"> <Link href={'/guides/email-deliverability'} className="text-sm text-neutral-600 transition hover:text-neutral-900">
@@ -47,8 +47,8 @@ export default function Navbar() {
const [featuresOpen, setFeaturesOpen] = useState(false); const [featuresOpen, setFeaturesOpen] = useState(false);
return ( return (
<header className={'sticky top-0 z-40 w-full border-b border-neutral-100 bg-white/95 backdrop-blur-sm'}> <header className={'sticky top-0 z-40 w-full border-b border-neutral-200 bg-white/95 backdrop-blur-sm'}>
<div className={'relative mx-auto max-w-7xl px-8 xl:px-0'}> <div className={'relative mx-auto max-w-[88rem] px-6 sm:px-10'}>
<div className={'py-5'}> <div className={'py-5'}>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-12"> <div className="flex items-center gap-12">
@@ -83,14 +83,14 @@ export default function Navbar() {
onMouseEnter={() => setFeaturesOpen(true)} onMouseEnter={() => setFeaturesOpen(true)}
onMouseLeave={() => setFeaturesOpen(false)} onMouseLeave={() => setFeaturesOpen(false)}
className={ className={
'absolute left-0 top-full z-50 mt-2 w-80 rounded-lg border border-neutral-200 bg-white p-2 shadow-lg' 'absolute left-0 top-full z-50 mt-2 w-80 rounded-[16px] border border-neutral-200 bg-white p-2 shadow-lg'
} }
> >
{featuresMenu.map(feature => ( {featuresMenu.map(feature => (
<Link <Link
key={feature.href} key={feature.href}
href={feature.href} href={feature.href}
className={'flex items-start gap-3 rounded-lg p-3 transition hover:bg-neutral-50'} className={'flex items-start gap-3 rounded-[10px] p-3 transition hover:bg-neutral-50'}
> >
<div <div
className={ className={
@@ -166,7 +166,7 @@ export default function Navbar() {
whileTap={{scale: 0.98}} whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={
'rounded-lg bg-neutral-900 px-6 py-2.5 text-sm font-semibold text-white shadow-sm transition hover:bg-neutral-800' 'rounded-full bg-neutral-900 px-6 py-2.5 text-sm font-semibold text-white transition hover:bg-neutral-800'
} }
> >
Get started Get started
@@ -226,7 +226,7 @@ export default function Navbar() {
className="space-y-1 p-4" className="space-y-1 p-4"
> >
<div className="mb-2"> <div className="mb-2">
<div className="px-4 py-2 text-xs font-semibold uppercase tracking-wider text-neutral-500"> <div style={{fontFamily: 'var(--font-mono)'}} className="px-4 py-2 text-[11px] font-semibold uppercase tracking-[0.18em] text-neutral-500">
Features Features
</div> </div>
{featuresMenu.map(feature => ( {featuresMenu.map(feature => (
@@ -293,7 +293,7 @@ export default function Navbar() {
</a> </a>
<a <a
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className="mt-2 block rounded-lg bg-neutral-900 px-4 py-3 text-center text-sm font-semibold text-white transition hover:bg-neutral-800" className="mt-2 block rounded-full bg-neutral-900 px-4 py-3 text-center text-sm font-semibold text-white transition hover:bg-neutral-800"
> >
Get started Get started
</a> </a>
@@ -0,0 +1,48 @@
import {motion} from 'framer-motion';
import React from 'react';
export function SectionHeader({
number,
label,
title,
titleAccent,
subtitle,
}: {
number: string;
label: string;
title: string;
titleAccent?: string;
subtitle?: string;
}) {
return (
<motion.div
initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true, margin: '-10%'}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'grid gap-8 lg:grid-cols-12 lg:gap-16'}
>
<div
style={{fontFamily: 'var(--font-mono)'}}
className={
'flex items-center gap-4 border-t border-neutral-900 pt-4 text-[11px] uppercase tracking-[0.2em] text-neutral-700 lg:col-span-3 lg:self-start'
}
>
<span className={'font-medium text-neutral-900'}>§ {number}</span>
<span className={'text-neutral-500'}>{label}</span>
</div>
<div className={'lg:col-span-9'}>
<h2
style={{fontFamily: 'var(--font-display)'}}
className={
'text-[clamp(2.25rem,5.5vw,4.5rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'
}
>
{title}
{titleAccent && <> {titleAccent}</>}
</h2>
{subtitle && <p className={'mt-6 max-w-2xl text-lg leading-relaxed text-neutral-600'}>{subtitle}</p>}
</div>
</motion.div>
);
}
@@ -114,7 +114,7 @@ export function GuideLayout({
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-4 sm:px-8 w-full overflow-x-hidden'}> <main className={'mx-auto max-w-[88rem] px-4 sm:px-8 w-full overflow-x-hidden'}>
<div className={'flex flex-col lg:flex-row gap-8 lg:gap-12 py-8 sm:py-16 w-full'}> <div className={'flex flex-col lg:flex-row gap-8 lg:gap-12 py-8 sm:py-16 w-full'}>
{/* Main Content */} {/* Main Content */}
<article className={'flex-1 max-w-full lg:max-w-4xl w-full'}> <article className={'flex-1 max-w-full lg:max-w-4xl w-full'}>
+1
View File
@@ -3,3 +3,4 @@ export * from './Footer';
export * from './ComparisonTable'; export * from './ComparisonTable';
export * from './FAQSection'; export * from './FAQSection';
export * from './CodeBlock'; export * from './CodeBlock';
export * from './SectionHeader';
+24 -2
View File
@@ -7,6 +7,28 @@ import {SWRConfig} from 'swr';
import {network} from '../lib/network'; import {network} from '../lib/network';
import {DefaultSeo} from 'next-seo'; import {DefaultSeo} from 'next-seo';
import Script from 'next/script'; import Script from 'next/script';
import {Bricolage_Grotesque, Hanken_Grotesk, JetBrains_Mono} from 'next/font/google';
const display = Bricolage_Grotesque({
subsets: ['latin'],
variable: '--font-display',
display: 'swap',
weight: ['400', '500', '600', '700', '800'],
});
const body = Hanken_Grotesk({
subsets: ['latin'],
variable: '--font-body',
display: 'swap',
weight: ['400', '500', '600', '700'],
});
const mono = JetBrains_Mono({
subsets: ['latin'],
variable: '--font-mono',
display: 'swap',
weight: ['400', '500'],
});
/** /**
* Main app component * Main app component
@@ -25,7 +47,7 @@ function App({Component, pageProps}: AppProps) {
}, []); }, []);
return ( return (
<> <div className={`${display.variable} ${body.variable} ${mono.variable}`}>
<Head> <Head>
<title>Plunk | The Open-Source Email Platform</title> <title>Plunk | The Open-Source Email Platform</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" key={'viewport'} /> <meta name="viewport" content="width=device-width, initial-scale=1.0" key={'viewport'} />
@@ -33,7 +55,7 @@ function App({Component, pageProps}: AppProps) {
<Toaster position={'top-right'} /> <Toaster position={'top-right'} />
<Component {...pageProps} /> <Component {...pageProps} />
</> </div>
); );
} }
-8
View File
@@ -6,14 +6,6 @@ export default class MyDocument extends Document {
return ( return (
<Html lang="en"> <Html lang="en">
<Head> <Head>
{/* Start fonts */}
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@500&display=swap"
rel="stylesheet"
/>
{/* End fonts */}
{/* Start favicon */} {/* Start favicon */}
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png" /> <link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png" /> <link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png" />
+193 -174
View File
@@ -8,36 +8,34 @@ import Head from 'next/head';
const features = [ const features = [
{ {
icon: <Type className="h-5 w-5" />, icon: <Type className="h-6 w-6" strokeWidth={1.5} />,
title: 'Visual WYSIWYG Editor', title: 'Visual WYSIWYG Editor',
description: description:
'Rich text editing with formatting toolbar. Bold, italic, headings, lists, links, images, and tables. No code required.', 'Rich text editing with formatting toolbar. Bold, italic, headings, lists, links, images, and tables. No code required.',
featured: true,
}, },
{ {
icon: <Code2 className="h-5 w-5" />, icon: <Code2 className="h-6 w-6" strokeWidth={1.5} />,
title: 'Full HTML Editor', title: 'Full HTML Editor',
description: description: 'Syntax highlighting, auto-completion, and bracket matching. Write custom HTML when you need complete control.',
'Syntax highlighting, auto-completion, and bracket matching. Write custom HTML when you need complete control.',
}, },
{ {
icon: <Zap className="h-5 w-5" />, icon: <Zap className="h-6 w-6" strokeWidth={1.5} />,
title: 'Smart Mode Switching', title: 'Smart Mode Switching',
description: description: 'Automatically detects complex HTML and switches to code mode. Warns you before changes that would lose custom formatting.',
'Automatically detects complex HTML and switches to code mode. Warns you before changes that would lose custom formatting.',
}, },
{ {
icon: <Sparkles className="h-5 w-5" />, icon: <Sparkles className="h-6 w-6" strokeWidth={1.5} />,
title: 'Powerful Variables', title: 'Powerful Variables',
description: description: 'Autocomplete with {{variable}} syntax. Supports fallbacks, nested properties, and custom contact fields.',
'Autocomplete with {{variable}} syntax. Supports fallbacks, nested properties, and custom contact fields.',
}, },
{ {
icon: <Eye className="h-5 w-5" />, icon: <Eye className="h-6 w-6" strokeWidth={1.5} />,
title: 'Live Preview', title: 'Live Preview',
description: 'Preview with real contact data. Test on desktop, tablet, and mobile views before sending.', description: 'Preview with real contact data. Test on desktop, tablet, and mobile views before sending.',
}, },
{ {
icon: <Palette className="h-5 w-5" />, icon: <Palette className="h-6 w-6" strokeWidth={1.5} />,
title: 'Email-Safe HTML', title: 'Email-Safe HTML',
description: 'Automatic CSS inlining and email-client-friendly code generation. Yes, even in Outlook.', description: 'Automatic CSS inlining and email-client-friendly code generation. Yes, even in Outlook.',
}, },
@@ -45,21 +43,21 @@ const features = [
const useCases = [ const useCases = [
{ {
icon: <Code2 className="h-6 w-6" />, icon: <Code2 className="h-6 w-6" strokeWidth={1.5} />,
title: 'For Developers', title: 'For Developers',
description: description:
'Full HTML control when you need it. Powerful variable system with autocomplete and fallbacks. Use templates in API calls, workflows, and campaigns.', 'Full HTML control when you need it. Powerful variable system with autocomplete and fallbacks. Use templates in API calls, workflows, and campaigns.',
example: 'Password resets → API-triggered alerts → Webhook notifications → Those cat meme attachments', example: 'Password resets → API-triggered alerts → Webhook notifications',
}, },
{ {
icon: <Palette className="h-6 w-6" />, icon: <Palette className="h-6 w-6" strokeWidth={1.5} />,
title: 'For Marketers', title: 'For Marketers',
description: description:
'Visual editor for quick changes. Live preview with real customer data. Create professional emails without waiting for developers.', 'Visual editor for quick changes. Live preview with real customer data. Create professional emails without waiting for developers.',
example: 'Product announcements → Newsletter campaigns → Promotional emails → Customer onboarding', example: 'Product announcements → Newsletter campaigns → Promotional emails → Customer onboarding',
}, },
{ {
icon: <Zap className="h-6 w-6" />, icon: <Zap className="h-6 w-6" strokeWidth={1.5} />,
title: 'For Teams', title: 'For Teams',
description: description:
'One tool for everyone. Developers can code, marketers can design, everyone can preview. Reusable templates across campaigns and workflows.', 'One tool for everyone. Developers can code, marketers can design, everyone can preview. Reusable templates across campaigns and workflows.',
@@ -67,9 +65,6 @@ const useCases = [
}, },
]; ];
/**
*
*/
export default function EmailEditorFeature() { export default function EmailEditorFeature() {
return ( return (
<> <>
@@ -79,10 +74,7 @@ export default function EmailEditorFeature() {
name="description" name="description"
content="The email editor that speaks both languages. Switch seamlessly between visual and code editing, preview with real data, and create templates that work everywhere." content="The email editor that speaks both languages. Switch seamlessly between visual and code editing, preview with real data, and create templates that work everywhere."
/> />
<meta <meta property="og:title" content="Email Editor - Create Beautiful Emails Without Fighting Your Tools | Plunk" />
property="og:title"
content="Email Editor - Create Beautiful Emails Without Fighting Your Tools | Plunk"
/>
<meta <meta
property="og:description" property="og:description"
content="The email editor that speaks both languages. Switch seamlessly between visual and code editing, preview with real data, and create templates that work everywhere." content="The email editor that speaks both languages. Switch seamlessly between visual and code editing, preview with real data, and create templates that work everywhere."
@@ -91,178 +83,134 @@ export default function EmailEditorFeature() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-20 sm:py-32'}> {/* Hero */}
{/* Subtle background grid */} <section className={'relative overflow-hidden'}>
<div <div
aria-hidden
className={ className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]' 'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'
} }
/> />
<div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
animate={{opacity: 1, y: 0}} animate={{opacity: 1, y: 0}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl text-center'}
> >
<div className={'mb-6 inline-flex items-center gap-2 rounded-full bg-neutral-100 px-4 py-2 text-sm'}> <div
<Mail className="h-4 w-4 text-neutral-600" /> style={{fontFamily: 'var(--font-mono)'}}
<span className={'font-medium text-neutral-600'}>Email Editor & Templates</span> className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}
>
Email Editor & Templates
</div> </div>
<h1
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}> style={{fontFamily: 'var(--font-display)'}}
The Email Editor className={
'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'
}
>
The editor that
<br /> <br />
That Speaks Both Languages speaks both languages.
</h1> </h1>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>
Switch seamlessly between visual and code editing. Preview with real customer data. Create templates that Switch seamlessly between visual and code editing. Preview with real customer data. Create templates that
work everywhere. work everywhere.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> <div className={'mt-10 flex flex-wrap gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800' 'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'
} }
> >
<span className={'flex items-center gap-2'}>
Try the editor free Try the editor free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</span>
</motion.a> </motion.a>
<Link <Link
href={WIKI_URI} href={WIKI_URI}
target={'_blank'} target={'_blank'}
className={ className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400' 'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'
} }
> >
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Features Grid */} {/* Features grid */}
<section className={'py-20'}> <section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'} className={'mb-16'}
>
<h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}>
Two editors, one experience Two editors, one experience
</h2> </h2>
<p className={'mt-4 text-lg text-neutral-600'}>Visual editing for speed, code editing for control</p> <p className={'mt-4 text-lg text-neutral-600'}>Visual editing for speed, code editing for control</p>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-4 sm:grid-cols-2 lg:grid-cols-3'}>
{features.map((feature, index) => ( {features.map((feature, index) => {
const highlighted = feature.featured;
return (
<motion.div <motion.div
key={feature.title} key={feature.title}
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: index * 0.06, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-10 transition hover:bg-neutral-50'}
>
<div
className={ className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110' highlighted
? 'flex min-h-[16rem] flex-col justify-between rounded-[28px] border border-neutral-900 bg-neutral-900 p-8 text-white'
: 'flex min-h-[16rem] flex-col justify-between rounded-[28px] border border-neutral-200 bg-white p-8 transition hover:border-neutral-900'
} }
> >
{feature.icon} <div className={'flex items-start justify-between'}>
</div> <div className={highlighted ? 'text-white' : 'text-neutral-900'}>{feature.icon}</div>
<h3 className={'mt-6 text-lg font-semibold text-neutral-900'}>{feature.title}</h3> <span
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>{feature.description}</p> style={{fontFamily: 'var(--font-mono)'}}
</motion.div> className={`text-[11px] uppercase tracking-[0.18em] ${highlighted ? 'text-neutral-500' : 'text-neutral-400'}`}
))}
</div>
</section>
{/* How It Works */}
<section className={'py-20'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl text-center'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}> {String(index + 1).padStart(2, '0')}
From first draft to send </span>
</h2> </div>
<p className={'mt-6 text-lg text-neutral-600'}>Create, preview, and deploy templates in minutes</p> <div>
</motion.div> <h3
style={{fontFamily: 'var(--font-display)'}}
<div className={'mx-auto mt-16 max-w-5xl'}> className={`mt-8 text-xl font-bold tracking-[-0.02em] ${highlighted ? 'text-white' : 'text-neutral-900'}`}
<div className={'grid gap-12 lg:grid-cols-3'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}}
> >
<div className={'mb-5 flex items-center gap-4'}> {feature.title}
<div className={'flex h-14 w-14 items-center justify-center rounded-full border-2 border-neutral-200 bg-white text-xl font-bold text-neutral-900'}> </h3>
1 <p className={`mt-2 text-sm leading-relaxed ${highlighted ? 'text-neutral-300' : 'text-neutral-600'}`}>
</div> {feature.description}
</div>
<h3 className={'text-lg font-semibold text-neutral-900'}>Create your template</h3>
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>
Use the visual editor for quick formatting or write custom HTML. Add variables with autocomplete.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
>
<div className={'mb-5 flex items-center gap-4'}>
<div className={'flex h-14 w-14 items-center justify-center rounded-full border-2 border-neutral-200 bg-white text-xl font-bold text-neutral-900'}>
2
</div>
</div>
<h3 className={'text-lg font-semibold text-neutral-900'}>Preview with real data</h3>
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>
Select any contact and see exactly what they'll receive. Test on desktop, tablet, and mobile. No
surprises.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
>
<div className={'mb-5 flex items-center gap-4'}>
<div className={'flex h-14 w-14 items-center justify-center rounded-full border-2 border-neutral-200 bg-white text-xl font-bold text-neutral-900'}>
3
</div>
</div>
<h3 className={'text-lg font-semibold text-neutral-900'}>Use everywhere</h3>
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>
Use your template in campaigns, workflows, and API calls. One template, unlimited uses.
</p> </p>
</div>
</motion.div> </motion.div>
);
})}
</div> </div>
</div> </div>
</section> </section>
{/* Use Cases */} {/* How it works */}
<section className={'py-20'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
@@ -270,11 +218,77 @@ export default function EmailEditorFeature() {
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'} className={'mb-16 text-center'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}>Built for every team</h2> <h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
>
From first draft to send
</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Create, preview, and deploy templates in minutes</p>
</motion.div>
<div className={'mx-auto max-w-4xl'}>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-3'}>
{[
{
step: '01',
title: 'Create your template',
body: 'Use the visual editor for quick formatting or write custom HTML. Add variables with autocomplete.',
},
{
step: '02',
title: 'Preview with real data',
body: 'Select any contact and see exactly what they\'ll receive. Test on desktop, tablet, and mobile.',
},
{
step: '03',
title: 'Use everywhere',
body: 'Use your template in campaigns, workflows, and API calls. One template, unlimited uses.',
},
].map((item, i) => (
<motion.div
key={item.step}
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: i * 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'bg-white p-10'}
>
<div
style={{fontFamily: 'var(--font-mono)'}}
className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-400'}
>
Step {item.step}
</div>
<h3 className={'text-lg font-semibold text-neutral-900'}>{item.title}</h3>
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>{item.body}</p>
</motion.div>
))}
</div>
</div>
</div>
</section>
{/* Use cases */}
<section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16'}
>
<h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
>
Built for every team
</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Whether you're a developer, marketer, or founder</p> <p className={'mt-4 text-lg text-neutral-600'}>Whether you're a developer, marketer, or founder</p>
</motion.div> </motion.div>
<div className={'mx-auto max-w-5xl space-y-8'}> <div className={'space-y-4'}>
{useCases.map((useCase, index) => ( {useCases.map((useCase, index) => (
<motion.div <motion.div
key={useCase.title} key={useCase.title}
@@ -282,74 +296,79 @@ export default function EmailEditorFeature() {
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'rounded-xl border border-neutral-200 bg-white p-8'} className={'rounded-[24px] border border-neutral-200 bg-white p-8'}
> >
<div className={'flex items-start gap-6'}> <div className={'flex items-start gap-6'}>
<div <div className={'flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-full border border-neutral-200 text-neutral-900'}>
className={
'flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-xl bg-neutral-900 text-white'
}
>
{useCase.icon} {useCase.icon}
</div> </div>
<div className={'flex-1'}> <div className={'flex-1'}>
<h3 className={'text-xl font-semibold text-neutral-900'}>{useCase.title}</h3> <h3
style={{fontFamily: 'var(--font-display)'}}
className={'text-xl font-bold tracking-[-0.02em] text-neutral-900'}
>
{useCase.title}
</h3>
<p className={'mt-2 text-neutral-600'}>{useCase.description}</p> <p className={'mt-2 text-neutral-600'}>{useCase.description}</p>
<div className={'mt-4 rounded-lg bg-neutral-50 p-4'}> <div className={'mt-4 rounded-xl border border-neutral-100 bg-neutral-50 p-4'}>
<p className={'text-sm text-neutral-700'}>{useCase.example}</p> <p style={{fontFamily: 'var(--font-mono)'}} className={'text-sm text-neutral-600'}>
{useCase.example}
</p>
</div> </div>
</div> </div>
</div> </div>
</motion.div> </motion.div>
))} ))}
</div> </div>
</div>
</section> </section>
{/* CTA Section */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-20'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2
} initial={{opacity: 0, y: 16}}
/>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-3xl text-center'} style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}> Build your first template today.
Build your first template today </motion.h2>
</h2> <motion.div
<p className={'mt-6 text-lg text-neutral-600'}> initial={{opacity: 0, y: 16}}
1,000 emails free every month. Then $0.001 per email. No contact limits, no credit card required. whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}}
className={'flex max-w-md flex-col gap-6'}
>
<p className={'text-base text-neutral-300 sm:text-lg'}>
Free plan available. $0.001 per email on paid. No credit card required.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> <div className={'flex flex-wrap gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
> >
<span className={'flex items-center gap-2'}>
Get started for free Get started for free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className="h-4 w-4" />
</span>
</motion.a> </motion.a>
<Link <Link
href={'/pricing'} href={'/pricing'}
className={ className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
> >
View pricing View pricing
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main> </main>
<Footer /> <Footer />
+205 -259
View File
@@ -8,33 +8,33 @@ import Head from 'next/head';
const features = [ const features = [
{ {
icon: <Database className="h-5 w-5" />, icon: <Database className="h-6 w-6" strokeWidth={1.5} />,
title: 'Automatic Contact Capture', title: 'Automatic Contact Capture',
description: 'Every sender is automatically added to your contact database with no manual data entry required.', description: 'Every sender is automatically added to your contact database with no manual data entry required.',
featured: true,
}, },
{ {
icon: <Zap className="h-5 w-5" />, icon: <Zap className="h-6 w-6" strokeWidth={1.5} />,
title: 'Workflow Automation', title: 'Workflow Automation',
description: 'Trigger automated workflows when emails are received to create sophisticated two-way communication.', description: 'Trigger automated workflows when emails are received to create sophisticated two-way communication.',
}, },
{ {
icon: <Shield className="h-5 w-5" />, icon: <Shield className="h-6 w-6" strokeWidth={1.5} />,
title: 'Built-in Security', title: 'Built-in Security',
description: description: 'Spam, virus, SPF, DKIM, and DMARC filtering keeps your inbox clean. The spam stays out, the good stuff gets in.',
'Spam, virus, SPF, DKIM, and DMARC filtering keeps your inbox clean. The spam stays out, the good stuff gets in.',
}, },
{ {
icon: <Bell className="h-5 w-5" />, icon: <Bell className="h-6 w-6" strokeWidth={1.5} />,
title: 'Webhook Notifications', title: 'Webhook Notifications',
description: 'Get instant notifications with rich metadata whenever an email arrives at your domain.', description: 'Get instant notifications with rich metadata whenever an email arrives at your domain.',
}, },
{ {
icon: <Mail className="h-5 w-5" />, icon: <Mail className="h-6 w-6" strokeWidth={1.5} />,
title: 'Simple DNS Setup', title: 'Simple DNS Setup',
description: 'Add one MX record to your domain and start receiving emails immediately. No PhD required.', description: 'Add one MX record to your domain and start receiving emails immediately. No PhD required.',
}, },
{ {
icon: <Inbox className="h-5 w-5" />, icon: <Inbox className="h-6 w-6" strokeWidth={1.5} />,
title: 'Real-Time Processing', title: 'Real-Time Processing',
description: 'Emails are processed instantly and can trigger workflows or webhooks in real-time.', description: 'Emails are processed instantly and can trigger workflows or webhooks in real-time.',
}, },
@@ -42,21 +42,21 @@ const features = [
const useCases = [ const useCases = [
{ {
icon: <Mail className="h-6 w-6" />, icon: <Mail className="h-6 w-6" strokeWidth={1.5} />,
title: 'Support Ticket Creation', title: 'Support Ticket Creation',
description: description:
'Automatically create support tickets when customers email [email protected]. Send auto-replies and route to your help desk system via webhooks. Your support team will thank you.', 'Automatically create support tickets when customers email [email protected]. Send auto-replies and route to your help desk system via webhooks. Your support team will thank you.',
benefits: ['Instant acknowledgment', 'Automatic ticket creation', 'No emails missed'], benefits: ['Instant acknowledgment', 'Automatic ticket creation', 'No emails missed'],
}, },
{ {
icon: <Database className="h-6 w-6" />, icon: <Database className="h-6 w-6" strokeWidth={1.5} />,
title: 'Lead Capture from Email', title: 'Lead Capture from Email',
description: description:
'Receive emails at [email protected] and automatically add senders to your CRM. Trigger nurture workflows based on when they reached out.', 'Receive emails at [email protected] and automatically add senders to your CRM. Trigger nurture workflows based on when they reached out.',
benefits: ['Zero-friction lead capture', 'Auto-segmentation', 'Instant follow-up'], benefits: ['Zero-friction lead capture', 'Auto-segmentation', 'Instant follow-up'],
}, },
{ {
icon: <Zap className="h-6 w-6" />, icon: <Zap className="h-6 w-6" strokeWidth={1.5} />,
title: 'Two-Way Conversations', title: 'Two-Way Conversations',
description: description:
'Let customers reply to your campaign emails and automatically trigger engagement workflows. Tag contacts as "engaged" when they respond.', 'Let customers reply to your campaign emails and automatically trigger engagement workflows. Tag contacts as "engaged" when they respond.',
@@ -64,9 +64,6 @@ const useCases = [
}, },
]; ];
/**
*
*/
export default function InboundEmailFeature() { export default function InboundEmailFeature() {
return ( return (
<> <>
@@ -85,66 +82,134 @@ export default function InboundEmailFeature() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-20 sm:py-32'}> {/* Hero */}
{/* Subtle background grid */} <section className={'relative overflow-hidden'}>
<div <div
aria-hidden
className={ className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]' 'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'
} }
/> />
<div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
animate={{opacity: 1, y: 0}} animate={{opacity: 1, y: 0}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl text-center'}
> >
<div className={'mb-6 inline-flex items-center gap-2 rounded-full bg-neutral-100 px-4 py-2 text-sm'}> <div
<Inbox className="h-4 w-4 text-neutral-600" /> style={{fontFamily: 'var(--font-mono)'}}
<span className={'font-medium text-neutral-600'}>Inbound Email</span> className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}
>
Inbound Email
</div> </div>
<h1
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}> style={{fontFamily: 'var(--font-display)'}}
Turn Incoming Emails className={
'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'
}
>
Emails in,
<br /> <br />
into Actions actions out.
</h1> </h1>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>
Receive emails at your custom domain and automatically trigger workflows, capture leads, or create support Receive emails at your custom domain and automatically trigger workflows, capture leads, or create support
tickets. Two-way email communication made simple. tickets. Two-way email communication made simple.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> <div className={'mt-10 flex flex-wrap gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800' 'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'
} }
> >
<span className={'flex items-center gap-2'}>
Start receiving emails Start receiving emails
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</span>
</motion.a> </motion.a>
<Link <Link
href={WIKI_URI} href={WIKI_URI}
target={'_blank'} target={'_blank'}
className={ className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400' 'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'
} }
> >
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Features Grid */} {/* Features grid */}
<section className={'py-20'}> <section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16'}
>
<h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
>
Complete inbound email solution
</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Everything you need to receive and process incoming emails</p>
</motion.div>
<div className={'grid gap-4 sm:grid-cols-2 lg:grid-cols-3'}>
{features.map((feature, index) => {
const highlighted = feature.featured;
return (
<motion.div
key={feature.title}
initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.06, ease: [0.22, 1, 0.36, 1]}}
className={
highlighted
? 'flex min-h-[16rem] flex-col justify-between rounded-[28px] border border-neutral-900 bg-neutral-900 p-8 text-white'
: 'flex min-h-[16rem] flex-col justify-between rounded-[28px] border border-neutral-200 bg-white p-8 transition hover:border-neutral-900'
}
>
<div className={'flex items-start justify-between'}>
<div className={highlighted ? 'text-white' : 'text-neutral-900'}>{feature.icon}</div>
<span
style={{fontFamily: 'var(--font-mono)'}}
className={`text-[11px] uppercase tracking-[0.18em] ${highlighted ? 'text-neutral-500' : 'text-neutral-400'}`}
>
{String(index + 1).padStart(2, '0')}
</span>
</div>
<div>
<h3
style={{fontFamily: 'var(--font-display)'}}
className={`mt-8 text-xl font-bold tracking-[-0.02em] ${highlighted ? 'text-white' : 'text-neutral-900'}`}
>
{feature.title}
</h3>
<p className={`mt-2 text-sm leading-relaxed ${highlighted ? 'text-neutral-300' : 'text-neutral-600'}`}>
{feature.description}
</p>
</div>
</motion.div>
);
})}
</div>
</div>
</section>
{/* How it works */}
<section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
@@ -152,136 +217,77 @@ export default function InboundEmailFeature() {
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'} className={'mb-16 text-center'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}> <h2
Complete inbound email solution style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
>
Set up in minutes
</h2> </h2>
<p className={'mt-4 text-lg text-neutral-600'}> <p className={'mt-4 text-lg text-neutral-600'}>One MX record is all it takes</p>
Everything you need to receive and process incoming emails
</p>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'mx-auto max-w-4xl'}>
{features.map((feature, index) => ( <div className={'grid gap-px bg-neutral-200 sm:grid-cols-3'}>
{[
{
step: '01',
title: 'Verify your domain',
body: 'Add and verify your custom domain in Plunk by configuring DKIM and SPF records in your DNS settings.',
},
{
step: '02',
title: 'Add MX record',
body: 'Add one MX record to your DNS to route incoming emails to Plunk. Copy the record directly from your dashboard.',
},
{
step: '03',
title: 'Start receiving',
body: 'Emails sent to any address at your domain are automatically received and can trigger workflows or webhooks.',
},
].map((item, i) => (
<motion.div <motion.div
key={feature.title} key={item.step}
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: i * 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-10 transition hover:bg-neutral-50'} className={'bg-white p-10'}
> >
<div <div
className={ style={{fontFamily: 'var(--font-mono)'}}
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110' className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-400'}
}
> >
{feature.icon} Step {item.step}
</div> </div>
<h3 className={'mt-6 text-lg font-semibold text-neutral-900'}>{feature.title}</h3> <h3 className={'text-lg font-semibold text-neutral-900'}>{item.title}</h3>
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>{feature.description}</p> <p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>{item.body}</p>
</motion.div> </motion.div>
))} ))}
</div> </div>
</div>
</div>
</section> </section>
{/* How It Works */} {/* Use cases */}
<section className={'py-20'}> <section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl text-center'} className={'mb-16'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}>Set up in minutes</h2> <h2
<p className={'mt-6 text-lg text-neutral-600'}>Get started with inbound email in three simple steps</p> style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
>
Powerful use cases
</h2>
<p className={'mt-4 text-lg text-neutral-600'}>From support to sales, inbound email unlocks new automation possibilities</p>
</motion.div> </motion.div>
<div className={'mx-auto mt-16 max-w-5xl'}> <div className={'space-y-4'}>
<div className={'grid gap-12 lg:grid-cols-3'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}}
>
<div className={'mb-5 flex items-center gap-4'}>
<div
className={
'flex h-14 w-14 items-center justify-center rounded-full border-2 border-neutral-200 bg-white text-xl font-bold text-neutral-900'
}
>
1
</div>
</div>
<h3 className={'text-lg font-semibold text-neutral-900'}>Verify your domain</h3>
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>
Add and verify your custom domain in Plunk by configuring DKIM and SPF records in your DNS settings.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
>
<div className={'mb-5 flex items-center gap-4'}>
<div
className={
'flex h-14 w-14 items-center justify-center rounded-full border-2 border-neutral-200 bg-white text-xl font-bold text-neutral-900'
}
>
2
</div>
</div>
<h3 className={'text-lg font-semibold text-neutral-900'}>Add MX record</h3>
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>
Add one MX record to your DNS to route incoming emails to Plunk. Copy the record from your dashboard.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
>
<div className={'mb-5 flex items-center gap-4'}>
<div
className={
'flex h-14 w-14 items-center justify-center rounded-full border-2 border-neutral-200 bg-white text-xl font-bold text-neutral-900'
}
>
3
</div>
</div>
<h3 className={'text-lg font-semibold text-neutral-900'}>Start receiving</h3>
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>
Emails sent to any address at your domain are automatically received and can trigger workflows or
webhooks.
</p>
</motion.div>
</div>
</div>
</section>
{/* Use Cases */}
<section className={'py-20'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}>Powerful use cases</h2>
<p className={'mt-4 text-lg text-neutral-600'}>
From support to sales, inbound email unlocks new automation possibilities
</p>
</motion.div>
<div className={'mx-auto max-w-5xl space-y-8'}>
{useCases.map((useCase, index) => ( {useCases.map((useCase, index) => (
<motion.div <motion.div
key={useCase.title} key={useCase.title}
@@ -289,139 +295,79 @@ export default function InboundEmailFeature() {
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'rounded-xl border border-neutral-200 bg-white p-8'} className={'rounded-[24px] border border-neutral-200 bg-white p-8'}
> >
<div className={'flex items-start gap-6'}> <div className={'flex items-start gap-6'}>
<div <div className={'flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-full border border-neutral-200 text-neutral-900'}>
className={
'flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-xl bg-neutral-900 text-white'
}
>
{useCase.icon} {useCase.icon}
</div> </div>
<div className={'flex-1'}> <div className={'flex-1'}>
<h3 className={'text-xl font-semibold text-neutral-900'}>{useCase.title}</h3> <h3
style={{fontFamily: 'var(--font-display)'}}
className={'text-xl font-bold tracking-[-0.02em] text-neutral-900'}
>
{useCase.title}
</h3>
<p className={'mt-2 text-neutral-600'}>{useCase.description}</p> <p className={'mt-2 text-neutral-600'}>{useCase.description}</p>
<div className={'mt-4 flex flex-wrap gap-2'}> <div className={'mt-4 rounded-xl border border-neutral-100 bg-neutral-50 p-4'}>
{useCase.benefits.map(benefit => ( <p style={{fontFamily: 'var(--font-mono)'}} className={'text-sm text-neutral-600'}>
<span {useCase.benefits.join(' → ')}
key={benefit}
className={'rounded-full bg-neutral-100 px-3 py-1 text-sm text-neutral-700'}
>
{benefit}
</span>
))}
</div>
</div>
</div>
</motion.div>
))}
</div>
</section>
{/* Technical Details */}
<section className={'py-20'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl'}
>
<div className={'rounded-2xl border border-neutral-200 bg-white p-8 sm:p-12'}>
<h2 className={'text-3xl font-bold tracking-tight text-neutral-900 text-balance'}>
What happens when an email arrives?
</h2>
<div className={'mt-10'}>
{[
{
title: 'Email arrives at your domain',
description: 'Your MX record routes the email to Plunk for processing',
},
{
title: 'Security checks pass',
description: 'Automatic validation of spam, virus, SPF, DKIM, and DMARC',
},
{
title: 'Contact is created or updated',
description: 'The sender is automatically added to your contact database',
},
{
title: 'Workflows trigger automatically',
description: 'Configured workflows start running based on the incoming email',
},
].map((step, i, arr) => (
<div key={step.title} className={'relative flex gap-6'}>
{/* Vertical connector */}
{i < arr.length - 1 && (
<div className={'absolute left-[1.125rem] top-10 bottom-0 w-px bg-neutral-200'} />
)}
<div className={'relative flex-shrink-0'}>
<div
className={
'flex h-9 w-9 items-center justify-center rounded-full border-2 border-neutral-200 bg-white text-sm font-bold text-neutral-900'
}
>
{i + 1}
</div>
</div>
<div className={i < arr.length - 1 ? 'pb-8' : ''}>
<p className={'font-semibold text-neutral-900'}>{step.title}</p>
<p className={'mt-1 text-sm text-neutral-600'}>{step.description}</p>
</div>
</div>
))}
</div>
</div>
</motion.div>
</section>
{/* CTA Section */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-20'}>
<div
className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]'
}
/>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-3xl text-center'}
>
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}>
Your domain can receive emails too
</h2>
<p className={'mt-6 text-lg text-neutral-600'}>
Set up inbound email on any verified domain in minutes. Replies, support tickets, and webhooks, all from
one platform.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> </div>
</div>
</div>
</motion.div>
))}
</div>
</div>
</section>
{/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
<div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
<motion.h2
initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}}
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}
>
Your domain can receive emails too.
</motion.h2>
<motion.div
initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}}
className={'flex max-w-md flex-col gap-6'}
>
<p className={'text-base text-neutral-300 sm:text-lg'}>
Free plan available. $0.001 per email on paid. No credit card required.
</p>
<div className={'flex flex-wrap gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
> >
<span className={'flex items-center gap-2'}>
Get started for free Get started for free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className="h-4 w-4" />
</span>
</motion.a> </motion.a>
<Link <Link
href={'/pricing'} href={'/pricing'}
className={ className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
> >
View pricing View pricing
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main> </main>
<Footer /> <Footer />
+201 -177
View File
@@ -8,37 +8,35 @@ import Head from 'next/head';
const features = [ const features = [
{ {
icon: <Filter className="h-5 w-5" />, icon: <Filter className="h-6 w-6" strokeWidth={1.5} />,
title: 'Dynamic Filtering', title: 'Dynamic Filtering',
description: description: 'Create segments based on contact data, custom fields, email activity, and events with powerful AND/OR logic.',
'Create segments based on contact data, custom fields, email activity, and events with powerful AND/OR logic.', featured: true,
}, },
{ {
icon: <TrendingUp className="h-5 w-5" />, icon: <TrendingUp className="h-6 w-6" strokeWidth={1.5} />,
title: 'Real-Time Updates', title: 'Real-Time Updates',
description: 'Dynamic segments automatically update as contact data changes, always keeping your audience current.', description: 'Dynamic segments automatically update as contact data changes, always keeping your audience current.',
}, },
{ {
icon: <GitBranch className="h-5 w-5" />, icon: <GitBranch className="h-6 w-6" strokeWidth={1.5} />,
title: 'Workflow Integration', title: 'Workflow Integration',
description: description: 'Trigger workflows when contacts enter or exit segments, or use segment conditions in workflow branching.',
'Trigger workflows when contacts enter or exit segments, or use segment conditions in workflow branching.',
}, },
{ {
icon: <Target className="h-5 w-5" />, icon: <Target className="h-6 w-6" strokeWidth={1.5} />,
title: 'Campaign Targeting', title: 'Campaign Targeting',
description: description: 'Send targeted campaigns to specific segments instead of your entire contact list. Less noise, more signal.',
'Send targeted campaigns to specific segments instead of your entire contact list. Less noise, more signal.',
}, },
{ {
icon: <Users className="h-5 w-5" />, icon: <Users className="h-6 w-6" strokeWidth={1.5} />,
title: 'Static Segments', title: 'Static Segments',
description: 'Manually curate contact lists for special groups like beta testers or VIP customers.', description: 'Manually curate contact lists for special groups like beta testers or VIP customers.',
}, },
{ {
icon: <Mail className="h-5 w-5" />, icon: <Mail className="h-6 w-6" strokeWidth={1.5} />,
title: 'Behavior-Based', title: 'Behavior-Based',
description: 'Segment by email engagement - who opened, clicked, bounced, or never received your emails.', description: 'Segment by email engagement who opened, clicked, bounced, or never received your emails.',
}, },
]; ];
@@ -50,7 +48,7 @@ const filterExamples = [
}, },
{ {
title: 'Re-engagement Needed', title: 'Re-engagement Needed',
description: 'Find inactive users who need a nudge to come back. Sometimes they just need a reminder.', description: 'Find inactive users who need a nudge to come back',
filters: ['Last activity older than 60 days', 'Email sent but not opened', 'Subscribed equals true'], filters: ['Last activity older than 60 days', 'Email sent but not opened', 'Subscribed equals true'],
}, },
{ {
@@ -62,28 +60,25 @@ const filterExamples = [
const useCases = [ const useCases = [
{ {
icon: <Mail className="h-6 w-6" />, icon: <Mail className="h-6 w-6" strokeWidth={1.5} />,
title: 'Targeted Campaigns', title: 'Targeted Campaigns',
description: description:
'Send newsletters and announcements to specific audience segments instead of blasting everyone. Increase open rates by sending relevant content to the right people. Your unsubscribe rate will thank you.', 'Send newsletters and announcements to specific audience segments instead of blasting everyone. Increase open rates by sending relevant content to the right people.',
}, },
{ {
icon: <GitBranch className="h-6 w-6" />, icon: <GitBranch className="h-6 w-6" strokeWidth={1.5} />,
title: 'Behavior-Based Workflows', title: 'Behavior-Based Workflows',
description: description:
'Trigger workflows when contacts enter segments like "VIP Customers" or "Churning Users". Create personalized automations based on segment membership.', 'Trigger workflows when contacts enter segments like "VIP Customers" or "Churning Users". Create personalized automations based on segment membership.',
}, },
{ {
icon: <Target className="h-6 w-6" />, icon: <Target className="h-6 w-6" strokeWidth={1.5} />,
title: 'A/B Testing', title: 'A/B Testing',
description: description:
'Create segments for test groups and control groups. Send different campaigns to each segment and measure results.', 'Create segments for test groups and control groups. Send different campaigns to each segment and measure results.',
}, },
]; ];
/**
*
*/
export default function SegmentsFeature() { export default function SegmentsFeature() {
return ( return (
<> <>
@@ -96,125 +91,157 @@ export default function SegmentsFeature() {
<meta property="og:title" content="Audience Segmentation - Smart Contact Organization | Plunk" /> <meta property="og:title" content="Audience Segmentation - Smart Contact Organization | Plunk" />
<meta <meta
property="og:description" property="og:description"
content="Create dynamic and static segments to organize your contacts. Filter by behavior, attributes, and engagement. Target campaigns and trigger workflows based on segment membership." content="Create dynamic and static segments to organize your contacts. Filter by behavior, attributes, and engagement."
/> />
</Head> </Head>
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-20 sm:py-32'}> {/* Hero */}
{/* Subtle background grid */} <section className={'relative overflow-hidden'}>
<div <div
aria-hidden
className={ className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]' 'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'
} }
/> />
<div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
animate={{opacity: 1, y: 0}} animate={{opacity: 1, y: 0}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl text-center'}
> >
<div className={'mb-6 inline-flex items-center gap-2 rounded-full bg-neutral-100 px-4 py-2 text-sm'}> <div
<Users className="h-4 w-4 text-neutral-600" /> style={{fontFamily: 'var(--font-mono)'}}
<span className={'font-medium text-neutral-600'}>Audience Segmentation</span> className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}
>
Audience Segmentation
</div> </div>
<h1
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}> style={{fontFamily: 'var(--font-display)'}}
Target the Right Audience, className={
'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'
}
>
Target the right audience,
<br /> <br />
Every Time every time.
</h1> </h1>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>
Organize contacts into dynamic segments based on behavior, attributes, and engagement. Send targeted Organize contacts into dynamic segments based on behavior, attributes, and engagement. Send targeted
campaigns and trigger personalized workflows. campaigns and trigger personalized workflows.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> <div className={'mt-10 flex flex-wrap gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800' 'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'
} }
> >
<span className={'flex items-center gap-2'}>
Start segmenting Start segmenting
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</span>
</motion.a> </motion.a>
<Link <Link
href={WIKI_URI} href={WIKI_URI}
target={'_blank'} target={'_blank'}
className={ className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400' 'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'
} }
> >
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Features Grid */} {/* Features grid */}
<section className={'py-20'}> <section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'} className={'mb-16'}
>
<h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}>
The right message to the right person The right message to the right person
</h2> </h2>
<p className={'mt-4 text-lg text-neutral-600'}>Build precise audiences and send campaigns that land</p> <p className={'mt-4 text-lg text-neutral-600'}>Build precise audiences and send campaigns that land</p>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-4 sm:grid-cols-2 lg:grid-cols-3'}>
{features.map((feature, index) => ( {features.map((feature, index) => {
const highlighted = feature.featured;
return (
<motion.div <motion.div
key={feature.title} key={feature.title}
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: index * 0.06, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-10 transition hover:bg-neutral-50'}
>
<div
className={ className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110' highlighted
? 'flex min-h-[16rem] flex-col justify-between rounded-[28px] border border-neutral-900 bg-neutral-900 p-8 text-white'
: 'flex min-h-[16rem] flex-col justify-between rounded-[28px] border border-neutral-200 bg-white p-8 transition hover:border-neutral-900'
} }
> >
{feature.icon} <div className={'flex items-start justify-between'}>
<div className={highlighted ? 'text-white' : 'text-neutral-900'}>{feature.icon}</div>
<span
style={{fontFamily: 'var(--font-mono)'}}
className={`text-[11px] uppercase tracking-[0.18em] ${highlighted ? 'text-neutral-500' : 'text-neutral-400'}`}
>
{String(index + 1).padStart(2, '0')}
</span>
</div>
<div>
<h3
style={{fontFamily: 'var(--font-display)'}}
className={`mt-8 text-xl font-bold tracking-[-0.02em] ${highlighted ? 'text-white' : 'text-neutral-900'}`}
>
{feature.title}
</h3>
<p className={`mt-2 text-sm leading-relaxed ${highlighted ? 'text-neutral-300' : 'text-neutral-600'}`}>
{feature.description}
</p>
</div> </div>
<h3 className={'mt-6 text-lg font-semibold text-neutral-900'}>{feature.title}</h3>
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>{feature.description}</p>
</motion.div> </motion.div>
))} );
})}
</div>
</div> </div>
</section> </section>
{/* Filter Examples */} {/* Filter examples */}
<section className={'py-20'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'} className={'mb-16'}
>
<h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}>
Flexible filtering options Flexible filtering options
</h2> </h2>
<p className={'mt-4 text-lg text-neutral-600'}>Build complex segments with nested AND/OR logic</p> <p className={'mt-4 text-lg text-neutral-600'}>Build complex segments with nested AND/OR logic</p>
</motion.div> </motion.div>
<div className={'mx-auto max-w-5xl space-y-6'}> <div className={'space-y-4'}>
{filterExamples.map((example, index) => ( {filterExamples.map((example, index) => (
<motion.div <motion.div
key={example.title} key={example.title}
@@ -222,122 +249,115 @@ export default function SegmentsFeature() {
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'rounded-xl border border-neutral-200 bg-white p-8'} className={'rounded-[24px] border border-neutral-200 bg-white p-8'}
> >
<div className={'flex items-start justify-between gap-6'}> <h3
<div className={'flex-1'}> style={{fontFamily: 'var(--font-display)'}}
<h3 className={'text-xl font-semibold text-neutral-900'}>{example.title}</h3> className={'text-xl font-bold tracking-[-0.02em] text-neutral-900'}
<p className={'mt-2 text-neutral-600'}>{example.description}</p> >
</div> {example.title}
</div> </h3>
<p className={'mt-1 text-neutral-600'}>{example.description}</p>
<div className={'mt-6 space-y-2'}> <div className={'mt-6 space-y-2'}>
{example.filters.map((filter, filterIndex) => ( {example.filters.map((filter, filterIndex) => (
<div key={filterIndex} className={'flex items-center gap-3 rounded-lg bg-neutral-50 px-4 py-3'}> <div key={filterIndex} className={'flex items-center gap-3 rounded-xl border border-neutral-100 bg-neutral-50 px-4 py-3'}>
<Filter className="h-4 w-4 flex-shrink-0 text-neutral-400" /> <Filter className="h-4 w-4 flex-shrink-0 text-neutral-400" />
<span className={'font-mono text-sm text-neutral-700'}>{filter}</span> <span style={{fontFamily: 'var(--font-mono)'}} className={'text-sm text-neutral-700'}>
{filter}
</span>
</div> </div>
))} ))}
</div> </div>
</motion.div> </motion.div>
))} ))}
</div> </div>
</div>
</section> </section>
{/* Types of Segments */} {/* Segment types */}
<section className={'py-20'}> <section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl text-center'} className={'mb-16'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}>Two types of segments</h2> <h2
<p className={'mt-6 text-lg text-neutral-600'}>Choose between dynamic filtering or manual curation</p> style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
>
Two types of segments
</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Choose between dynamic filtering or manual curation</p>
</motion.div> </motion.div>
<div className={'mx-auto mt-16 max-w-5xl'}> <div className={'grid gap-4 sm:grid-cols-2'}>
<div className={'grid gap-8 lg:grid-cols-2'}> {[
{
icon: <TrendingUp className="h-6 w-6" strokeWidth={1.5} />,
title: 'Dynamic Segments',
description: 'Automatically update based on filter conditions. As contact data changes, segment membership updates in real-time.',
bullets: ['Filter-based membership', 'Automatic updates', 'Optional entry/exit tracking'],
},
{
icon: <Users className="h-6 w-6" strokeWidth={1.5} />,
title: 'Static Segments',
description: 'Manually curate your segment by adding specific contacts. Membership stays fixed until you change it.',
bullets: ['Manual contact selection', 'Fixed membership', 'Perfect for VIP lists'],
},
].map((type, i) => (
<motion.div <motion.div
initial={{opacity: 0, y: 20}} key={type.title}
initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: i * 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'rounded-xl border border-neutral-200 bg-white p-8'} className={'rounded-[24px] border border-neutral-200 bg-white p-8'}
> >
<div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}> <div className={'text-neutral-900'}>{type.icon}</div>
<TrendingUp className="h-6 w-6" /> <h3
</div> style={{fontFamily: 'var(--font-display)'}}
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Dynamic Segments</h3> className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}
<p className={'mt-2 text-neutral-600'}>
Automatically update based on filter conditions. As contact data changes, segment membership updates
in real-time.
</p>
<div className={'mt-6 space-y-2'}>
<div className={'flex items-center gap-2 text-sm text-neutral-600'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-900'} />
<span>Filter-based membership</span>
</div>
<div className={'flex items-center gap-2 text-sm text-neutral-600'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-900'} />
<span>Automatic updates</span>
</div>
<div className={'flex items-center gap-2 text-sm text-neutral-600'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-900'} />
<span>Optional entry/exit tracking</span>
</div>
</div>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
className={'rounded-xl border border-neutral-200 bg-white p-8'}
> >
<div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}> {type.title}
<Users className="h-6 w-6" /> </h3>
</div> <p className={'mt-2 text-neutral-600'}>{type.description}</p>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Static Segments</h3> <ul className={'mt-6 space-y-2'}>
<p className={'mt-2 text-neutral-600'}> {type.bullets.map(b => (
Manually curate your segment by adding specific contacts. Membership stays fixed until you change it. <li key={b} className={'flex items-center gap-2 text-sm text-neutral-600'}>
</p> <div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-900'} />
<div className={'mt-6 space-y-2'}> {b}
<div className={'flex items-center gap-2 text-sm text-neutral-600'}> </li>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-900'} /> ))}
<span>Manual contact selection</span> </ul>
</div>
<div className={'flex items-center gap-2 text-sm text-neutral-600'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-900'} />
<span>Fixed membership</span>
</div>
<div className={'flex items-center gap-2 text-sm text-neutral-600'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-900'} />
<span>Perfect for VIP lists</span>
</div>
</div>
</motion.div> </motion.div>
))}
</div> </div>
</div> </div>
</section> </section>
{/* Use Cases */} {/* Use cases */}
<section className={'py-20'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'} className={'mb-16'}
>
<h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}>
Use segments everywhere Use segments everywhere
</h2> </h2>
<p className={'mt-4 text-lg text-neutral-600'}>From targeted campaigns to automated workflows</p> <p className={'mt-4 text-lg text-neutral-600'}>From targeted campaigns to automated workflows</p>
</motion.div> </motion.div>
<div className={'mx-auto max-w-5xl space-y-8'}> <div className={'space-y-4'}>
{useCases.map((useCase, index) => ( {useCases.map((useCase, index) => (
<motion.div <motion.div
key={useCase.title} key={useCase.title}
@@ -345,71 +365,75 @@ export default function SegmentsFeature() {
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'rounded-xl border border-neutral-200 bg-white p-8'} className={'rounded-[24px] border border-neutral-200 bg-white p-8'}
> >
<div className={'flex items-start gap-6'}> <div className={'flex items-start gap-6'}>
<div <div className={'flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-full border border-neutral-200 text-neutral-900'}>
className={
'flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-xl bg-neutral-900 text-white'
}
>
{useCase.icon} {useCase.icon}
</div> </div>
<div className={'flex-1'}> <div className={'flex-1'}>
<h3 className={'text-xl font-semibold text-neutral-900'}>{useCase.title}</h3> <h3
style={{fontFamily: 'var(--font-display)'}}
className={'text-xl font-bold tracking-[-0.02em] text-neutral-900'}
>
{useCase.title}
</h3>
<p className={'mt-2 text-neutral-600'}>{useCase.description}</p> <p className={'mt-2 text-neutral-600'}>{useCase.description}</p>
</div> </div>
</div> </div>
</motion.div> </motion.div>
))} ))}
</div> </div>
</div>
</section> </section>
{/* CTA Section */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-20'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2
} initial={{opacity: 0, y: 16}}
/>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-3xl text-center'} style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}> Stop sending the same email to everyone.
Stop sending the same email to everyone </motion.h2>
</h2> <motion.div
<p className={'mt-6 text-lg text-neutral-600'}> initial={{opacity: 0, y: 16}}
Build precise audience segments and watch your open rates climb. 1,000 emails free, no credit card required. whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}}
className={'flex max-w-md flex-col gap-6'}
>
<p className={'text-base text-neutral-300 sm:text-lg'}>
Build precise audience segments and watch your open rates climb. 1,000 emails free, no credit card
required.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> <div className={'flex flex-wrap gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
> >
<span className={'flex items-center gap-2'}>
Get started for free Get started for free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className="h-4 w-4" />
</span>
</motion.a> </motion.a>
<Link <Link
href={'/pricing'} href={'/pricing'}
className={ className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
> >
View pricing View pricing
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main> </main>
<Footer /> <Footer />
+172 -129
View File
@@ -8,34 +8,33 @@ import Head from 'next/head';
const features = [ const features = [
{ {
icon: <Settings className="h-5 w-5" />, icon: <Settings className="h-6 w-6" strokeWidth={1.5} />,
title: 'Simple Configuration', title: 'Simple Configuration',
description: 'Quick setup with your project credentials. Works with any email client or application.', description: 'Quick setup with your project credentials. Works with any email client or application.',
featured: true,
}, },
{ {
icon: <Lock className="h-5 w-5" />, icon: <Lock className="h-6 w-6" strokeWidth={1.5} />,
title: 'Secure Connections', title: 'Secure Connections',
description: 'TLS/SSL encryption on ports 465 and 587. Your emails are always transmitted securely.', description: 'TLS/SSL encryption on ports 465 and 587. Your emails are always transmitted securely.',
}, },
{ {
icon: <Mail className="h-5 w-5" />, icon: <Mail className="h-6 w-6" strokeWidth={1.5} />,
title: 'Universal Compatibility', title: 'Universal Compatibility',
description: description: 'Works with Outlook, Thunderbird, Apple Mail, or any SMTP-compatible application.',
'Works with Outlook, Thunderbird, Apple Mail, or any SMTP-compatible application. Even that ancient email client from 2005.',
}, },
{ {
icon: <Server className="h-5 w-5" />, icon: <Server className="h-6 w-6" strokeWidth={1.5} />,
title: 'Domain Validation', title: 'Domain Validation',
description: 'Automatic verification that your sender domain is verified before accepting emails.', description: 'Automatic verification that your sender domain is verified before accepting emails.',
}, },
{ {
icon: <Shield className="h-5 w-5" />, icon: <Shield className="h-6 w-6" strokeWidth={1.5} />,
title: 'Full Feature Support', title: 'Full Feature Support',
description: description: 'Attachments, custom headers, HTML emails, and multiple recipients.',
'Attachments, custom headers, HTML emails, and multiple recipients. Send those cat memes with confidence.',
}, },
{ {
icon: <Code2 className="h-5 w-5" />, icon: <Code2 className="h-6 w-6" strokeWidth={1.5} />,
title: 'Same Infrastructure', title: 'Same Infrastructure',
description: 'SMTP emails use the same reliable delivery infrastructure as API emails with full tracking.', description: 'SMTP emails use the same reliable delivery infrastructure as API emails with full tracking.',
}, },
@@ -54,21 +53,21 @@ const comparisonData = [
const useCases = [ const useCases = [
{ {
icon: <Settings className="h-6 w-6" />, icon: <Settings className="h-6 w-6" strokeWidth={1.5} />,
title: 'Legacy System Integration', title: 'Legacy System Integration',
description: description:
'Already have applications using SMTP? No need to rewrite code. Just swap your SMTP credentials and keep everything else the same. Your PM will love you.', 'Already have applications using SMTP? No need to rewrite code. Just swap your SMTP credentials and keep everything else the same.',
benefit: 'Zero code changes required', benefit: 'Zero code changes required',
}, },
{ {
icon: <Mail className="h-6 w-6" />, icon: <Mail className="h-6 w-6" strokeWidth={1.5} />,
title: 'Email Client Sending', title: 'Email Client Sending',
description: description:
'Marketing teams can send emails directly from Outlook, Thunderbird, or Apple Mail using familiar tools without learning new APIs.', 'Marketing teams can send emails directly from Outlook, Thunderbird, or Apple Mail using familiar tools without learning new APIs.',
benefit: 'No technical knowledge needed', benefit: 'No technical knowledge needed',
}, },
{ {
icon: <Code2 className="h-6 w-6" />, icon: <Code2 className="h-6 w-6" strokeWidth={1.5} />,
title: 'Framework Compatibility', title: 'Framework Compatibility',
description: description:
'Works with any framework or language that supports SMTP. Perfect for older systems or platforms without HTTP API support.', 'Works with any framework or language that supports SMTP. Perfect for older systems or platforms without HTTP API support.',
@@ -76,9 +75,6 @@ const useCases = [
}, },
]; ];
/**
*
*/
export default function SMTPFeature() { export default function SMTPFeature() {
return ( return (
<> <>
@@ -97,161 +93,201 @@ export default function SMTPFeature() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-20 sm:py-32'}> {/* Hero */}
{/* Subtle background grid */} <section className={'relative overflow-hidden'}>
<div <div
aria-hidden
className={ className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]' 'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'
} }
/> />
<div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
animate={{opacity: 1, y: 0}} animate={{opacity: 1, y: 0}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl text-center'}
> >
<div className={'mb-6 inline-flex items-center gap-2 rounded-full bg-neutral-100 px-4 py-2 text-sm'}> <div
<Server className="h-4 w-4 text-neutral-600" /> style={{fontFamily: 'var(--font-mono)'}}
<span className={'font-medium text-neutral-600'}>SMTP Email Sending</span> className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}
>
SMTP
</div> </div>
<h1
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}> style={{fontFamily: 'var(--font-display)'}}
Send Emails via SMTP or API
</h1>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}>
Use our HTTP API for modern apps or drop in SMTP credentials for any legacy system. Same deliverability, same pricing, zero lock-in.
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={ className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800' 'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'
}
>
Send via SMTP
<br />
or API. Your call.
</h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>
Use our HTTP API for modern apps or drop in SMTP credentials for any legacy system. Same deliverability,
same pricing, zero lock-in.
</p>
<div className={'mt-10 flex flex-wrap gap-3'}>
<motion.a
whileHover={{scale: 1.015}}
whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'
} }
> >
<span className={'flex items-center gap-2'}>
Get SMTP credentials Get SMTP credentials
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</span>
</motion.a> </motion.a>
<Link <Link
href={WIKI_URI} href={WIKI_URI}
target={'_blank'} target={'_blank'}
className={ className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400' 'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'
} }
> >
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Features Grid */} {/* Features grid */}
<section className={'py-20'}> <section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'} className={'mb-16'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}>SMTP that works with everything</h2> <h2
<p className={'mt-4 text-lg text-neutral-600'}>Full authentication, tracking, and deliverability out of the box</p> style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
>
SMTP that works with everything
</h2>
<p className={'mt-4 text-lg text-neutral-600'}>
Full authentication, tracking, and deliverability out of the box
</p>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-4 sm:grid-cols-2 lg:grid-cols-3'}>
{features.map((feature, index) => ( {features.map((feature, index) => {
const highlighted = feature.featured;
return (
<motion.div <motion.div
key={feature.title} key={feature.title}
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: index * 0.06, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-10 transition hover:bg-neutral-50'}
>
<div
className={ className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110' highlighted
? 'flex min-h-[16rem] flex-col justify-between rounded-[28px] border border-neutral-900 bg-neutral-900 p-8 text-white'
: 'flex min-h-[16rem] flex-col justify-between rounded-[28px] border border-neutral-200 bg-white p-8 transition hover:border-neutral-900'
} }
> >
{feature.icon} <div className={'flex items-start justify-between'}>
<div className={highlighted ? 'text-white' : 'text-neutral-900'}>{feature.icon}</div>
<span
style={{fontFamily: 'var(--font-mono)'}}
className={`text-[11px] uppercase tracking-[0.18em] ${highlighted ? 'text-neutral-500' : 'text-neutral-400'}`}
>
{String(index + 1).padStart(2, '0')}
</span>
</div>
<div>
<h3
style={{fontFamily: 'var(--font-display)'}}
className={`mt-8 text-xl font-bold tracking-[-0.02em] ${highlighted ? 'text-white' : 'text-neutral-900'}`}
>
{feature.title}
</h3>
<p className={`mt-2 text-sm leading-relaxed ${highlighted ? 'text-neutral-300' : 'text-neutral-600'}`}>
{feature.description}
</p>
</div> </div>
<h3 className={'mt-6 text-lg font-semibold text-neutral-900'}>{feature.title}</h3>
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>{feature.description}</p>
</motion.div> </motion.div>
))} );
})}
</div>
</div> </div>
</section> </section>
{/* Comparison Table */} {/* Comparison table */}
<section className={'py-20'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-12 text-center'} className={'mb-12'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}>SMTP vs API</h2> <h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
>
SMTP vs API
</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Choose the right option for your use case</p> <p className={'mt-4 text-lg text-neutral-600'}>Choose the right option for your use case</p>
</motion.div> </motion.div>
<div className={'mx-auto max-w-4xl'}> <div className={'overflow-hidden rounded-[24px] border border-neutral-200 bg-white'}>
<div className={'overflow-hidden rounded-xl border border-neutral-200 bg-white'}>
<table className={'w-full'}> <table className={'w-full'}>
<thead className={'bg-neutral-50'}> <thead className={'border-b border-neutral-200 bg-neutral-50'}>
<tr> <tr>
<th className={'px-6 py-4 text-left text-sm font-semibold text-neutral-900'}>Feature</th> <th className={'px-6 py-4 text-left text-sm font-semibold text-neutral-900'}>Feature</th>
<th className={'px-6 py-4 text-center text-sm font-semibold text-neutral-900'}>Traditional SMTP</th> <th className={'px-6 py-4 text-center text-sm font-semibold text-neutral-500'}>Traditional SMTP</th>
<th className={'bg-neutral-100 px-6 py-4 text-center text-sm font-semibold text-neutral-900'}> <th className={'bg-neutral-900 px-6 py-4 text-center text-sm font-semibold text-white'}>Plunk SMTP</th>
Plunk SMTP <th className={'px-6 py-4 text-center text-sm font-semibold text-neutral-500'}>Plunk API</th>
</th>
<th className={'px-6 py-4 text-center text-sm font-semibold text-neutral-900'}>Plunk API</th>
</tr> </tr>
</thead> </thead>
<tbody className={'divide-y divide-neutral-200'}> <tbody className={'divide-y divide-neutral-100'}>
{comparisonData.map((row, index) => ( {comparisonData.map((row, index) => (
<tr key={index} className={'transition hover:bg-neutral-50'}> <tr key={index} className={'transition hover:bg-neutral-50'}>
<td className={'px-6 py-4 text-sm text-neutral-900'}>{row.feature}</td> <td className={'px-6 py-4 text-sm font-medium text-neutral-900'}>{row.feature}</td>
<td className={'px-6 py-4 text-center text-sm text-neutral-600'}>{row.traditional}</td> <td className={'px-6 py-4 text-center text-sm text-neutral-500'}>{row.traditional}</td>
<td className={'bg-neutral-50 px-6 py-4 text-center text-sm font-medium text-neutral-900'}> <td className={'bg-neutral-50 px-6 py-4 text-center text-sm font-semibold text-neutral-900'}>{row.plunkSMTP}</td>
{row.plunkSMTP} <td className={'px-6 py-4 text-center text-sm text-neutral-500'}>{row.plunkAPI}</td>
</td>
<td className={'px-6 py-4 text-center text-sm text-neutral-600'}>{row.plunkAPI}</td>
</tr> </tr>
))} ))}
</tbody> </tbody>
</table> </table>
</div> </div>
<div className={'mt-6 rounded-lg bg-neutral-50 p-4 text-center'}> <p className={'mt-4 text-sm text-neutral-500'}>
<p className={'text-sm text-neutral-600'}> Recommendation: Use the API for modern applications with workflow automation. Use SMTP for email clients
<strong>Recommendation:</strong> Use API for modern applications with workflow automation. Use SMTP for and legacy systems.
email clients and legacy systems.
</p> </p>
</div> </div>
</div>
</section> </section>
{/* Use Cases */} {/* Use cases */}
<section className={'py-20'}> <section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'} className={'mb-16'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}>When to use SMTP</h2> <h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
>
When to use SMTP
</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Perfect for these scenarios</p> <p className={'mt-4 text-lg text-neutral-600'}>Perfect for these scenarios</p>
</motion.div> </motion.div>
<div className={'mx-auto max-w-5xl space-y-8'}> <div className={'space-y-4'}>
{useCases.map((useCase, index) => ( {useCases.map((useCase, index) => (
<motion.div <motion.div
key={useCase.title} key={useCase.title}
@@ -259,74 +295,81 @@ export default function SMTPFeature() {
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'rounded-xl border border-neutral-200 bg-white p-8'} className={'rounded-[24px] border border-neutral-200 bg-white p-8'}
> >
<div className={'flex items-start gap-6'}> <div className={'flex items-start gap-6'}>
<div <div className={'flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-full border border-neutral-200 text-neutral-900'}>
className={
'flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-xl bg-neutral-900 text-white'
}
>
{useCase.icon} {useCase.icon}
</div> </div>
<div className={'flex-1'}> <div className={'flex-1'}>
<h3 className={'text-xl font-semibold text-neutral-900'}>{useCase.title}</h3> <h3
style={{fontFamily: 'var(--font-display)'}}
className={'text-xl font-bold tracking-[-0.02em] text-neutral-900'}
>
{useCase.title}
</h3>
<p className={'mt-2 text-neutral-600'}>{useCase.description}</p> <p className={'mt-2 text-neutral-600'}>{useCase.description}</p>
<div className={'mt-4 inline-flex items-center gap-2 rounded-full bg-neutral-100 px-4 py-2'}> <div
<div className={'h-2 w-2 rounded-full bg-green-500'} /> style={{fontFamily: 'var(--font-mono)'}}
<span className={'text-sm font-medium text-neutral-700'}>{useCase.benefit}</span> className={'mt-4 inline-flex items-center gap-2 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}
>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-900'} />
{useCase.benefit}
</div> </div>
</div> </div>
</div> </div>
</motion.div> </motion.div>
))} ))}
</div> </div>
</div>
</section> </section>
{/* CTA Section */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-20'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2
} initial={{opacity: 0, y: 16}}
/>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-3xl text-center'} style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}>Start sending via SMTP</h2> Start sending via SMTP today.
<p className={'mt-6 text-lg text-neutral-600'}> </motion.h2>
Get your SMTP credentials and start sending emails from any client or application. No credit card <motion.div
required. initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}}
className={'flex max-w-md flex-col gap-6'}
>
<p className={'text-base text-neutral-300 sm:text-lg'}>
Get your SMTP credentials and start sending from any client or application. No credit card required.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> <div className={'flex flex-wrap gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
> >
<span className={'flex items-center gap-2'}>
Get started for free Get started for free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className="h-4 w-4" />
</span>
</motion.a> </motion.a>
<Link <Link
href={'/pricing'} href={'/pricing'}
className={ className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
> >
View pricing View pricing
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main> </main>
<Footer /> <Footer />
+194 -166
View File
@@ -8,32 +8,33 @@ import Head from 'next/head';
const features = [ const features = [
{ {
icon: <Zap className="h-5 w-5" />, icon: <Zap className="h-6 w-6" strokeWidth={1.5} />,
title: 'Event-Driven Triggers', title: 'Event-Driven Triggers',
description: 'Start workflows automatically when users sign up, make a purchase, or perform any custom action.', description: 'Start workflows automatically when users sign up, make a purchase, or perform any custom action.',
featured: true,
}, },
{ {
icon: <Mail className="h-5 w-5" />, icon: <Mail className="h-6 w-6" strokeWidth={1.5} />,
title: 'Smart Email Sequences', title: 'Smart Email Sequences',
description: 'Send personalized emails at the right time with dynamic content based on user data.', description: 'Send personalized emails at the right time with dynamic content based on user data.',
}, },
{ {
icon: <Clock className="h-5 w-5" />, icon: <Clock className="h-6 w-6" strokeWidth={1.5} />,
title: 'Time-Based Delays', title: 'Time-Based Delays',
description: 'Add strategic delays between steps to create perfectly timed email journeys. Patience is a virtue.', description: 'Add strategic delays between steps to create perfectly timed email journeys. Patience is a virtue.',
}, },
{ {
icon: <GitBranch className="h-5 w-5" />, icon: <GitBranch className="h-6 w-6" strokeWidth={1.5} />,
title: 'Conditional Logic', title: 'Conditional Logic',
description: 'Branch workflows based on user behavior, attributes, or engagement to personalize every journey.', description: 'Branch workflows based on user behavior, attributes, or engagement to personalize every journey.',
}, },
{ {
icon: <Webhook className="h-5 w-5" />, icon: <Webhook className="h-6 w-6" strokeWidth={1.5} />,
title: 'External Integrations', title: 'External Integrations',
description: 'Connect to external systems with webhooks to sync data or trigger actions outside of Plunk.', description: 'Connect to external systems with webhooks to sync data or trigger actions outside of Plunk.',
}, },
{ {
icon: <RefreshCw className="h-5 w-5" />, icon: <RefreshCw className="h-6 w-6" strokeWidth={1.5} />,
title: 'Re-entry Control', title: 'Re-entry Control',
description: 'Decide whether contacts can enter workflows multiple times or just once. No spam, just strategy.', description: 'Decide whether contacts can enter workflows multiple times or just once. No spam, just strategy.',
}, },
@@ -41,21 +42,21 @@ const features = [
const useCases = [ const useCases = [
{ {
icon: <UserPlus className="h-6 w-6" />, icon: <UserPlus className="h-6 w-6" strokeWidth={1.5} />,
title: 'User Onboarding', title: 'User Onboarding',
description: description:
'Welcome new users with a personalized email series that guides them through your product features and helps them get started.', 'Welcome new users with a personalized email series that guides them through your product features and helps them get started.',
example: 'Trigger on signup → Send welcome email → Wait 2 days → Send getting started tips', example: 'Trigger on signup → Send welcome email → Wait 2 days → Send getting started tips',
}, },
{ {
icon: <Mail className="h-6 w-6" />, icon: <Mail className="h-6 w-6" strokeWidth={1.5} />,
title: 'Abandoned Cart Recovery', title: 'Abandoned Cart Recovery',
description: description:
'Automatically remind customers about items left in their cart with timely follow-ups and special incentives. Those forgotten items need a gentle nudge.', 'Automatically remind customers about items left in their cart with timely follow-ups and special incentives.',
example: 'Trigger on cart abandoned → Wait 1 hour → Send reminder → Wait 1 day → Send discount offer', example: 'Trigger on cart abandoned → Wait 1 hour → Send reminder → Wait 1 day → Send discount offer',
}, },
{ {
icon: <RefreshCw className="h-6 w-6" />, icon: <RefreshCw className="h-6 w-6" strokeWidth={1.5} />,
title: 'Re-engagement Campaigns', title: 'Re-engagement Campaigns',
description: description:
'Win back inactive users with targeted campaigns based on their last activity and engagement patterns.', 'Win back inactive users with targeted campaigns based on their last activity and engagement patterns.',
@@ -63,9 +64,6 @@ const useCases = [
}, },
]; ];
/**
*
*/
export default function WorkflowsFeature() { export default function WorkflowsFeature() {
return ( return (
<> <>
@@ -84,180 +82,136 @@ export default function WorkflowsFeature() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-20 sm:py-32'}> {/* Hero */}
{/* Subtle background grid */} <section className={'relative overflow-hidden'}>
<div <div
aria-hidden
className={ className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]' 'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'
} }
/> />
<div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
animate={{opacity: 1, y: 0}} animate={{opacity: 1, y: 0}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl text-center'}
> >
<div className={'mb-6 inline-flex items-center gap-2 rounded-full bg-neutral-100 px-4 py-2 text-sm'}> <div
<Zap className="h-4 w-4 text-neutral-600" /> style={{fontFamily: 'var(--font-mono)'}}
<span className={'font-medium text-neutral-600'}>Workflow Automation</span> className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}
>
Workflow Automation
</div> </div>
<h1
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}> style={{fontFamily: 'var(--font-display)'}}
Email Automation className={
'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'
}
>
Email automation
<br /> <br />
That Actually Works that actually works.
</h1> </h1>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>
Turn events into personalized email journeys. Build sophisticated automation workflows with our visual Turn events into personalized email journeys. Build sophisticated automation workflows with our visual
no-code builder. no-code builder.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> <div className={'mt-10 flex flex-wrap gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800' 'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'
} }
> >
<span className={'flex items-center gap-2'}>
Start building workflows Start building workflows
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</span>
</motion.a> </motion.a>
<Link <Link
href={WIKI_URI} href={WIKI_URI}
target={'_blank'} target={'_blank'}
className={ className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400' 'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'
} }
> >
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Features Grid */} {/* Features grid */}
<section className={'py-20'}> <section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'} className={'mb-16'}
>
<h2
style={{fontFamily: 'var(--font-display)'}}
className={
'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'
}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}>
Everything you need for email automation Everything you need for email automation
</h2> </h2>
<p className={'mt-4 text-lg text-neutral-600'}>Powerful features that make complex automations simple</p> <p className={'mt-4 text-lg text-neutral-600'}>Powerful features that make complex automations simple</p>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-4 sm:grid-cols-2 lg:grid-cols-3'}>
{features.map((feature, index) => ( {features.map((feature, index) => {
const highlighted = feature.featured;
return (
<motion.div <motion.div
key={feature.title} key={feature.title}
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: index * 0.06, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-10 transition hover:bg-neutral-50'}
>
<div
className={ className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110' highlighted
? 'flex min-h-[16rem] flex-col justify-between rounded-[28px] border border-neutral-900 bg-neutral-900 p-8 text-white'
: 'flex min-h-[16rem] flex-col justify-between rounded-[28px] border border-neutral-200 bg-white p-8 transition hover:border-neutral-900'
} }
> >
{feature.icon} <div className={'flex items-start justify-between'}>
</div> <div className={highlighted ? 'text-white' : 'text-neutral-900'}>{feature.icon}</div>
<h3 className={'mt-6 text-lg font-semibold text-neutral-900'}>{feature.title}</h3> <span
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>{feature.description}</p> style={{fontFamily: 'var(--font-mono)'}}
</motion.div> className={`text-[11px] uppercase tracking-[0.18em] ${highlighted ? 'text-neutral-500' : 'text-neutral-400'}`}
))}
</div>
</section>
{/* How It Works */}
<section className={'py-20'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl text-center'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}> {String(index + 1).padStart(2, '0')}
Visual workflow builder </span>
</h2> </div>
<p className={'mt-6 text-lg text-neutral-600'}> <div>
Create complex email automations without writing a single line of code <h3
</p> style={{fontFamily: 'var(--font-display)'}}
</motion.div> className={`mt-8 text-xl font-bold tracking-[-0.02em] ${highlighted ? 'text-white' : 'text-neutral-900'}`}
<div className={'mx-auto mt-16 max-w-5xl'}>
<div className={'grid gap-12 lg:grid-cols-3'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}}
> >
<div className={'mb-5 flex items-center gap-4'}> {feature.title}
<div className={'flex h-14 w-14 items-center justify-center rounded-full border-2 border-neutral-200 bg-white text-xl font-bold text-neutral-900'}> </h3>
1 <p className={`mt-2 text-sm leading-relaxed ${highlighted ? 'text-neutral-300' : 'text-neutral-600'}`}>
</div> {feature.description}
</div>
<h3 className={'text-lg font-semibold text-neutral-900'}>Choose a trigger</h3>
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>
Select an event that starts your workflow, like user signup, purchase, or any custom action you track.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
>
<div className={'mb-5 flex items-center gap-4'}>
<div className={'flex h-14 w-14 items-center justify-center rounded-full border-2 border-neutral-200 bg-white text-xl font-bold text-neutral-900'}>
2
</div>
</div>
<h3 className={'text-lg font-semibold text-neutral-900'}>Build your flow</h3>
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>
Drag and drop steps to create your workflow. Add emails, delays, conditions, webhooks, and more.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
>
<div className={'mb-5 flex items-center gap-4'}>
<div className={'flex h-14 w-14 items-center justify-center rounded-full border-2 border-neutral-200 bg-white text-xl font-bold text-neutral-900'}>
3
</div>
</div>
<h3 className={'text-lg font-semibold text-neutral-900'}>Activate and monitor</h3>
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>
Enable your workflow and watch it run automatically. Monitor executions in real-time with full
visibility.
</p> </p>
</div>
</motion.div> </motion.div>
);
})}
</div> </div>
</div> </div>
</section> </section>
{/* Use Cases */} {/* How it works */}
<section className={'py-20'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
@@ -265,13 +219,79 @@ export default function WorkflowsFeature() {
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'} className={'mb-16 text-center'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}> <h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
>
Visual workflow builder
</h2>
<p className={'mt-4 text-lg text-neutral-600'}>
Create complex email automations without writing a single line of code
</p>
</motion.div>
<div className={'mx-auto max-w-4xl'}>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-3'}>
{[
{
step: '01',
title: 'Choose a trigger',
body: 'Select an event that starts your workflow, like user signup, purchase, or any custom action you track.',
},
{
step: '02',
title: 'Build your flow',
body: 'Drag and drop steps to create your workflow. Add emails, delays, conditions, webhooks, and more.',
},
{
step: '03',
title: 'Activate and monitor',
body: 'Enable your workflow and watch it run automatically. Monitor executions in real-time with full visibility.',
},
].map((item, i) => (
<motion.div
key={item.step}
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: i * 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'bg-white p-10'}
>
<div
style={{fontFamily: 'var(--font-mono)'}}
className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-400'}
>
Step {item.step}
</div>
<h3 className={'text-lg font-semibold text-neutral-900'}>{item.title}</h3>
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>{item.body}</p>
</motion.div>
))}
</div>
</div>
</div>
</section>
{/* Use cases */}
<section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16'}
>
<h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
>
Built for every use case Built for every use case
</h2> </h2>
<p className={'mt-4 text-lg text-neutral-600'}>From onboarding to re-engagement, workflows handle it all</p> <p className={'mt-4 text-lg text-neutral-600'}>From onboarding to re-engagement, workflows handle it all</p>
</motion.div> </motion.div>
<div className={'mx-auto max-w-5xl space-y-8'}> <div className={'space-y-4'}>
{useCases.map((useCase, index) => ( {useCases.map((useCase, index) => (
<motion.div <motion.div
key={useCase.title} key={useCase.title}
@@ -279,74 +299,82 @@ export default function WorkflowsFeature() {
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'rounded-xl border border-neutral-200 bg-white p-8'} className={'rounded-[24px] border border-neutral-200 bg-white p-8'}
> >
<div className={'flex items-start gap-6'}> <div className={'flex items-start gap-6'}>
<div <div className={'flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-full border border-neutral-200 bg-white text-neutral-900'}>
className={
'flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-xl bg-neutral-900 text-white'
}
>
{useCase.icon} {useCase.icon}
</div> </div>
<div className={'flex-1'}> <div className={'flex-1'}>
<h3 className={'text-xl font-semibold text-neutral-900'}>{useCase.title}</h3> <h3
style={{fontFamily: 'var(--font-display)'}}
className={'text-xl font-bold tracking-[-0.02em] text-neutral-900'}
>
{useCase.title}
</h3>
<p className={'mt-2 text-neutral-600'}>{useCase.description}</p> <p className={'mt-2 text-neutral-600'}>{useCase.description}</p>
<div className={'mt-4 rounded-lg bg-neutral-50 p-4'}> <div className={'mt-4 rounded-xl border border-neutral-100 bg-neutral-50 p-4'}>
<p className={'font-mono text-sm text-neutral-700'}>{useCase.example}</p> <p
style={{fontFamily: 'var(--font-mono)'}}
className={'text-sm text-neutral-600'}
>
{useCase.example}
</p>
</div> </div>
</div> </div>
</div> </div>
</motion.div> </motion.div>
))} ))}
</div> </div>
</div>
</section> </section>
{/* CTA Section */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-20'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2
} initial={{opacity: 0, y: 16}}
/>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-3xl text-center'} style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}> Set up your first workflow in minutes.
Set up your first workflow in minutes </motion.h2>
</h2> <motion.div
<p className={'mt-6 text-lg text-neutral-600'}> initial={{opacity: 0, y: 16}}
1,000 emails free every month. Then $0.001 per email. No contact limits, no credit card required. whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}}
className={'flex max-w-md flex-col gap-6'}
>
<p className={'text-base text-neutral-300 sm:text-lg'}>
Free plan available. $0.001 per email on paid. No credit card required.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> <div className={'flex flex-wrap gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
> >
<span className={'flex items-center gap-2'}>
Get started for free Get started for free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className="h-4 w-4" />
</span>
</motion.a> </motion.a>
<Link <Link
href={'/pricing'} href={'/pricing'}
className={ className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
> >
View pricing View pricing
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main> </main>
<Footer /> <Footer />
+86 -72
View File
@@ -10,7 +10,7 @@ interface Guide {
title: string; title: string;
description: string; description: string;
href: string; href: string;
icon: React.ComponentType<{className?: string}>; icon: React.ComponentType<{className?: string; strokeWidth?: number}>;
badge?: string; badge?: string;
} }
@@ -94,9 +94,6 @@ const guides: Guide[] = [
}, },
]; ];
/**
* Email Guides hub page
*/
export default function GuidesIndex() { export default function GuidesIndex() {
return ( return (
<> <>
@@ -115,154 +112,171 @@ export default function GuidesIndex() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-32 sm:py-48'}> {/* Hero */}
<section className={'relative overflow-hidden'}>
<div <div
aria-hidden
className={ className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]' 'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'
} }
/> />
<div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
animate={{opacity: 1, y: 0}} animate={{opacity: 1, y: 0}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl text-center'}
> >
<div <div
style={{fontFamily: 'var(--font-mono)'}}
className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}
>
Free Guides
</div>
<h1
style={{fontFamily: 'var(--font-display)'}}
className={ className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2' 'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'
} }
> >
<Book className="h-4 w-4 text-neutral-600" /> Master email,
<span className={'text-sm text-neutral-600'}>Free Email Guides</span>
</div>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl'}>
Master email
<br /> <br />
marketing & deliverability start to finish.
</h1> </h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> Free guides on email authentication, deliverability, best practices, and technical implementation.
Free guides on email authentication, deliverability, best practices, and technical implementation. Learn
from the experts.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> <div className={'mt-10 flex flex-wrap gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800' 'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'
} }
> >
<span className={'flex items-center gap-2'}>
Try Plunk free Try Plunk free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</span>
</motion.a> </motion.a>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Guides Grid */} {/* Guides grid */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'} className={'mb-16'}
> >
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900'}>Browse all guides</h2> <h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
>
Browse all guides
</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Everything you need to master email</p> <p className={'mt-4 text-lg text-neutral-600'}>Everything you need to master email</p>
</motion.div> </motion.div>
<div className={'grid gap-6 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-4 sm:grid-cols-2 lg:grid-cols-3'}>
{guides.map((guide, index) => { {guides.map((guide, index) => {
const Icon = guide.icon; const Icon = guide.icon;
return ( return (
<motion.div <motion.div
key={guide.href} key={guide.href}
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.05, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: index * 0.04, ease: [0.22, 1, 0.36, 1]}}
> >
<Link <Link
href={guide.href} href={guide.href}
className={ className={
'group block h-full rounded-2xl border border-neutral-200 bg-white p-8 transition hover:border-neutral-300 hover:shadow-lg' 'group flex min-h-[16rem] flex-col justify-between rounded-[28px] border border-neutral-200 bg-white p-8 transition hover:border-neutral-900'
} }
> >
<div className={'flex items-start justify-between mb-4'}> <div className={'flex items-start justify-between'}>
<div <div className={'text-neutral-900'}>
className={ <Icon className="h-6 w-6" strokeWidth={1.5} />
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Icon className="h-5 w-5" />
</div> </div>
{guide.badge && ( {guide.badge && (
<span className={'rounded-full bg-neutral-100 px-3 py-1 text-xs font-medium text-neutral-700'}> <span
style={{fontFamily: 'var(--font-mono)'}}
className={'text-[11px] uppercase tracking-[0.18em] text-neutral-400'}
>
{guide.badge} {guide.badge}
</span> </span>
)} )}
</div> </div>
<h3 className={'text-xl font-semibold text-neutral-900 mb-2 group-hover:text-neutral-700'}> <div>
<h3
style={{fontFamily: 'var(--font-display)'}}
className={'mt-8 text-xl font-bold tracking-[-0.02em] text-neutral-900'}
>
{guide.title} {guide.title}
</h3> </h3>
<p className={'text-sm text-neutral-600 leading-relaxed'}>{guide.description}</p> <p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>{guide.description}</p>
</div>
</Link> </Link>
</motion.div> </motion.div>
); );
})} })}
</div> </div>
</div>
</section> </section>
{/* CTA Section */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2
} initial={{opacity: 0, y: 16}}
/>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-3xl text-center'} style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}
> >
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900'}>Ready to get started?</h2> Put it into practice.
<p className={'mt-6 text-lg text-neutral-600'}> </motion.h2>
Put these guides into practice with Plunk's modern email platform. Start free, no credit card required. <motion.div
initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}}
className={'flex max-w-md flex-col gap-6'}
>
<p className={'text-base text-neutral-300 sm:text-lg'}>
Start free. No credit card required.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> <div className={'flex flex-wrap gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}
'rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
> >
Get started free Get started free
<ArrowRight className="h-4 w-4" />
</motion.a> </motion.a>
<Link <Link
href="/pricing" href={'/pricing'}
className={ className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
> >
View pricing View pricing
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main> </main>
<Footer /> <Footer />
File diff suppressed because it is too large Load Diff
+123 -39
View File
@@ -1,13 +1,11 @@
import React from 'react'; import React from 'react';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {Footer, Navbar} from '../components'; import {Footer, Navbar} from '../components';
import {motion} from 'framer-motion';
import Image from 'next/image'; import Image from 'next/image';
import dries from '../../public/assets/dries.png'; import dries from '../../public/assets/dries.png';
import Link from 'next/link'; import Link from 'next/link';
/**
*
*/
export default function Index() { export default function Index() {
return ( return (
<> <>
@@ -31,23 +29,66 @@ export default function Index() {
<Navbar /> <Navbar />
<div className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
<main>
<section className={'py-32'}>
<div className="mx-auto max-w-4xl">
<div className={'mb-20 text-center'}>
<h1 className="text-5xl font-bold tracking-tight text-neutral-900 sm:text-6xl lg:text-7xl">
Made by Humans
</h1>
<p className="mx-auto mt-6 max-w-2xl text-xl text-neutral-600">Plunk is an indie SaaS run by a human</p>
</div>
{/* Main Content */} {/* Hero */}
<div className="space-y-12"> <section className={'relative overflow-hidden'}>
{/* About Section */} <div
<div className="rounded-xl border border-neutral-200 bg-white p-10"> aria-hidden
<h2 className="text-2xl font-bold text-neutral-900">Built with care</h2> className={
<div className="mt-6 space-y-4 text-lg leading-relaxed text-neutral-600"> 'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'
}
/>
<div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
<motion.div
initial={{opacity: 0, y: 16}}
animate={{opacity: 1, y: 0}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
>
<div
style={{fontFamily: 'var(--font-mono)'}}
className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}
>
Made by Humans
</div>
<h1
style={{fontFamily: 'var(--font-display)'}}
className={
'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'
}
>
Software built
<br />
by a person.
</h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>
Plunk is an indie SaaS run by a human. No VC funding, no aggressive growth tactics. Just a platform built
with care.
</p>
</motion.div>
</div>
</section>
{/* Content */}
<section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<div className={'mx-auto max-w-4xl space-y-4'}>
{/* About */}
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'rounded-[24px] border border-neutral-200 bg-white p-10'}
>
<h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-2xl font-bold tracking-[-0.025em] text-neutral-900'}
>
Built with care
</h2>
<div className={'mt-6 space-y-4 text-lg leading-relaxed text-neutral-600'}>
<p> <p>
Plunk is a small, independent SaaS run by a human. I am not a big corporation, nor am I backed by Plunk is a small, independent SaaS run by a human. I am not a big corporation, nor am I backed by
millions of dollars in venture capital. I am just a person who loves building software and helping millions of dollars in venture capital. I am just a person who loves building software and helping
@@ -59,28 +100,69 @@ export default function Index() {
everyone. Every change I make in Plunk starts from this fundamental belief. everyone. Every change I make in Plunk starts from this fundamental belief.
</p> </p>
</div> </div>
</div> </motion.div>
{/* Values Section */} {/* Values */}
<div className="grid gap-6 sm:grid-cols-2"> <div className={'grid gap-4 sm:grid-cols-2'}>
<div className="rounded-xl border border-neutral-200 bg-white p-8"> <motion.div
<h3 className="text-xl font-semibold text-neutral-900">Transparent</h3> initial={{opacity: 0, y: 20}}
<p className="mt-3 text-neutral-600"> whileInView={{opacity: 1, y: 0}}
I am not perfect. I make mistakes. I am learning and growing. Trying to put the bar a little viewport={{once: true}}
higher every day. Your feedback is always welcome and appreciated. transition={{duration: 0.5, delay: 0.05, ease: [0.22, 1, 0.36, 1]}}
</p> className={'rounded-[24px] border border-neutral-200 bg-white p-8'}
>
<div
style={{fontFamily: 'var(--font-mono)'}}
className={'mb-4 text-[11px] uppercase tracking-[0.18em] text-neutral-400'}
>
01
</div> </div>
<div className="rounded-xl border border-neutral-200 bg-white p-8"> <h3
<h3 className="text-xl font-semibold text-neutral-900">Grateful</h3> style={{fontFamily: 'var(--font-display)'}}
<p className="mt-3 text-neutral-600"> className={'text-xl font-bold tracking-[-0.02em] text-neutral-900'}
>
Transparent
</h3>
<p className={'mt-3 text-neutral-600'}>
I am not perfect. I make mistakes. I am learning and growing. Trying to put the bar a little higher
every day. Your feedback is always welcome and appreciated.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'rounded-[24px] border border-neutral-200 bg-white p-8'}
>
<div
style={{fontFamily: 'var(--font-mono)'}}
className={'mb-4 text-[11px] uppercase tracking-[0.18em] text-neutral-400'}
>
02
</div>
<h3
style={{fontFamily: 'var(--font-display)'}}
className={'text-xl font-bold tracking-[-0.02em] text-neutral-900'}
>
Grateful
</h3>
<p className={'mt-3 text-neutral-600'}>
I want to sincerely thank you for supporting a small business. I am grateful for your business and I want to sincerely thank you for supporting a small business. I am grateful for your business and
do not take it for granted. do not take it for granted.
</p> </p>
</div> </motion.div>
</div> </div>
{/* Signature */} {/* Signature */}
<div className="rounded-xl border border-neutral-200 bg-white p-10"> <motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.6, delay: 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'rounded-[24px] border border-neutral-200 bg-white p-10'}
>
<div className={'flex items-center gap-6'}> <div className={'flex items-center gap-6'}>
<Image <Image
src={dries} src={dries}
@@ -112,23 +194,25 @@ export default function Index() {
</g> </g>
</g> </g>
</svg> </svg>
<div className="text-sm text-neutral-500">Founder of Plunk</div> <div className="mt-1 text-sm text-neutral-500">Founder of Plunk</div>
</div>
</div> </div>
</div> </div>
</motion.div>
{/* Attribution */} {/* Attribution */}
<div className="text-center text-sm text-neutral-500"> <p className={'text-center text-sm text-neutral-400'}>
This page is inspired by{' '} This page is inspired by{' '}
<Link href={'https://logsnag.com/run-by-a-human'} target={'_blank'} className="underline"> <Link href={'https://logsnag.com/run-by-a-human'} target={'_blank'} className="underline hover:text-neutral-600 transition">
Shayan from LogSnag Shayan from LogSnag
</Link> </Link>
</div> </p>
</div> </div>
</div> </div>
</section> </section>
</main> </main>
</div>
<Footer /> <Footer />
</> </>
); );
+139 -67
View File
@@ -3,7 +3,19 @@ import React from 'react';
import {Footer, Navbar} from '../components'; import {Footer, Navbar} from '../components';
import {motion} from 'framer-motion'; import {motion} from 'framer-motion';
import {DASHBOARD_URI} from '../lib/constants'; import {DASHBOARD_URI} from '../lib/constants';
import {ArrowRight, BarChart3, Code2, Globe, Mail, PackageOpen, Shield, Users, Zap, X, Check} from 'lucide-react'; import {
ArrowRight,
BarChart3,
Code2,
Globe,
Mail,
PackageOpen,
Shield,
Users,
Zap,
X,
Check,
} from 'lucide-react';
import Link from 'next/link'; import Link from 'next/link';
import {GithubIcon} from 'lucide-react'; import {GithubIcon} from 'lucide-react';
@@ -55,9 +67,6 @@ const includedFeatures = [
}, },
]; ];
/**
*
*/
export default function Pricing() { export default function Pricing() {
return ( return (
<> <>
@@ -69,44 +78,48 @@ export default function Pricing() {
openGraph={{ openGraph={{
title: 'Plunk Pricing | The Open-Source Email Platform', title: 'Plunk Pricing | The Open-Source Email Platform',
description: description:
'Transparent email pricing at $0.001 per email with no contact limits. Free plan includes 1,000 emails/month across transactional, workflow, and campaign emails. No hidden fees, pay only for what you use.', 'Transparent email pricing at $0.001 per email with no contact limits. Free plan includes 1,000 emails/month. No hidden fees.',
}} }}
additionalMetaTags={[ additionalMetaTags={[{property: 'title', content: 'Plunk Pricing | The Open-Source Email Platform'}]}
{
property: 'title',
content: 'Plunk Pricing | The Open-Source Email Platform',
},
]}
/> />
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero */} {/* Hero */}
<section className={'relative py-20 sm:py-32'}> <section className={'relative overflow-hidden'}>
<div <div
aria-hidden
className={ className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]' 'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'
} }
/> />
<div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
animate={{opacity: 1, y: 0}} animate={{opacity: 1, y: 0}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl text-center'} className={'mx-auto max-w-4xl text-center'}
> >
<h1 className="text-5xl font-bold tracking-tight text-neutral-900 sm:text-6xl lg:text-7xl text-balance"> <h1
style={{fontFamily: 'var(--font-display)'}}
className={
'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'
}
>
Simple, transparent pricing Simple, transparent pricing
</h1> </h1>
<p className="mx-auto mt-6 max-w-2xl text-xl text-neutral-600"> <p className={'mx-auto mt-6 max-w-2xl text-xl text-neutral-600'}>
1,000 emails free every month. Then $0.001 per email. Unlimited contacts, no hidden fees. Free plan: 1,000 emails per month. Paid plan: $0.001 per email. Unlimited contacts, no hidden fees.
</p> </p>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Pricing tiers */} {/* Pricing tiers */}
<section className={'pb-20'}> <section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<div className={'mx-auto grid max-w-4xl gap-px bg-neutral-200 sm:grid-cols-2'}> <div className={'mx-auto grid max-w-4xl gap-px bg-neutral-200 sm:grid-cols-2'}>
{/* Free */} {/* Free */}
<motion.div <motion.div
@@ -115,15 +128,32 @@ export default function Pricing() {
transition={{delay: 0.1, duration: 0.6, ease: [0.22, 1, 0.36, 1]}} transition={{delay: 0.1, duration: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'flex flex-col bg-white p-10'} className={'flex flex-col bg-white p-10'}
> >
<p className={'text-sm font-semibold uppercase tracking-widest text-neutral-400'}>Free forever</p> <p
style={{fontFamily: 'var(--font-mono)'}}
className={'text-[11px] font-semibold uppercase tracking-[0.18em] text-neutral-400'}
>
Free forever
</p>
<div className={'mt-4 flex items-baseline gap-2'}> <div className={'mt-4 flex items-baseline gap-2'}>
<span className={'text-6xl font-bold tracking-tight text-neutral-900'}>1,000</span> <span
style={{fontFamily: 'var(--font-display)'}}
className={'text-6xl font-extrabold tracking-[-0.03em] text-neutral-900'}
>
1,000
</span>
<span className={'text-lg text-neutral-500'}>emails / mo</span> <span className={'text-lg text-neutral-500'}>emails / mo</span>
</div> </div>
<p className={'mt-2 text-sm text-neutral-500'}>No credit card required</p> <p className={'mt-2 text-sm text-neutral-500'}>No credit card required</p>
<ul className={'mt-8 flex-1 space-y-3'}> <ul className={'mt-8 flex-1 space-y-3'}>
{['Transactional emails', 'Workflow automation', 'Campaign broadcasts', 'Custom domains', 'Click & open tracking', 'Unlimited contacts'].map(item => ( {[
'Transactional emails',
'Workflow automation',
'Campaign broadcasts',
'Custom domains',
'Click & open tracking',
'Unlimited contacts',
].map(item => (
<li key={item} className={'flex items-center gap-3 text-sm text-neutral-600'}> <li key={item} className={'flex items-center gap-3 text-sm text-neutral-600'}>
<Check className={'h-4 w-4 flex-shrink-0 text-neutral-900'} /> <Check className={'h-4 w-4 flex-shrink-0 text-neutral-900'} />
{item} {item}
@@ -139,7 +169,9 @@ export default function Pricing() {
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
whileHover={{scale: 1.02}} whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.98}}
className={'mt-10 block w-full rounded-lg border border-neutral-300 px-6 py-3 text-center text-sm font-semibold text-neutral-900 transition hover:border-neutral-400'} className={
'mt-10 block w-full rounded-full border border-neutral-300 px-6 py-3 text-center text-sm font-semibold text-neutral-900 transition hover:border-neutral-900'
}
> >
Start for free Start for free
</motion.a> </motion.a>
@@ -150,19 +182,29 @@ export default function Pricing() {
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
animate={{opacity: 1, y: 0}} animate={{opacity: 1, y: 0}}
transition={{delay: 0.2, duration: 0.6, ease: [0.22, 1, 0.36, 1]}} transition={{delay: 0.2, duration: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'flex flex-col bg-white p-10'} className={'flex flex-col bg-neutral-900 p-10 text-white'}
> >
<p className={'text-sm font-semibold uppercase tracking-widest text-neutral-400'}>Pay as you grow</p> <p
style={{fontFamily: 'var(--font-mono)'}}
className={'text-[11px] font-semibold uppercase tracking-[0.18em] text-neutral-400'}
>
Pay as you grow
</p>
<div className={'mt-4 flex items-baseline gap-2'}> <div className={'mt-4 flex items-baseline gap-2'}>
<span className={'text-6xl font-bold tracking-tight text-neutral-900'}>$0.001</span> <span
<span className={'text-lg text-neutral-500'}>/ email</span> style={{fontFamily: 'var(--font-display)'}}
className={'text-6xl font-extrabold tracking-[-0.03em] text-white'}
>
$0.001
</span>
<span className={'text-lg text-neutral-400'}>/ email</span>
</div> </div>
<p className={'mt-2 text-sm'}>&nbsp;</p> <p className={'mt-2 text-sm'}>&nbsp;</p>
<ul className={'mt-8 flex-1 space-y-3'}> <ul className={'mt-8 flex-1 space-y-3'}>
{['Everything in Free', 'No Plunk branding', 'Monthly spend cap', 'Unlimited emails'].map(item => ( {['Everything in Free', 'No Plunk branding', 'Monthly spend cap', 'Unlimited emails'].map(item => (
<li key={item} className={'flex items-center gap-3 text-sm text-neutral-600'}> <li key={item} className={'flex items-center gap-3 text-sm text-neutral-300'}>
<Check className={'h-4 w-4 flex-shrink-0 text-neutral-900'} /> <Check className={'h-4 w-4 flex-shrink-0 text-white'} />
{item} {item}
</li> </li>
))} ))}
@@ -172,17 +214,20 @@ export default function Pricing() {
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
whileHover={{scale: 1.02}} whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.98}}
className={'mt-10 block w-full rounded-lg bg-neutral-900 px-6 py-3 text-center text-sm font-semibold text-white transition hover:bg-neutral-800'} className={
'mt-10 block w-full rounded-full bg-white px-6 py-3 text-center text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'
}
> >
Get started Get started
</motion.a> </motion.a>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Every feature included */} {/* Every feature included */}
<section className={'py-20'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
@@ -190,7 +235,12 @@ export default function Pricing() {
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'} className={'mb-16 text-center'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}> <h2
style={{fontFamily: 'var(--font-display)'}}
className={
'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'
}
>
Every feature on every plan Every feature on every plan
</h2> </h2>
<p className={'mt-4 text-lg text-neutral-600'}>No feature tiers, no add-ons, no surprises</p> <p className={'mt-4 text-lg text-neutral-600'}>No feature tiers, no add-ons, no surprises</p>
@@ -206,7 +256,7 @@ export default function Pricing() {
transition={{duration: 0.5, delay: index * 0.05, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: index * 0.05, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-10 transition hover:bg-neutral-50'} className={'group bg-white p-10 transition hover:bg-neutral-50'}
> >
<div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'}> <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}>
{feature.icon} {feature.icon}
</div> </div>
<h3 className={'mt-6 text-lg font-semibold text-neutral-900'}>{feature.title}</h3> <h3 className={'mt-6 text-lg font-semibold text-neutral-900'}>{feature.title}</h3>
@@ -214,36 +264,47 @@ export default function Pricing() {
</motion.div> </motion.div>
))} ))}
</div> </div>
</div>
</section> </section>
{/* Self-host */} {/* Self-host */}
<section className={'py-20'}> <section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'overflow-hidden rounded-xl border border-neutral-200 bg-white'} className={'overflow-hidden rounded-[24px] border border-neutral-200 bg-white'}
> >
<div className={'flex flex-col items-center gap-6 p-10 sm:flex-row sm:gap-0'}> <div className={'flex flex-col items-center gap-6 p-10 sm:flex-row sm:gap-0'}>
<div className={'flex-1 text-center sm:text-left'}> <div className={'flex-1 text-center sm:text-left'}>
<div className={'mb-3 inline-flex items-center gap-2 rounded-full bg-neutral-100 px-3 py-1 text-sm font-medium text-neutral-700'}> <div
style={{fontFamily: 'var(--font-mono)'}}
className={'mb-3 inline-flex items-center gap-2 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}
>
<PackageOpen className={'h-3.5 w-3.5'} /> <PackageOpen className={'h-3.5 w-3.5'} />
Self-hostable Self-hostable
</div> </div>
<h2 className={'text-2xl font-bold text-neutral-900'}>Run it on your own infrastructure</h2> <h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-2xl font-bold tracking-[-0.025em] text-neutral-900'}
>
Run it on your own infrastructure
</h2>
<p className={'mt-2 text-neutral-600'}> <p className={'mt-2 text-neutral-600'}>
Full data ownership, no per-email costs, and GDPR compliance by default. Deploy with Docker Compose in minutes. Full data ownership, no per-email costs, and GDPR compliance by default. Deploy with Docker Compose
in minutes.
</p> </p>
</div> </div>
<div className={'sm:ml-auto sm:pl-8'}> <div className={'sm:ml-auto sm:pl-8'}>
<motion.button <motion.button
onClick={() => { onClick={() => window.open('https://github.com/useplunk/plunk', '_blank')}
window.open('https://github.com/useplunk/plunk', '_blank');
}}
whileHover={{scale: 1.02}} whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.98}}
className={'flex w-full items-center justify-center gap-x-3 rounded-lg bg-neutral-900 px-6 py-3 text-base font-semibold text-white transition hover:bg-neutral-800 sm:w-auto'} className={
'flex w-full items-center justify-center gap-x-3 rounded-full bg-neutral-900 px-6 py-3 text-base font-semibold text-white transition hover:bg-neutral-800 sm:w-auto'
}
> >
<GithubIcon size={18} /> <GithubIcon size={18} />
View on GitHub View on GitHub
@@ -251,50 +312,61 @@ export default function Pricing() {
</div> </div>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* CTA */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-20'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2
} initial={{opacity: 0, y: 16}}
/>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-3xl text-center'} style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}
> >
<h2 className={'text-4xl font-bold tracking-tight text-neutral-900 sm:text-5xl text-balance'}> Start sending in 5 minutes.
Start sending in 5 minutes </motion.h2>
</h2>
<p className={'mt-6 text-lg text-neutral-600'}> <motion.div
1,000 emails free every month. No credit card required. initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}}
className={'flex max-w-md flex-col gap-6'}
>
<p className={'text-base text-neutral-300 sm:text-lg'}>
Start free. No credit card required.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> <div className={'flex flex-wrap gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'} className={
'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'
}
> >
<span className={'flex items-center gap-2'}>
Create free account Create free account
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className="h-4 w-4" />
</span>
</motion.a> </motion.a>
<Link <Link
href={'https://github.com/useplunk/plunk'} href={'https://github.com/useplunk/plunk'}
target={'_blank'} target={'_blank'}
className={'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'} className={
'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'
}
> >
Self-host for free Self-host for free
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main> </main>
<Footer /> <Footer />
+206 -151
View File
@@ -1,31 +1,50 @@
import {Footer, Navbar} from '../../components'; import {Footer, Navbar, SectionHeader} from '../../components';
import {motion} from 'framer-motion'; import {motion} from 'framer-motion';
import {DASHBOARD_URI} from '../../lib/constants'; import {DASHBOARD_URI} from '../../lib/constants';
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {ArrowRight, Code2, Mail, Search, Sparkles, Wrench} from 'lucide-react'; import {ArrowRight, ArrowUpRight, Code2, Search} from 'lucide-react';
import {Bricolage_Grotesque, Hanken_Grotesk, JetBrains_Mono} from 'next/font/google';
const display = Bricolage_Grotesque({
subsets: ['latin'],
variable: '--font-display',
display: 'swap',
weight: ['400', '500', '600', '700', '800'],
});
const body = Hanken_Grotesk({
subsets: ['latin'],
variable: '--font-body',
display: 'swap',
weight: ['400', '500', '600', '700'],
});
const mono = JetBrains_Mono({
subsets: ['latin'],
variable: '--font-mono',
display: 'swap',
weight: ['400', '500'],
});
const tools = [ const tools = [
{ {
name: 'Markdown to Email', name: 'Markdown to Email',
slug: 'markdown-to-email', slug: 'markdown-to-email',
description: 'Convert rich text to email-safe HTML with our visual editor and instant preview.', description: 'Convert rich text to email-safe HTML with a visual editor and instant preview.',
features: ['Visual Editor', 'Email-Safe HTML', 'Inline CSS', 'Copy to Clipboard'],
icon: Code2, icon: Code2,
number: '01',
}, },
{ {
name: 'Email Verification', name: 'Email Verification',
slug: 'verify-email', slug: 'verify-email',
description: 'Verify email addresses instantly. Check DNS, MX records, typos, and disposable domains.', description: 'Verify email addresses instantly. Check DNS, MX records, typos, and disposable domains.',
features: ['DNS Validation', 'Typo Detection', 'MX Records', 'Disposable Check'],
icon: Search, icon: Search,
number: '02',
}, },
]; ];
/**
* Free Email Tools index page
*/
export default function ToolsIndex() { export default function ToolsIndex() {
return ( return (
<> <>
@@ -44,225 +63,261 @@ export default function ToolsIndex() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <div className={`${display.variable} ${body.variable} ${mono.variable}`}>
{/* Hero Section */} <main className={'text-neutral-800'}>
<section className={'relative py-32 sm:py-48'}> {/* ========== HERO ========== */}
<section className={'relative overflow-hidden'}>
<div <div
aria-hidden
className={ className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]' 'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'
} }
/> />
<div className={'mx-auto max-w-[88rem] px-6 pb-24 pt-20 sm:px-10 sm:pt-28 lg:pb-36'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 8}}
animate={{opacity: 1, y: 0}} animate={{opacity: 1, y: 0}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl text-center'} style={{fontFamily: 'var(--font-mono)'}}
>
<div
className={ className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2' 'mb-16 flex items-center justify-between border-t border-neutral-900/90 pt-4 text-[11px] uppercase tracking-[0.18em] text-neutral-700 sm:mb-24'
} }
> >
<Wrench className="h-4 w-4 text-neutral-600" /> <span className={'font-medium text-neutral-900'}>§ Tools &nbsp; &nbsp;Plunk</span>
<span className={'text-sm text-neutral-600'}>Free Email Tools</span> </motion.div>
</div>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}> <motion.div
Free tools for initial={{opacity: 0, y: 16}}
animate={{opacity: 1, y: 0}}
transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-5xl text-center'}
>
<h1
style={{fontFamily: 'var(--font-display)'}}
className={
'text-[clamp(3rem,9vw,8rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'
}
>
Free email
<br /> <br />
email developers developer tools
</h1> </h1>
<p className={'mx-auto mt-8 max-w-2xl text-lg leading-relaxed text-neutral-600 sm:text-xl'}>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> Convert markdown to email-safe HTML, verify addresses, and more. No sign-up required.
Build better emails with our free tools. Convert markdown to email-safe HTML, verify email addresses, and
more. No sign-up required.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> <div className={'mt-10 flex flex-wrap justify-center gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800' 'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'
} }
> >
<span className={'flex items-center gap-2'}>
Try Plunk free Try Plunk free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</span>
</motion.a> </motion.a>
<Link <Link
href="/guides" href="/guides"
className={ className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400' 'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'
} }
> >
Browse guides Browse guides
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Tools Grid */} {/* ========== TOOLS LIST ========== */}
<section className={'py-32'}> <section className={'mx-auto max-w-[88rem] px-6 py-28 sm:px-10 sm:py-36'}>
<motion.div <SectionHeader
initial={{opacity: 0, y: 20}} number={'01'}
whileInView={{opacity: 1, y: 0}} label={'Tools'}
viewport={{once: true}} title={'Available tools.'}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} subtitle={'Everything you need to work with email. No sign-up, no limits.'}
className={'mb-16 text-center'} />
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Available Tools</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Everything you need to work with emails</p>
</motion.div>
<div className={'grid gap-8 md:grid-cols-2 lg:grid-cols-2 max-w-4xl mx-auto'}> <ul className={'mt-20 divide-y divide-neutral-200 border-y border-neutral-200'}>
{tools.map((tool, index) => { {tools.map((tool, i) => (
const Icon = tool.icon; <motion.li
return ( key={tool.slug}
<Link key={tool.slug} href={`/tools/${tool.slug}`}> initial={{opacity: 0, y: 12}}
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: i * 0.06, ease: [0.22, 1, 0.36, 1]}}
>
<Link
href={`/tools/${tool.slug}`}
className={ className={
'group rounded-2xl border border-neutral-200 bg-white p-8 transition hover:border-neutral-300 hover:shadow-lg cursor-pointer h-full' 'group flex items-center justify-between gap-6 py-6 transition-colors hover:bg-neutral-50 sm:py-8'
} }
> >
<div className={'flex items-start justify-between mb-4'}> <div className={'flex items-center gap-6 sm:gap-10'}>
<span
style={{fontFamily: 'var(--font-mono)'}}
className={'w-12 text-xs tabular-nums tracking-[0.18em] text-neutral-400 sm:w-16'}
>
{tool.number}
</span>
<div>
<span
style={{fontFamily: 'var(--font-display)'}}
className={
'block text-4xl font-bold tracking-[-0.03em] text-neutral-900 transition-transform duration-300 group-hover:-translate-x-1 sm:text-5xl lg:text-6xl'
}
>
{tool.name}
</span>
<p className={'mt-2 text-sm text-neutral-500'}>{tool.description}</p>
</div>
</div>
<div className={'flex items-center gap-4'}>
<span
style={{fontFamily: 'var(--font-mono)'}}
className={
'hidden text-xs uppercase tracking-[0.18em] text-neutral-500 transition group-hover:text-neutral-900 sm:inline'
}
>
Open tool
</span>
<span
className={
'flex h-11 w-11 items-center justify-center rounded-full border border-neutral-300 text-neutral-900 transition group-hover:border-neutral-900 group-hover:bg-neutral-900 group-hover:text-white sm:h-14 sm:w-14'
}
>
<ArrowUpRight className={'h-5 w-5'} strokeWidth={2} />
</span>
</div>
</Link>
</motion.li>
))}
</ul>
</section>
{/* ========== WHY ========== */}
<section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<div className={'mx-auto max-w-[88rem] px-6 py-28 sm:px-10 sm:py-36'}>
<SectionHeader
number={'02'}
label={'Why'}
title={'Built for developers,'}
titleAccent={'free forever.'}
subtitle={'No sign-up, no paywalls. Tools built by email experts for real-world workflows.'}
/>
<div className={'mt-20 grid gap-10 sm:grid-cols-3 sm:gap-16'}>
{[
{
tag: 'Access',
big: '$0',
title: 'Free forever',
body: 'No sign-up, no paywalls, no limits. Use these tools as much as you need, completely free.',
},
{
tag: 'Focus',
big: 'Dev-first',
title: 'Developer-focused',
body: 'Built by developers who work with email every day. Clean outputs, instant results, real-world workflows.',
},
{
tag: 'Output',
big: '100%',
title: 'Production ready',
body: 'Email-safe HTML that works across all email clients. Industry-standard validation. Battle-tested by thousands.',
},
].map((item, i) => (
<motion.div
key={item.tag}
initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.6, delay: i * 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'flex flex-col gap-6'}
>
<span
style={{fontFamily: 'var(--font-mono)'}}
className={'text-[11px] uppercase tracking-[0.2em] text-neutral-500'}
>
/ {item.tag}
</span>
<div <div
className={ style={{fontFamily: 'var(--font-display)'}}
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110' className={'text-5xl font-extrabold tracking-[-0.035em] text-neutral-900 sm:text-6xl'}
}
> >
<Icon className="h-5 w-5" /> {item.big}
</div>
<Sparkles className="h-5 w-5 text-neutral-400" />
</div>
<h3 className={'text-2xl font-bold text-neutral-900 mb-3'}>{tool.name}</h3>
<p className={'mb-6 leading-relaxed text-neutral-600'}>{tool.description}</p>
<div className={'space-y-2'}>
{tool.features.map(feature => (
<div key={feature} className={'flex items-center gap-2 text-sm text-neutral-600'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-900'} />
<span>{feature}</span>
</div> </div>
<div className={'h-px w-full bg-neutral-300'} />
<h3
style={{fontFamily: 'var(--font-display)'}}
className={'text-xl font-semibold text-neutral-900'}
>
{item.title}
</h3>
<p className={'text-base leading-relaxed text-neutral-600'}>{item.body}</p>
</motion.div>
))} ))}
</div> </div>
</motion.div>
</Link>
);
})}
</div> </div>
</section> </section>
{/* Why Use These Tools */} {/* ========== CTA ========== */}
<section className={'border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
initial={{opacity: 0, y: 20}} <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
<motion.h2
initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'} style={{fontFamily: 'var(--font-display)'}}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Why use these tools?</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Built by email experts for email developers</p>
</motion.div>
<div className={'grid gap-8 lg:grid-cols-3'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}}
className={ className={
'rounded-2xl border border-neutral-200 bg-white p-8 transition hover:border-neutral-300 hover:shadow-lg' 'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'
} }
> >
<Mail className="h-8 w-8 text-blue-500 mb-4" /> Need production-grade email?
<h3 className={'text-2xl font-bold text-neutral-900'}>Free Forever</h3> </motion.h2>
<p className={'mt-4 leading-relaxed text-neutral-600'}>
No sign-up, no paywalls, no limits. Use our tools as much as you need, completely free. We believe in
giving back to the email development community.
</p>
</motion.div>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}}
className={ className={'flex max-w-md flex-col gap-6'}
'rounded-2xl border border-neutral-200 bg-white p-8 transition hover:border-neutral-300 hover:shadow-lg'
}
> >
<Code2 className="h-8 w-8 text-green-500 mb-4" /> <p className={'text-base text-neutral-300 sm:text-lg'}>
<h3 className={'text-2xl font-bold text-neutral-900'}>Developer-Focused</h3> Templates, scheduling, automation, analytics, and deliverability. Start free, scale as you grow.
<p className={'mt-4 leading-relaxed text-neutral-600'}>
Built by developers who work with email every day. Clean outputs, instant results, and designed for
real-world email workflows.
</p> </p>
</motion.div> <div className={'flex flex-wrap gap-3'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
className={
'rounded-2xl border border-neutral-200 bg-white p-8 transition hover:border-neutral-300 hover:shadow-lg'
}
>
<Sparkles className="h-8 w-8 text-yellow-500 mb-4" />
<h3 className={'text-2xl font-bold text-neutral-900'}>Production Ready</h3>
<p className={'mt-4 leading-relaxed text-neutral-600'}>
Generate email-safe HTML that works across all email clients. Verify emails with industry-standard
checks. Our tools are battle-tested and used by thousands of developers.
</p>
</motion.div>
</div>
</section>
{/* CTA */}
<section className={'border-t border-neutral-200 py-32'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-3xl text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Need production-grade email tools?</h2>
<p className={'mt-6 text-lg text-neutral-600'}>
These free tools are great for development, but Plunk offers so much more: templates, scheduling,
automation, analytics, and deliverability optimization. Start free, scale as you grow.
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={
'rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800' 'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'
} }
> >
Start with Plunk Start with Plunk
<ArrowRight className="h-4 w-4" />
</motion.a> </motion.a>
<Link <Link
href="/pricing" href="/pricing"
className={ className={
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400' 'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'
} }
> >
View pricing View pricing
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main> </main>
</div>
<Footer /> <Footer />
</> </>
@@ -1,21 +1,40 @@
import {Footer, Navbar} from '../../components'; import {Footer, Navbar, SectionHeader} from '../../components';
import {motion} from 'framer-motion'; import {motion} from 'framer-motion';
import {DASHBOARD_URI} from '../../lib/constants'; import {DASHBOARD_URI} from '../../lib/constants';
import React, {useMemo, useState} from 'react'; import React, {useMemo, useState} from 'react';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {ArrowRight, Check, Code2, Copy, Sparkles} from 'lucide-react'; import {ArrowRight, Check, Code2, Copy} from 'lucide-react';
import {MarkdownEmailEditor} from '../../components/tools/MarkdownEmailEditor'; import {MarkdownEmailEditor} from '../../components/tools/MarkdownEmailEditor';
import {convertToCompleteEmailHtml} from '../../lib/emailHtmlConverter'; import {convertToCompleteEmailHtml} from '../../lib/emailHtmlConverter';
import {Button} from '@plunk/ui'; import {Button} from '@plunk/ui';
import {Bricolage_Grotesque, Hanken_Grotesk, JetBrains_Mono} from 'next/font/google';
const display = Bricolage_Grotesque({
subsets: ['latin'],
variable: '--font-display',
display: 'swap',
weight: ['400', '500', '600', '700', '800'],
});
const body = Hanken_Grotesk({
subsets: ['latin'],
variable: '--font-body',
display: 'swap',
weight: ['400', '500', '600', '700'],
});
const mono = JetBrains_Mono({
subsets: ['latin'],
variable: '--font-mono',
display: 'swap',
weight: ['400', '500'],
});
export default function MarkdownToEmail() { export default function MarkdownToEmail() {
const [editorContent, setEditorContent] = useState('<p>Hello!</p><p>Try editing this text...</p>'); const [editorContent, setEditorContent] = useState('<p>Hello!</p><p>Try editing this text...</p>');
const [copied, setCopied] = useState(false); const [copied, setCopied] = useState(false);
// Convert editor content to complete, ready-to-send email HTML const emailSafeHtml = useMemo(() => convertToCompleteEmailHtml(editorContent), [editorContent]);
const emailSafeHtml = useMemo(() => {
return convertToCompleteEmailHtml(editorContent);
}, [editorContent]);
const handleCopy = async () => { const handleCopy = async () => {
await navigator.clipboard.writeText(emailSafeHtml); await navigator.clipboard.writeText(emailSafeHtml);
@@ -40,45 +59,61 @@ export default function MarkdownToEmail() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <div className={`${display.variable} ${body.variable} ${mono.variable}`}>
{/* Hero Section */} <main className={'text-neutral-800'}>
<section className={'relative py-32 sm:py-48'}> {/* ========== HERO ========== */}
<section className={'relative overflow-hidden'}>
<div <div
aria-hidden
className={ className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]' 'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'
} }
/> />
<div className={'mx-auto max-w-[88rem] px-6 pb-24 pt-20 sm:px-10 sm:pt-28 lg:pb-36'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 8}}
animate={{opacity: 1, y: 0}} animate={{opacity: 1, y: 0}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl text-center'} style={{fontFamily: 'var(--font-mono)'}}
>
<div
className={ className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2' 'mb-16 flex items-center justify-between border-t border-neutral-900/90 pt-4 text-[11px] uppercase tracking-[0.18em] text-neutral-700 sm:mb-24'
} }
> >
<Sparkles className="h-4 w-4 text-neutral-600" /> <span className={'font-medium text-neutral-900'}>§ T-01 &nbsp; &nbsp;Tool</span>
<span className={'text-sm text-neutral-600'}>Free Tool</span> <a
</div> href="/tools"
className={'text-neutral-500 transition hover:text-neutral-900'}
>
All tools
</a>
</motion.div>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}> <motion.div
Markdown to Email initial={{opacity: 0, y: 16}}
animate={{opacity: 1, y: 0}}
transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-5xl text-center'}
>
<h1
style={{fontFamily: 'var(--font-display)'}}
className={
'text-[clamp(2.5rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'
}
>
Markdown to
<br /> <br />
HTML Converter Email HTML
</h1> </h1>
<p className={'mx-auto mt-8 max-w-2xl text-lg leading-relaxed text-neutral-600 sm:text-xl'}>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> Format your content with the visual editor and get production-ready HTML with inlined styles that works across all email clients.
Create beautiful, email-safe HTML instantly. Format your text with our visual editor and get
production-ready HTML with inlined styles that works across all email clients.
</p> </p>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Editor Section */} {/* ========== EDITOR ========== */}
<section className={'py-16'}> <section className={'mx-auto max-w-[88rem] px-6 py-16 sm:px-10 sm:py-20'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
@@ -88,11 +123,15 @@ export default function MarkdownToEmail() {
> >
{/* Left: Editor */} {/* Left: Editor */}
<div> <div>
<div className="mb-4 flex items-center justify-between"> <div className={'mb-4 flex items-center justify-between'}>
<h2 className="text-xl font-semibold text-neutral-900">Visual Editor</h2> <div className={'flex items-center gap-3'}>
<div className="flex items-center gap-2 text-sm text-neutral-600"> <Code2 className={'h-4 w-4 text-neutral-500'} strokeWidth={1.5} />
<Code2 className="h-4 w-4" /> <span
<span>Format your content</span> style={{fontFamily: 'var(--font-mono)'}}
className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}
>
Visual Editor
</span>
</div> </div>
</div> </div>
<MarkdownEmailEditor value={editorContent} onChange={setEditorContent} /> <MarkdownEmailEditor value={editorContent} onChange={setEditorContent} />
@@ -100,63 +139,150 @@ export default function MarkdownToEmail() {
{/* Right: Email-Safe HTML Output */} {/* Right: Email-Safe HTML Output */}
<div> <div>
<div className="mb-4 flex items-center justify-between"> <div className={'mb-4 flex items-center justify-between'}>
<h2 className="text-xl font-semibold text-neutral-900">Email-Safe HTML</h2> <span
<Button onClick={handleCopy} size="sm" variant="outline" className="gap-2"> style={{fontFamily: 'var(--font-mono)'}}
className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}
>
Email-Safe HTML
</span>
<Button onClick={handleCopy} size="sm" variant="outline" className={'gap-2'}>
{copied ? ( {copied ? (
<> <>
<Check className="h-4 w-4" /> <Check className={'h-4 w-4'} />
Copied! Copied!
</> </>
) : ( ) : (
<> <>
<Copy className="h-4 w-4" /> <Copy className={'h-4 w-4'} />
Copy Copy
</> </>
)} )}
</Button> </Button>
</div> </div>
<div className="border border-neutral-200 rounded-lg overflow-hidden bg-white"> <div className={'overflow-hidden rounded-[16px] border border-neutral-200 bg-white'}>
<pre className="p-4 text-xs font-mono overflow-x-auto min-h-[500px] max-h-[500px] overflow-y-auto"> <pre className={'max-h-[500px] min-h-[500px] overflow-x-auto overflow-y-auto p-4 text-xs'}>
<code className="text-neutral-700">{emailSafeHtml}</code> <code style={{fontFamily: 'var(--font-mono)'}} className={'text-neutral-700'}>
{emailSafeHtml}
</code>
</pre> </pre>
</div> </div>
</div> </div>
</motion.div> </motion.div>
</section> </section>
{/* CTA Section */} {/* ========== ABOUT ========== */}
<section className={'border-t border-neutral-200 py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<div className={'mx-auto max-w-[88rem] px-6 py-28 sm:px-10 sm:py-36'}>
<SectionHeader
number={'01'}
label={'How it works'}
title={'Write once,'}
titleAccent={'send everywhere.'}
subtitle={
'Email clients ignore most CSS. This tool inlines every style rule so your formatting survives any inbox.'
}
/>
<div className={'mt-20 grid gap-10 sm:grid-cols-3 sm:gap-16'}>
{[
{
tag: 'Step 1',
big: 'Write',
title: 'Format your content',
body: 'Use the visual editor to format text, add headings, lists, and links — just like a word processor.',
},
{
tag: 'Step 2',
big: 'Convert',
title: 'Styles get inlined',
body: 'Every CSS rule is moved inline so email clients like Outlook, Gmail, and Apple Mail render it correctly.',
},
{
tag: 'Step 3',
big: 'Copy',
title: 'Drop it in your send',
body: 'Copy the output HTML and paste it into any email service, SMTP template, or API payload.',
},
].map((item, i) => (
<motion.div <motion.div
initial={{opacity: 0, y: 20}} key={item.tag}
initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.6, delay: i * 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-3xl text-center'} className={'flex flex-col gap-6'}
> >
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Ready to send great emails?</h2> <span
<p className={'mt-6 text-lg text-neutral-600'}> style={{fontFamily: 'var(--font-mono)'}}
This tool is great for creating email HTML, but Plunk handles everything: templates, sending, tracking, className={'text-[11px] uppercase tracking-[0.2em] text-neutral-500'}
and deliverability. Start free, no credit card required. >
/ {item.tag}
</span>
<div
style={{fontFamily: 'var(--font-display)'}}
className={'text-5xl font-extrabold tracking-[-0.035em] text-neutral-900 sm:text-6xl'}
>
{item.big}
</div>
<div className={'h-px w-full bg-neutral-300'} />
<h3
style={{fontFamily: 'var(--font-display)'}}
className={'text-xl font-semibold text-neutral-900'}
>
{item.title}
</h3>
<p className={'text-base leading-relaxed text-neutral-600'}>{item.body}</p>
</motion.div>
))}
</div>
</div>
</section>
{/* ========== CTA ========== */}
<section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
<div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
<motion.h2
initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}}
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}
>
Ready to send great emails?
</motion.h2>
<motion.div
initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}}
className={'flex max-w-md flex-col gap-6'}
>
<p className={'text-base text-neutral-300 sm:text-lg'}>
Plunk handles everything: templates, sending, tracking, and deliverability. Start free, no credit card required.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> <div className={'flex flex-wrap gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800' 'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'
} }
> >
<span className={'flex items-center gap-2'}>
Start with Plunk Start with Plunk
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className={'h-4 w-4'} />
</span>
</motion.a> </motion.a>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main> </main>
</div>
<Footer /> <Footer />
</> </>
+138 -82
View File
@@ -1,4 +1,4 @@
import {Footer, Navbar} from '../../components'; import {Footer, Navbar, SectionHeader} from '../../components';
import {motion} from 'framer-motion'; import {motion} from 'framer-motion';
import {DASHBOARD_URI} from '../../lib/constants'; import {DASHBOARD_URI} from '../../lib/constants';
import React, {useState} from 'react'; import React, {useState} from 'react';
@@ -9,6 +9,28 @@ import {verifyEmail} from '../../lib/emailVerification';
import {EmailVerificationResult} from '../../components/tools/EmailVerificationResult'; import {EmailVerificationResult} from '../../components/tools/EmailVerificationResult';
import {Button, Input} from '@plunk/ui'; import {Button, Input} from '@plunk/ui';
import {EMAIL_VERIFICATION_FEATURES} from '../../lib/toolsContent'; import {EMAIL_VERIFICATION_FEATURES} from '../../lib/toolsContent';
import {Bricolage_Grotesque, Hanken_Grotesk, JetBrains_Mono} from 'next/font/google';
const display = Bricolage_Grotesque({
subsets: ['latin'],
variable: '--font-display',
display: 'swap',
weight: ['400', '500', '600', '700', '800'],
});
const body = Hanken_Grotesk({
subsets: ['latin'],
variable: '--font-body',
display: 'swap',
weight: ['400', '500', '600', '700'],
});
const mono = JetBrains_Mono({
subsets: ['latin'],
variable: '--font-mono',
display: 'swap',
weight: ['400', '500'],
});
export default function VerifyEmailPage() { export default function VerifyEmailPage() {
const [email, setEmail] = useState(''); const [email, setEmail] = useState('');
@@ -48,45 +70,58 @@ export default function VerifyEmailPage() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <div className={`${display.variable} ${body.variable} ${mono.variable}`}>
{/* Hero Section */} <main className={'text-neutral-800'}>
<section className={'relative py-32 sm:py-48'}> {/* ========== HERO ========== */}
<section className={'relative overflow-hidden'}>
<div <div
aria-hidden
className={ className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]' 'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'
} }
/> />
<div className={'mx-auto max-w-[88rem] px-6 pb-24 pt-20 sm:px-10 sm:pt-28 lg:pb-36'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 8}}
animate={{opacity: 1, y: 0}} animate={{opacity: 1, y: 0}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl text-center'} style={{fontFamily: 'var(--font-mono)'}}
>
<div
className={ className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2' 'mb-16 flex items-center justify-between border-t border-neutral-900/90 pt-4 text-[11px] uppercase tracking-[0.18em] text-neutral-700 sm:mb-24'
} }
> >
<Search className="h-4 w-4 text-neutral-600" /> <span className={'font-medium text-neutral-900'}>§ T-02 &nbsp; &nbsp;Tool</span>
<span className={'text-sm text-neutral-600'}>Free Tool</span> <a href="/tools" className={'text-neutral-500 transition hover:text-neutral-900'}>
</div> All tools
</a>
</motion.div>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}> <motion.div
Email Verification initial={{opacity: 0, y: 16}}
animate={{opacity: 1, y: 0}}
transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-5xl text-center'}
>
<h1
style={{fontFamily: 'var(--font-display)'}}
className={
'text-[clamp(2.5rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'
}
>
Email address
<br /> <br />
Tool verification
</h1> </h1>
<p className={'mx-auto mt-8 max-w-2xl text-lg leading-relaxed text-neutral-600 sm:text-xl'}>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> Check for typos, disposable domains, DNS configuration, and MX records. Detailed results in seconds.
Verify email addresses instantly. Check for typos, disposable domains, DNS configuration, and more. Get
detailed verification results in seconds.
</p> </p>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Verification Tool Section */} {/* ========== VERIFICATION TOOL ========== */}
<section className={'pb-16'}> <section className={'mx-auto max-w-[88rem] px-6 py-16 sm:px-10 sm:py-20'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
@@ -94,12 +129,23 @@ export default function VerifyEmailPage() {
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-2xl'} className={'mx-auto max-w-2xl'}
> >
{/* Input Form */} <div className={'overflow-hidden rounded-[20px] border border-neutral-200 bg-white'}>
<div className="rounded-lg border border-neutral-200 bg-white p-8 shadow-lg"> <div className={'border-b border-neutral-200 px-8 py-5'}>
<form onSubmit={handleVerify} className="space-y-4"> <div className={'flex items-center gap-3'}>
<Search className={'h-4 w-4 text-neutral-500'} strokeWidth={1.5} />
<span
style={{fontFamily: 'var(--font-mono)'}}
className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}
>
Verify an address
</span>
</div>
</div>
<form onSubmit={handleVerify} className={'space-y-4 p-8'}>
<div> <div>
<label htmlFor="email" className="block text-sm font-medium text-neutral-900 mb-2"> <label htmlFor="email" className={'mb-2 block text-sm font-medium text-neutral-900'}>
Email Address Email address
</label> </label>
<Input <Input
id="email" id="email"
@@ -109,40 +155,38 @@ export default function VerifyEmailPage() {
placeholder="[email protected]" placeholder="[email protected]"
required required
disabled={loading} disabled={loading}
className="w-full" className={'w-full'}
/> />
</div> </div>
<Button type="submit" disabled={loading || !email} className="w-full gap-2"> <Button type="submit" disabled={loading || !email} className={'w-full gap-2'}>
{loading ? ( {loading ? (
<> <>
<Loader2 className="h-4 w-4 animate-spin" /> <Loader2 className={'h-4 w-4 animate-spin'} />
Verifying... Verifying
</> </>
) : ( ) : (
<> <>
<CheckCircle className="h-4 w-4" /> <CheckCircle className={'h-4 w-4'} />
Verify Email Verify email
</> </>
)} )}
</Button> </Button>
</form> </form>
{/* Error Display */}
{error && ( {error && (
<div className="mt-4 rounded-lg border border-red-200 bg-red-50 p-4"> <div className={'mx-8 mb-8 rounded-lg border border-red-200 bg-red-50 p-4'}>
<p className="text-sm text-red-700">{error}</p> <p className={'text-sm text-red-700'}>{error}</p>
</div> </div>
)} )}
</div> </div>
{/* Results Display */}
{result && ( {result && (
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
animate={{opacity: 1, y: 0}} animate={{opacity: 1, y: 0}}
transition={{duration: 0.5}} transition={{duration: 0.5, ease: [0.22, 1, 0.36, 1]}}
className="mt-8" className={'mt-6'}
> >
<EmailVerificationResult result={result} /> <EmailVerificationResult result={result} />
</motion.div> </motion.div>
@@ -150,82 +194,94 @@ export default function VerifyEmailPage() {
</motion.div> </motion.div>
</section> </section>
{/* Educational Content */} {/* ========== WHY VERIFY ========== */}
<section className={'border-t border-neutral-200 py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-28 sm:px-10 sm:py-36'}>
initial={{opacity: 0, y: 20}} <SectionHeader
whileInView={{opacity: 1, y: 0}} number={'01'}
viewport={{once: true}} label={'Why verify'}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} title={'Protect your'}
className={'mb-16 text-center'} titleAccent={'sender reputation.'}
> subtitle={'Invalid addresses hurt deliverability. Verification keeps your list clean before you send.'}
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Why verify email addresses?</h2> />
<p className={'mt-4 text-lg text-neutral-600'}>
Email verification helps improve deliverability and protect your sender reputation.
</p>
</motion.div>
<div className={'grid gap-6 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'mt-20 grid gap-4 sm:grid-cols-2 lg:grid-cols-3'}>
{EMAIL_VERIFICATION_FEATURES.map((feature, index) => { {EMAIL_VERIFICATION_FEATURES.map((feature, index) => {
const Icon = feature.icon; const Icon = feature.icon;
return ( return (
<motion.div <motion.div
key={feature.title} key={feature.title}
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.05, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: index * 0.05, ease: [0.22, 1, 0.36, 1]}}
className={ className={
'group block h-full rounded-2xl border border-neutral-200 bg-white p-8 transition hover:border-neutral-300 hover:shadow-lg' 'flex min-h-[14rem] flex-col justify-between rounded-[28px] border border-neutral-200 bg-white p-8 transition hover:border-neutral-900'
} }
> >
<div <div className={'text-neutral-900'}>
className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white mb-4'} <Icon className={'h-6 w-6'} strokeWidth={1.5} />
</div>
<div>
<h3
style={{fontFamily: 'var(--font-display)'}}
className={'mt-10 text-xl font-bold tracking-[-0.02em] text-neutral-900'}
> >
<Icon className="h-5 w-5" /> {feature.title}
</h3>
<p className={'mt-2 text-sm leading-relaxed text-neutral-600'}>{feature.description}</p>
</div> </div>
<h3 className={'text-xl font-semibold text-neutral-900 mb-2'}>{feature.title}</h3>
<p className={'text-sm text-neutral-600 leading-relaxed'}>{feature.description}</p>
</motion.div> </motion.div>
); );
})} })}
</div> </div>
</div>
</section> </section>
{/* CTA Section */} {/* ========== CTA ========== */}
<section className={'border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
initial={{opacity: 0, y: 20}} <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
<motion.h2
initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-3xl text-center'} style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}
> >
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}> Ready for production-grade verification?
Ready for production-grade email verification? </motion.h2>
</h2>
<p className={'mt-6 text-lg text-neutral-600'}> <motion.div
This tool is great for testing individual emails, but Plunk offers bulk verification, real-time initial={{opacity: 0, y: 16}}
validation, and seamless integration with your email workflows. Start free, no credit card required. whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}}
className={'flex max-w-md flex-col gap-6'}
>
<p className={'text-base text-neutral-300 sm:text-lg'}>
Bulk verification, real-time validation, and seamless integration with your email workflows. Start free, no credit card required.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> <div className={'flex flex-wrap gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800' 'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'
} }
> >
<span className={'flex items-center gap-2'}>
Start with Plunk Start with Plunk
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className={'h-4 w-4'} />
</span>
</motion.a> </motion.a>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main> </main>
</div>
<Footer /> <Footer />
</> </>
+83 -321
View File
@@ -4,7 +4,7 @@ import {DASHBOARD_URI, WIKI_URI} from '../../lib/constants';
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {ArrowRight, Code2, DollarSign, Globe, PackageOpen, Workflow, Zap} from 'lucide-react'; import {ArrowRight, Check, Code2, DollarSign, Globe, PackageOpen, Workflow, Zap} from 'lucide-react';
import type {ComparisonRow} from '../../components/ComparisonTable'; import type {ComparisonRow} from '../../components/ComparisonTable';
import type {FAQ} from '../../components/FAQSection'; import type {FAQ} from '../../components/FAQSection';
@@ -49,9 +49,6 @@ const faqs: FAQ[] = [
}, },
]; ];
/**
* Plunk vs ActiveCampaign comparison page
*/
export default function ActiveCampaignComparison() { export default function ActiveCampaignComparison() {
return ( return (
<> <>
@@ -70,367 +67,132 @@ export default function ActiveCampaignComparison() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-32 sm:py-48'}>
<div
className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]'
}
/>
<motion.div {/* Hero */}
initial={{opacity: 0, y: 20}} <section className={'relative overflow-hidden'}>
animate={{opacity: 1, y: 0}} <div aria-hidden className={'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'} />
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
className={'mx-auto max-w-4xl text-center'} <motion.div initial={{opacity: 0, y: 16}} animate={{opacity: 1, y: 0}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}>
> <div style={{fontFamily: 'var(--font-mono)'}} className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>
<div Plunk vs ActiveCampaign
className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2'
}
>
<span className={'text-sm text-neutral-600'}>Comparing</span>
<span className={'text-sm font-semibold text-neutral-900'}>Plunk vs ActiveCampaign</span>
</div> </div>
<h1 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'}>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}>
Open-source alternative Open-source alternative
<br /> <br />
for ActiveCampaign for ActiveCampaign
</h1> </h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>ActiveCampaign is powerful but expensive and complex. Plunk delivers essential email automation without CRM bloat, sales features, or enterprise pricing. Built for developers, not marketing departments.</p>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <div className={'mt-10 flex flex-wrap gap-3'}>
ActiveCampaign is powerful but expensive and complex. Plunk delivers essential email automation without <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'}>
CRM bloat, sales features, or enterprise pricing. Built for developers, not marketing departments. Get started free <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={WIKI_URI} target={'_blank'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'}>
href={WIKI_URI}
target={'_blank'}
className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Pricing Model Comparison */} {/* Pricing comparison */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>
Enterprise Features Without Enterprise Prices Enterprise Features Without Enterprise Prices
</h2> </h2>
<p className={'mt-4 text-lg text-neutral-600'}>Email automation that doesn't break the bank</p> <p className={'mt-4 text-lg text-neutral-600'}>Email automation that doesn't break the bank</p>
</motion.div> </motion.div>
<div className={'grid gap-4 lg:grid-cols-2'}>
<div className={'grid gap-8 lg:grid-cols-2'}> <motion.div initial={{opacity: 0, x: -20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-900 bg-neutral-900 p-10 text-white'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-400'}>Plunk</div>
initial={{opacity: 0, x: -20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-white'}>Simple pay-as-you-go</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-300'}>Only pay for emails sent. All features included, no tier gating, no forced upgrades.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-white'}>Pay-as-you-go</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border-2 border-neutral-900 bg-white p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />All automation features included</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />No monthly minimums or contracts</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-900 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Typical savings: 50-80% vs ActiveCampaign</li>
<span className={'text-sm font-semibold text-white'}>Plunk</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Simple pay-as-you-go</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Only pay for emails sent. All features included, no tier gating, no forced upgrades.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Pay-as-you-go</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>All automation features included</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>No monthly minimums or contracts</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Typical savings: 50-80% vs ActiveCampaign</span>
</div>
</div>
</motion.div> </motion.div>
<motion.div initial={{opacity: 0, x: 20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-200 bg-white p-10'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>ActiveCampaign</div>
initial={{opacity: 0, x: 20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-neutral-900'}>Expensive subscription tiers</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Complex pricing with feature gating. Automation requires higher tiers.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-neutral-900'}>From $29/month</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border border-neutral-200 bg-neutral-50 p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Advanced automation: $149+/month</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Feature limits on lower tiers</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-200 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Includes CRM/sales features you may not need</li>
<span className={'text-sm font-semibold text-neutral-900'}>ActiveCampaign</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Expensive subscription tiers</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Complex pricing with feature gating. Automation requires higher tiers.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>From $29/month</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Advanced automation: $149+/month</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Feature limits on lower tiers</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Includes CRM/sales features you may not need</span>
</div>
</div>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Key Advantages */} {/* Key advantages */}
<section className={'py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Automation Without Complexity</h2>
viewport={{once: true}} <p className={'mt-4 text-lg text-neutral-600'}>Powerful email workflows without the enterprise overhead</p>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-20 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Automation Without Complexity</h2>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}>
<motion.div {[
initial={{opacity: 0, y: 20}} {icon: <Workflow className="h-5 w-5" />, title: 'Workflow Automation', body: 'Build automated email sequences with triggers, delays, and conditions. No CRM required. Pure email automation that integrates with your product.'},
whileInView={{opacity: 1, y: 0}} {icon: <Code2 className="h-5 w-5" />, title: 'Developer-First API', body: 'Integrate email into your application with a clean REST API. No complex marketing UI to navigate just code and send.'},
viewport={{once: true}} {icon: <DollarSign className="h-5 w-5" />, title: '50-80% Cost Savings', body: 'ActiveCampaign charges $149+/month for automation features. Plunk charges for emails sent only. The savings add up fast.'},
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}} {icon: <PackageOpen className="h-5 w-5" />, title: 'Open Source', body: 'AGPL-3.0 licensed. Inspect the code, understand the system, contribute features. No proprietary algorithms or black-box systems.'},
className={'group bg-white p-12 transition hover:bg-neutral-50'} {icon: <Globe className="h-5 w-5" />, title: 'Self-Hostable', body: 'Deploy on your own infrastructure with Docker. Full data ownership and compliance control. ActiveCampaign is cloud-only.'},
> {icon: <Zap className="h-5 w-5" />, title: 'Fast Setup', body: 'Start sending in 5 minutes. Simple authentication, clean API, comprehensive docs. No CRM to configure before you can send your first email.'},
<div ].map((item, i) => (
className={ <motion.div key={item.title} initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: i * 0.1, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110' <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}>{item.icon}</div>
} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>{item.title}</h3>
> <p className={'mt-3 leading-relaxed text-neutral-600'}>{item.body}</p>
<DollarSign className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Affordable Pricing</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay-as-you-go with all features included. No expensive tier upgrades required for automation. Typically
50-80% cheaper than ActiveCampaign.
</p>
</motion.div> </motion.div>
))}
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Zap className="h-5 w-5" />
</div> </div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>5-Minute Setup</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Start sending in minutes. No CRM to configure, no sales pipeline to set up. Just authenticate and build
your email workflows.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Code2 className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Developer-First</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Clean API designed for developers, not marketing teams. Integrate email into your product without
learning complex enterprise software.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<PackageOpen className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Open Source</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
AGPL-3.0 licensed. Full transparency into how your emails are processed. Contribute features, understand
the system. ActiveCampaign is proprietary.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Globe className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Self-Hostable</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Deploy on your own infrastructure with Docker. Full data control, compliance-ready, no vendor lock-in.
ActiveCampaign is cloud-only.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Workflow className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Workflow Automation</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Event-based triggers, segmentation, and automated sequences. All the email automation power of
ActiveCampaign without CRM complexity.
</p>
</motion.div>
</div> </div>
</section> </section>
{/* Feature Comparison */} {/* Feature comparison table */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Feature comparison</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Feature Comparison</h2>
</motion.div> </motion.div>
<ComparisonTable competitorName="ActiveCampaign" rows={comparisonData} /> <ComparisonTable competitorName="ActiveCampaign" rows={comparisonData} />
</div>
</section> </section>
{/* FAQ */} {/* FAQ */}
<FAQSection faqs={faqs} schemaId="faq-schema-activecampaign" /> <FAQSection faqs={faqs} schemaId="faq-schema-activecampaign" />
{/* CTA */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2 initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}} style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}>
} Email automation, not enterprise complexity.
/> </motion.h2>
<motion.div <motion.div initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}} className={'flex max-w-md flex-col gap-6'}>
initial={{opacity: 0, y: 20}} <p className={'text-base text-neutral-300 sm:text-lg'}>Save 50-80% on email automation. Open-source, self-hostable, pay-as-you-go. Start free.</p>
whileInView={{opacity: 1, y: 0}} <div className={'flex flex-wrap gap-3'}>
viewport={{once: true}} <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} Get started free <ArrowRight className="h-4 w-4" />
className={'mx-auto max-w-3xl text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>
Get email automation without the bloat
</h2>
<p className={'mt-6 text-lg text-neutral-600'}>
Join developers choosing focused email automation over enterprise complexity. Start free, no credit card
required.
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={'/pricing'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}>
href="/pricing"
className={
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View pricing View pricing
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main>
</main>
<Footer /> <Footer />
</> </>
); );
+82 -319
View File
@@ -4,7 +4,7 @@ import {DASHBOARD_URI, WIKI_URI} from '../../lib/constants';
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {ArrowRight, Code2, DollarSign, Globe, Mail, PackageOpen, Zap} from 'lucide-react'; import {ArrowRight, Check, Code2, DollarSign, Globe, PackageOpen, Zap} from 'lucide-react';
import type {ComparisonRow} from '../../components/ComparisonTable'; import type {ComparisonRow} from '../../components/ComparisonTable';
import type {FAQ} from '../../components/FAQSection'; import type {FAQ} from '../../components/FAQSection';
@@ -49,9 +49,6 @@ const faqs: FAQ[] = [
}, },
]; ];
/**
* Plunk vs Bento comparison page
*/
export default function BentoComparison() { export default function BentoComparison() {
return ( return (
<> <>
@@ -70,365 +67,131 @@ export default function BentoComparison() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-32 sm:py-48'}>
<div
className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]'
}
/>
<motion.div {/* Hero */}
initial={{opacity: 0, y: 20}} <section className={'relative overflow-hidden'}>
animate={{opacity: 1, y: 0}} <div aria-hidden className={'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'} />
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
className={'mx-auto max-w-4xl text-center'} <motion.div initial={{opacity: 0, y: 16}} animate={{opacity: 1, y: 0}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}>
> <div style={{fontFamily: 'var(--font-mono)'}} className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>
<div Plunk vs Bento
className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2'
}
>
<span className={'text-sm text-neutral-600'}>Comparing</span>
<span className={'text-sm font-semibold text-neutral-900'}>Plunk vs Bento</span>
</div> </div>
<h1 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'}>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}>
Open-source alternative Open-source alternative
<br /> <br />
for Bento for Bento
</h1> </h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>Bento is an all-in-one platform. Plunk is focused on email. Get powerful email automation without CRM, live chat, or multi-channel complexity. Developer-first, API-driven, transparent pricing.</p>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <div className={'mt-10 flex flex-wrap gap-3'}>
Bento is an all-in-one platform. Plunk is focused on email. Get powerful email automation without CRM, <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'}>
live chat, or multi-channel complexity. Developer-first, API-driven, transparent pricing. Get started free <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={WIKI_URI} target={'_blank'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'}>
href={WIKI_URI}
target={'_blank'}
className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Pricing Model Comparison */} {/* Pricing comparison */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>
Focused Email vs All-in-One Complexity Focused Email vs All-in-One Complexity
</h2> </h2>
<p className={'mt-4 text-lg text-neutral-600'}>Pay for what you use, not what you don't need</p> <p className={'mt-4 text-lg text-neutral-600'}>Pay for what you use, not what you don't need</p>
</motion.div> </motion.div>
<div className={'grid gap-4 lg:grid-cols-2'}>
<div className={'grid gap-8 lg:grid-cols-2'}> <motion.div initial={{opacity: 0, x: -20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-900 bg-neutral-900 p-10 text-white'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-400'}>Plunk</div>
initial={{opacity: 0, x: -20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-white'}>Pay per email sent</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-300'}>Pay-as-you-go for email only. No CRM or chat features you don't need. Simple, transparent pricing.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-white'}>Pay-as-you-go</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border-2 border-neutral-900 bg-white p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Only pay for emails sent</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />No monthly commitments</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-900 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Focus on email, nothing more</li>
<span className={'text-sm font-semibold text-white'}>Plunk</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Pay per email sent</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay-as-you-go for email only. No CRM or chat features you don't need. Simple, transparent pricing.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Pay-as-you-go</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Only pay for emails sent</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>No monthly commitments</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Focus on email, nothing more</span>
</div>
</div>
</motion.div> </motion.div>
<motion.div initial={{opacity: 0, x: 20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-200 bg-white p-10'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>Bento</div>
initial={{opacity: 0, x: 20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-neutral-900'}>Trial then subscription</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-600'}>30-day unlimited trial, then subscription pricing. Includes CRM, chat, and multi-channel features.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-neutral-900'}>30-day trial</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border border-neutral-200 bg-neutral-50 p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Trial ends, then monthly subscription</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Includes features beyond email</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-200 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />All-in-one platform approach</li>
<span className={'text-sm font-semibold text-neutral-900'}>Bento</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Trial then subscription</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
30-day unlimited trial, then subscription pricing. Includes CRM, chat, and multi-channel features.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>30-day trial</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Trial ends, then monthly subscription</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Includes features beyond email</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>All-in-one platform approach</span>
</div>
</div>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Key Advantages */} {/* Key advantages */}
<section className={'py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Developer-First Email Platform</h2>
viewport={{once: true}} <p className={'mt-4 text-lg text-neutral-600'}>Everything you need for email, nothing you don't</p>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-20 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Developer-First Email Platform</h2>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}>
<motion.div {[
initial={{opacity: 0, y: 20}} {icon: <Code2 className="h-5 w-5" />, title: 'API-First Design', body: 'Built for developers who integrate email into their applications. Clean REST API, comprehensive docs, webhook support.'},
whileInView={{opacity: 1, y: 0}} {icon: <PackageOpen className="h-5 w-5" />, title: 'Open Source', body: 'AGPL-3.0 licensed. Full code transparency, contribute features, understand the system. Bento is proprietary closed-source.'},
viewport={{once: true}} {icon: <DollarSign className="h-5 w-5" />, title: 'Pay-as-you-go', body: 'Only pay for emails sent. No subscriptions, no trials that expire, no forced plan upgrades. Predictable costs based on usage.'},
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}} {icon: <Zap className="h-5 w-5" />, title: 'Simple Setup', body: 'Start sending in 5 minutes. No CRM to configure, no multi-channel setup, no live chat integration. Just email, done right.'},
className={'group bg-white p-12 transition hover:bg-neutral-50'} {icon: <Globe className="h-5 w-5" />, title: 'Self-Hostable', body: 'Deploy on your infrastructure with Docker. Full data ownership, compliance control, no vendor lock-in. Bento is cloud-only.'},
> ].map((item, i) => (
<div <motion.div key={item.title} initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: i * 0.1, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
className={ <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}>{item.icon}</div>
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110' <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>{item.title}</h3>
} <p className={'mt-3 leading-relaxed text-neutral-600'}>{item.body}</p>
>
<Code2 className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>API-First Design</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Built for developers who integrate email into their applications. Clean REST API, comprehensive docs,
webhook support.
</p>
</motion.div> </motion.div>
))}
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<PackageOpen className="h-5 w-5" />
</div> </div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Open Source</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
AGPL-3.0 licensed. Full code transparency, contribute features, understand the system. Bento is
proprietary closed-source.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<DollarSign className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Pay-as-you-go</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Only pay for emails sent. No subscriptions, no trials that expire, no forced plan upgrades. Predictable
costs based on usage.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Zap className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Simple Setup</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Start sending in 5 minutes. No CRM to configure, no multi-channel setup, no live chat integration. Just
email, done right.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Globe className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Self-Hostable</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Deploy on your infrastructure with Docker. Full data control, compliance-ready, no vendor lock-in. Bento
is cloud-only.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Mail className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Email-Focused</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Do one thing exceptionally well: email. No feature bloat, no CRM complexity, no multi-channel confusion.
Just powerful email automation.
</p>
</motion.div>
</div> </div>
</section> </section>
{/* Feature Comparison */} {/* Feature comparison table */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Feature comparison</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Feature Comparison</h2>
</motion.div> </motion.div>
<ComparisonTable competitorName="Bento" rows={comparisonData} /> <ComparisonTable competitorName="Bento" rows={comparisonData} />
</div>
</section> </section>
{/* FAQ */} {/* FAQ */}
<FAQSection faqs={faqs} schemaId="faq-schema-bento" /> <FAQSection faqs={faqs} schemaId="faq-schema-bento" />
{/* CTA */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2 initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}} style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}>
} Focused email. No bloat.
/> </motion.h2>
<motion.div <motion.div initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}} className={'flex max-w-md flex-col gap-6'}>
initial={{opacity: 0, y: 20}} <p className={'text-base text-neutral-300 sm:text-lg'}>API-first email without CRM complexity. Open-source, self-hostable, pay-as-you-go. Start free.</p>
whileInView={{opacity: 1, y: 0}} <div className={'flex flex-wrap gap-3'}>
viewport={{once: true}} <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} Get started free <ArrowRight className="h-4 w-4" />
className={'mx-auto max-w-3xl text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Get focused email automation</h2>
<p className={'mt-6 text-lg text-neutral-600'}>
Join developers choosing focused email solutions over all-in-one complexity. Start free, no credit card
required.
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={'/pricing'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}>
href="/pricing"
className={
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View pricing View pricing
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main>
</main>
<Footer /> <Footer />
</> </>
); );
+97 -308
View File
@@ -4,7 +4,7 @@ import {DASHBOARD_URI, WIKI_URI} from '../../lib/constants';
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {ArrowRight, BarChart3, DollarSign, Globe, PackageOpen, Users, Zap} from 'lucide-react'; import {ArrowRight, BarChart3, Check, DollarSign, Globe, PackageOpen, Users, Zap} from 'lucide-react';
import type {ComparisonRow} from '../../components/ComparisonTable'; import type {ComparisonRow} from '../../components/ComparisonTable';
import type {FAQ} from '../../components/FAQSection'; import type {FAQ} from '../../components/FAQSection';
@@ -69,364 +69,153 @@ export default function BrevoComparison() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-32 sm:py-48'}>
<div
className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]'
}
/>
<motion.div {/* Hero */}
initial={{opacity: 0, y: 20}} <section className={'relative overflow-hidden'}>
animate={{opacity: 1, y: 0}} <div aria-hidden className={'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'} />
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
className={'mx-auto max-w-4xl text-center'} <motion.div initial={{opacity: 0, y: 16}} animate={{opacity: 1, y: 0}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}>
> <div style={{fontFamily: 'var(--font-mono)'}} className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>
<div Plunk vs Brevo
className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2'
}
>
<span className={'text-sm text-neutral-600'}>Comparing</span>
<span className={'text-sm font-semibold text-neutral-900'}>Plunk vs Brevo</span>
</div> </div>
<h1 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'}>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}>
Open-source alternative Open-source alternative
<br /> <br />
for Brevo for Brevo
</h1> </h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>Simpler pricing, cleaner API, open-source code. All the email power, none of the bloat. Built for developers, not marketing teams.</p>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <div className={'mt-10 flex flex-wrap gap-3'}>
Simpler pricing, cleaner API, open-source code. All the email power, none of the bloat. Built for <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'}>
developers, not marketing teams. Get started free <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={WIKI_URI} target={'_blank'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'}>
href={WIKI_URI}
target={'_blank'}
className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Pricing Model Comparison */} {/* Pricing comparison */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>
viewport={{once: true}} Pricing That Scales With You
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} </h2>
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Pricing That Scales With You</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Pay for emails sent, not contacts stored</p> <p className={'mt-4 text-lg text-neutral-600'}>Pay for emails sent, not contacts stored</p>
</motion.div> </motion.div>
<div className={'grid gap-4 lg:grid-cols-2'}>
<div className={'grid gap-8 lg:grid-cols-2'}> <motion.div initial={{opacity: 0, x: -20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-900 bg-neutral-900 p-10 text-white'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-400'}>Plunk</div>
initial={{opacity: 0, x: -20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-white'}>Pay per email</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-300'}>Simple pay-as-you-go pricing. Unlimited contacts, pay only for emails sent.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-white'}>$0.001/email</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border-2 border-neutral-900 bg-white p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Unlimited contacts included</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />All features on all plans</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-900 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />No monthly minimums</li>
<span className={'text-sm font-semibold text-white'}>Plunk</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Pay per email</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Simple pay-as-you-go pricing. Unlimited contacts, pay only for emails sent.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>$0.001/email</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Unlimited contacts included</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>All features on all plans</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>No monthly minimums</span>
</div>
</div>
</motion.div> </motion.div>
<motion.div initial={{opacity: 0, x: 20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-200 bg-white p-10'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>Brevo</div>
initial={{opacity: 0, x: 20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-neutral-900'}>Tiered by contacts</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Monthly subscription tiers based on contact count with feature restrictions on lower plans.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-neutral-900'}>Contact-based</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border border-neutral-200 bg-neutral-50 p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Pricing increases with contacts</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Features gated by tier</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-200 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Monthly subscription required</li>
<span className={'text-sm font-semibold text-neutral-900'}>Brevo</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Tiered by contacts</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Monthly subscription tiers based on contact count with feature restrictions on lower plans.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Contact-based</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Pricing increases with contacts</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Features gated by tier</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Monthly subscription required</span>
</div>
</div>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Key Advantages */} {/* Key advantages */}
<section className={'py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Why Choose Plunk Over Brevo</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-20 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Why Choose Plunk Over Brevo</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Focus on email, not feature overload</p> <p className={'mt-4 text-lg text-neutral-600'}>Focus on email, not feature overload</p>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><DollarSign className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Simpler Pricing</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Pay $0.001 per email with unlimited contacts. No contact-based tiers, no surprise charges as you grow. Predictable costs.</p>
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<DollarSign className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Simpler Pricing</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay $0.001 per email with unlimited contacts. No contact-based tiers, no surprise charges as you grow.
Predictable costs.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Zap className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Developer-First</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Clean API, clear documentation, 5-minute setup. Built for developers who want to ship fast, not navigate complex marketing suites.</p>
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Zap className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Developer-First</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Clean API, clear documentation, 5-minute setup. Built for developers who want to ship fast, not navigate
complex marketing suites.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><PackageOpen className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Open Source</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>AGPL-3.0 licensed. Inspect the code, contribute features, fork if needed. Full transparency, no vendor lock-in. Brevo is proprietary.</p>
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<PackageOpen className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Open Source</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
AGPL-3.0 licensed. Inspect the code, contribute features, fork if needed. Full transparency, no vendor
lock-in. Brevo is proprietary.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Globe className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Self-Hostable</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Run on your infrastructure with Docker. Full data control, compliance-ready, cost-optimized. Brevo is cloud-only.</p>
transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Globe className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Self-Hostable</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Run on your infrastructure with Docker. Full data control, compliance-ready, cost-optimized. Brevo is
cloud-only.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Users className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Unlimited Contacts</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Store unlimited contacts at no extra cost. Brevo charges more as your contact list grows. With Plunk, you only pay for emails sent.</p>
transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Users className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Unlimited Contacts</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Store unlimited contacts at no extra cost. Brevo charges more as your contact list grows. With Plunk,
you only pay for emails sent.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><BarChart3 className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Email-Focused</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Plunk does email and does it well. No SMS, chat, CRM bloat. If you need just email automation, Plunk is simpler and more focused.</p>
transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<BarChart3 className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Email-Focused</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Plunk does email and does it well. No SMS, chat, CRM bloat. If you need just email automation, Plunk is
simpler and more focused.
</p>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Feature Comparison */} {/* Feature comparison table */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Feature comparison</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Feature-by-Feature Comparison</h2>
<p className={'mt-4 text-lg text-neutral-600'}>See exactly what you get with each platform</p>
</motion.div> </motion.div>
<ComparisonTable competitorName="Brevo" rows={comparisonData} /> <ComparisonTable competitorName="Brevo" rows={comparisonData} />
</div>
</section> </section>
{/* FAQ */} {/* FAQ */}
<FAQSection faqs={faqs} schemaId="faq-schema-brevo" /> <FAQSection faqs={faqs} schemaId="faq-schema-brevo" />
{/* CTA */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2 initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}} style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}>
} Make the switch to simplicity
/> </motion.h2>
<motion.div <motion.div initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}} className={'flex max-w-md flex-col gap-6'}>
initial={{opacity: 0, y: 20}} <p className={'text-base text-neutral-300 sm:text-lg'}>Join developers choosing focused tools over bloated marketing suites. Start free, no credit card required.</p>
whileInView={{opacity: 1, y: 0}} <div className={'flex flex-wrap gap-3'}>
viewport={{once: true}} <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} Get started free <ArrowRight className="h-4 w-4" />
className={'mx-auto max-w-3xl text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Make the switch to simplicity</h2>
<p className={'mt-6 text-lg text-neutral-600'}>
Join developers choosing focused tools over bloated marketing suites. Start free, no credit card required.
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={'/pricing'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}>
href="/pricing" View pricing
className={
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View pricing details
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main>
</main>
<Footer /> <Footer />
</> </>
); );
+95 -308
View File
@@ -4,7 +4,7 @@ import {DASHBOARD_URI, WIKI_URI} from '../../lib/constants';
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {ArrowRight, Code2, DollarSign, Globe, PackageOpen, Users, Zap} from 'lucide-react'; import {ArrowRight, Check, Code2, DollarSign, Globe, PackageOpen, Users, Zap} from 'lucide-react';
import type {ComparisonRow} from '../../components/ComparisonTable'; import type {ComparisonRow} from '../../components/ComparisonTable';
import type {FAQ} from '../../components/FAQSection'; import type {FAQ} from '../../components/FAQSection';
@@ -70,365 +70,152 @@ export default function ConvertkitComparison() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-32 sm:py-48'}>
<div
className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]'
}
/>
<motion.div {/* Hero */}
initial={{opacity: 0, y: 20}} <section className={'relative overflow-hidden'}>
animate={{opacity: 1, y: 0}} <div aria-hidden className={'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'} />
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
className={'mx-auto max-w-4xl text-center'} <motion.div initial={{opacity: 0, y: 16}} animate={{opacity: 1, y: 0}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}>
> <div style={{fontFamily: 'var(--font-mono)'}} className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>
<div Plunk vs ConvertKit
className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2'
}
>
<span className={'text-sm text-neutral-600'}>Comparing</span>
<span className={'text-sm font-semibold text-neutral-900'}>Plunk vs ConvertKit</span>
</div> </div>
<h1 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'}>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}>
Open-source alternative Open-source alternative
<br /> <br />
for ConvertKit for ConvertKit
</h1> </h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>ConvertKit is built for creators. Plunk is built for developers who need powerful email automation without the creator-focused bloat. Same automation, better DX, pay-as-you-go.</p>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <div className={'mt-10 flex flex-wrap gap-3'}>
ConvertKit is built for creators. Plunk is built for developers who need powerful email automation without <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'}>
the creator-focused bloat. Same automation, better DX, pay-as-you-go. Get started free <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={WIKI_URI} target={'_blank'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'}>
href={WIKI_URI}
target={'_blank'}
className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Pricing Model Comparison */} {/* Pricing comparison */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>
viewport={{once: true}} Pay for Emails, Not Subscribers
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} </h2>
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Pay for Emails, Not Subscribers</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Pricing that grows with usage, not list size</p> <p className={'mt-4 text-lg text-neutral-600'}>Pricing that grows with usage, not list size</p>
</motion.div> </motion.div>
<div className={'grid gap-4 lg:grid-cols-2'}>
<div className={'grid gap-8 lg:grid-cols-2'}> <motion.div initial={{opacity: 0, x: -20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-900 bg-neutral-900 p-10 text-white'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-400'}>Plunk</div>
initial={{opacity: 0, x: -20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-white'}>Pay per email sent</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-300'}>Pay-as-you-go pricing. Only pay for emails you send, not for subscribers you store.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-white'}>Pay-as-you-go</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border-2 border-neutral-900 bg-white p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Unlimited subscribers at no cost</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Only pay when you actually send</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-900 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Grow your list without price increases</li>
<span className={'text-sm font-semibold text-white'}>Plunk</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Pay per email sent</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay-as-you-go pricing. Only pay for emails you send, not for subscribers you store.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Pay-as-you-go</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Unlimited subscribers at no cost</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Only pay when you actually send</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Grow your list without price increases</span>
</div>
</div>
</motion.div> </motion.div>
<motion.div initial={{opacity: 0, x: 20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-200 bg-white p-10'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>ConvertKit</div>
initial={{opacity: 0, x: 20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-neutral-900'}>Pay per subscriber count</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Monthly subscription based on total subscribers, whether you email them or not.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-neutral-900'}>From $25/month</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border border-neutral-200 bg-neutral-50 p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Price increases with subscriber count</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Pay even if you don't send emails</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-200 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />10K subscribers = $119/month</li>
<span className={'text-sm font-semibold text-neutral-900'}>ConvertKit</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Pay per subscriber count</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Monthly subscription based on total subscribers, whether you email them or not.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>From $25/month</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Price increases with subscriber count</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Pay even if you don't send emails</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>10K subscribers = $119/month</span>
</div>
</div>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Key Advantages */} {/* Key advantages */}
<section className={'py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Built for Developers, Not Creators</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-20 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Built for Developers, Not Creators</h2>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Code2 className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Developer-First API</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Modern REST API designed for developers. No visual builder complexity, just clean endpoints for sending emails and managing workflows.</p>
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Code2 className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Developer-First API</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Modern REST API designed for developers. No visual builder complexity, just clean endpoints for sending
emails and managing workflows.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><DollarSign className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Pay-as-you-go Pricing</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Only pay for emails sent, not subscribers stored. Grow your list without worrying about tier upgrades or subscription increases.</p>
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<DollarSign className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Pay-as-you-go Pricing</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Only pay for emails sent, not subscribers stored. Grow your list without worrying about tier upgrades or
subscription increases.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><PackageOpen className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Open Source</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>AGPL-3.0 licensed. Inspect the code, contribute features, understand exactly how your emails are sent. ConvertKit is proprietary.</p>
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<PackageOpen className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Open Source</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
AGPL-3.0 licensed. Inspect the code, contribute features, understand exactly how your emails are sent.
ConvertKit is proprietary.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Globe className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Self-Hostable</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Run on your own infrastructure with Docker. Full data control, compliance-ready, cost-optimized for scale. ConvertKit is cloud-only.</p>
transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Globe className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Self-Hostable</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Run on your own infrastructure with Docker. Full data control, compliance-ready, cost-optimized for
scale. ConvertKit is cloud-only.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Zap className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>5-Minute Setup</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Start sending emails in minutes. No form builders to configure, no landing pages to design. Just authenticate and send.</p>
transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Zap className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>5-Minute Setup</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Start sending emails in minutes. No form builders to configure, no landing pages to design. Just
authenticate and send.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Users className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Unlimited Contacts</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Store unlimited contacts without penalty. No subscriber tiers, no forced upgrades. Your contact database grows freely.</p>
transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Users className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Unlimited Contacts</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Store unlimited contacts without penalty. No subscriber tiers, no forced upgrades. Your contact database
grows freely.
</p>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Feature Comparison */} {/* Feature comparison table */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Feature comparison</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Feature Comparison</h2>
</motion.div> </motion.div>
<ComparisonTable competitorName="ConvertKit" rows={comparisonData} /> <ComparisonTable competitorName="ConvertKit" rows={comparisonData} />
</div>
</section> </section>
{/* FAQ */} {/* FAQ */}
<FAQSection faqs={faqs} schemaId="faq-schema-convertkit" /> <FAQSection faqs={faqs} schemaId="faq-schema-convertkit" />
{/* CTA */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2 initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}} style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}>
}
/>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-3xl text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>
Ready for a developer-first email platform? Ready for a developer-first email platform?
</h2> </motion.h2>
<p className={'mt-6 text-lg text-neutral-600'}> <motion.div initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}} className={'flex max-w-md flex-col gap-6'}>
Join developers who've switched from ConvertKit to Plunk for better API design and transparent <p className={'text-base text-neutral-300 sm:text-lg'}>Join developers who've switched from ConvertKit to Plunk for better API design and transparent pay-as-you-go pricing.</p>
pay-as-you-go pricing. <div className={'flex flex-wrap gap-3'}>
</p> <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> Get started free <ArrowRight className="h-4 w-4" />
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={'/pricing'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}>
href="/pricing"
className={
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View pricing View pricing
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main>
</main>
<Footer /> <Footer />
</> </>
); );
+101 -311
View File
@@ -4,7 +4,7 @@ import {DASHBOARD_URI, WIKI_URI} from '../../lib/constants';
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {ArrowRight, BarChart3, Code2, DollarSign, Globe, PackageOpen, Zap} from 'lucide-react'; import {ArrowRight, BarChart3, Check, Code2, DollarSign, Globe, PackageOpen, Zap} from 'lucide-react';
import type {ComparisonRow} from '../../components/ComparisonTable'; import type {ComparisonRow} from '../../components/ComparisonTable';
import type {FAQ} from '../../components/FAQSection'; import type {FAQ} from '../../components/FAQSection';
@@ -65,363 +65,153 @@ export default function CustomerioComparison() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-32 sm:py-48'}>
<div
className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]'
}
/>
<motion.div {/* Hero */}
initial={{opacity: 0, y: 20}} <section className={'relative overflow-hidden'}>
animate={{opacity: 1, y: 0}} <div aria-hidden className={'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'} />
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
className={'mx-auto max-w-4xl text-center'} <motion.div initial={{opacity: 0, y: 16}} animate={{opacity: 1, y: 0}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}>
> <div style={{fontFamily: 'var(--font-mono)'}} className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>
<div Plunk vs Customer.io
className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2'
}
>
<span className={'text-sm text-neutral-600'}>Comparing</span>
<span className={'text-sm font-semibold text-neutral-900'}>Plunk vs Customer.io</span>
</div> </div>
<h1 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'}>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}>
Open-source alternative Open-source alternative
<br /> <br />
for Customer.io for Customer.io
</h1> </h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>Customer.io starts at $100/month and takes weeks to set up. Plunk delivers the same event-driven automation in an open-source platform you can be sending from in under 5 minutes.</p>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <div className={'mt-10 flex flex-wrap gap-3'}>
Customer.io starts at $100/month and takes weeks to set up. Plunk delivers the same event-driven automation in an open-source platform you can be sending from in under 5 minutes. <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'}>
</p> Try Plunk free <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Try Plunk free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={WIKI_URI} target={'_blank'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'}>
href={WIKI_URI}
target={'_blank'}
className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Pricing Model Comparison */} {/* Pricing comparison */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>
viewport={{once: true}} Simple Pricing That Scales
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} </h2>
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Simple Pricing That Scales</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Transparent pay-as-you-go vs complex enterprise tiers</p> <p className={'mt-4 text-lg text-neutral-600'}>Transparent pay-as-you-go vs complex enterprise tiers</p>
</motion.div> </motion.div>
<div className={'grid gap-4 lg:grid-cols-2'}>
<div className={'grid gap-8 lg:grid-cols-2'}> <motion.div initial={{opacity: 0, x: -20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-900 bg-neutral-900 p-10 text-white'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-400'}>Plunk</div>
initial={{opacity: 0, x: -20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-white'}>Pay per email sent</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-300'}>Pay-as-you-go pricing. Only pay for emails you actually send.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-white'}>Pay-as-you-go</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border-2 border-neutral-900 bg-white p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Only pay for emails you actually send</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />No contact-based pricing complexity</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-900 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />All features included, no upsells</li>
<span className={'text-sm font-semibold text-white'}>Plunk</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Pay per email sent</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay-as-you-go pricing. Only pay for emails you actually send.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Pay-as-you-go</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Only pay for emails you actually send</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>No contact-based pricing complexity</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>All features included, no upsells</span>
</div>
</div>
</motion.div> </motion.div>
<motion.div initial={{opacity: 0, x: 20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-200 bg-white p-10'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>Customer.io</div>
initial={{opacity: 0, x: 20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-neutral-900'}>Complex usage-based pricing</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Pricing based on profiles, messages, and feature tiers.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-neutral-900'}>Tiered complexity</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border border-neutral-200 bg-neutral-50 p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Pay for profiles and messages sent</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Enterprise pricing can be expensive</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-200 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Advanced features locked behind tiers</li>
<span className={'text-sm font-semibold text-neutral-900'}>Customer.io</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Complex usage-based pricing</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pricing based on profiles, messages, and feature tiers.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Tiered complexity</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Pay for profiles and messages sent</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Enterprise pricing can be expensive</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Advanced features locked behind tiers</span>
</div>
</div>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Feature Comparison */} {/* Key advantages */}
<section className={'py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Key Advantages</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Feature-by-Feature</h2>
</motion.div>
<ComparisonTable competitorName="Customer.io" rows={comparisonData} />
</section>
{/* Key Advantages */}
<section className={'py-32'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-20 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Key Advantages</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Why developers choose Plunk</p> <p className={'mt-4 text-lg text-neutral-600'}>Why developers choose Plunk</p>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Code2 className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Developer-First Experience</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Clean, simple APIs designed for developers. No complex visual builders or marketing jargon. Integrate in minutes, not weeks.</p>
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Code2 className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Developer-First Experience</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Clean, simple APIs designed for developers. No complex visual builders or marketing jargon. Integrate in
minutes, not weeks.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><DollarSign className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Transparent Pricing</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Pay-as-you-go pricing with no hidden costs or complex tiers. No need to pay for contact lists or profile counts - just emails sent.</p>
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<DollarSign className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Transparent Pricing</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay-as-you-go pricing with no hidden costs or complex tiers. No need to pay for contact lists or profile
counts - just emails sent.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><PackageOpen className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Open Source</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>AGPL-3.0 licensed. Inspect the code, contribute features, fork if needed. No vendor lock-in with proprietary platforms.</p>
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<PackageOpen className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Open Source</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
AGPL-3.0 licensed. Inspect the code, contribute features, fork if needed. No vendor lock-in with
proprietary platforms.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Zap className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Quick Setup</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Minutes to integrate and start sending. No lengthy onboarding, no sales calls, no enterprise setup processes. Start free immediately.</p>
transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Zap className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Quick Setup</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Minutes to integrate and start sending. No lengthy onboarding, no sales calls, no enterprise setup
processes. Start free immediately.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Globe className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Self-Hosting Option</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Run on your infrastructure with Docker. Full data control, compliance-ready. Pay only AWS SES fees when self-hosting.</p>
transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Globe className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Self-Hosting Option</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Run on your infrastructure with Docker. Full data control, compliance-ready. Pay only AWS SES fees when
self-hosting.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><BarChart3 className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Simplicity at Scale</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Simple workflows that scale without over-engineering. Get enterprise capabilities without enterprise complexity or dedicated ops teams.</p>
transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<BarChart3 className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Simplicity at Scale</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Simple workflows that scale without over-engineering. Get enterprise capabilities without enterprise
complexity or dedicated ops teams.
</p>
</motion.div> </motion.div>
</div> </div>
</div>
</section>
{/* Feature comparison table */}
<section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
<h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Feature comparison</h2>
</motion.div>
<ComparisonTable competitorName="Customer.io" rows={comparisonData} />
</div>
</section> </section>
{/* FAQ */} {/* FAQ */}
<FAQSection faqs={faqs} schemaId="faq-schema-customerio" /> <FAQSection faqs={faqs} schemaId="faq-schema-customerio" />
{/* CTA */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2 initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}} style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}>
} Try Plunk free
/> </motion.h2>
<motion.div <motion.div initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}} className={'flex max-w-md flex-col gap-6'}>
initial={{opacity: 0, y: 20}} <p className={'text-base text-neutral-300 sm:text-lg'}>1,000 emails/month free. No credit card required. Developer-friendly from day one.</p>
whileInView={{opacity: 1, y: 0}} <div className={'flex flex-wrap gap-3'}>
viewport={{once: true}} <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} Get started free <ArrowRight className="h-4 w-4" />
className={'mx-auto max-w-3xl text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Try Plunk free</h2>
<p className={'mt-6 text-lg text-neutral-600'}>
1,000 emails/month free. No credit card required. Developer-friendly from day one.
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={'/pricing'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}>
href={WIKI_URI} View pricing
target={'_blank'}
className={
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
Read documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main>
</main>
<Footer /> <Footer />
</> </>
); );
+133 -131
View File
@@ -87,9 +87,6 @@ const competitors = [
}, },
]; ];
/**
* Plunk vs Competitors index page
*/
export default function CompetitorsIndex() { export default function CompetitorsIndex() {
return ( return (
<> <>
@@ -108,220 +105,225 @@ export default function CompetitorsIndex() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-32 sm:py-48'}>
<div
className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]'
}
/>
{/* Hero */}
<section className={'relative overflow-hidden'}>
<div
aria-hidden
className={'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'}
/>
<div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 16}}
animate={{opacity: 1, y: 0}} animate={{opacity: 1, y: 0}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-4xl text-center'}
> >
<div <div style={{fontFamily: 'var(--font-mono)'}} className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>
className={ Comparisons
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2'
}
>
<span className={'text-sm text-neutral-600'}>Email Platform Comparisons</span>
</div> </div>
<h1
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}> style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'}
>
Plunk vs the Plunk vs the
<br /> <br />
competition competition.
</h1> </h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}>
Most email platforms charge by the contact, lock you in, and split transactional from marketing. Plunk does all three in one open-source platform at $0.001 per email. Most email platforms charge by the contact, lock you in, and split transactional from marketing. Plunk does all three in one open-source platform at $0.001 per email.
</p> </p>
<div className={'mt-10 flex flex-wrap gap-3'}>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'}
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800'
}
> >
<span className={'flex items-center gap-2'}>
Get started free Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</span>
</motion.a> </motion.a>
<Link <Link
href={WIKI_URI} href={WIKI_URI}
target={'_blank'} target={'_blank'}
className={ className={'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'}
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
> >
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Competitors Grid */} {/* Competitors grid */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'} className={'mb-16'}
> >
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}> <h2
Compare Plunk with Industry Leaders style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
>
All comparisons
</h2> </h2>
<p className={'mt-4 text-lg text-neutral-600'}>See how Plunk stacks up against popular email platforms</p> <p className={'mt-4 text-lg text-neutral-600'}>See how Plunk stacks up against popular email platforms</p>
</motion.div> </motion.div>
<div className={'grid gap-8 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4'}> <div className={'grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4'}>
{competitors.map((competitor, index) => ( {competitors.map((competitor, index) => (
<Link key={competitor.slug} href={`/vs/${competitor.slug}`}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} key={competitor.slug}
initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: index * 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: index * 0.04, ease: [0.22, 1, 0.36, 1]}}
className={
'group rounded-2xl border border-neutral-200 bg-white p-8 transition hover:border-neutral-300 hover:shadow-lg cursor-pointer'
}
> >
<div className={'mb-4 flex items-center justify-between'}> <Link
<h3 className={'text-xl font-bold text-neutral-900'}>{competitor.name}</h3> href={`/vs/${competitor.slug}`}
className={'group flex min-h-[14rem] flex-col justify-between rounded-[28px] border border-neutral-200 bg-white p-8 transition hover:border-neutral-900'}
>
<div className={'flex items-start justify-between'}>
<h3
style={{fontFamily: 'var(--font-display)'}}
className={'text-xl font-bold tracking-[-0.02em] text-neutral-900'}
>
{competitor.name}
</h3>
<ArrowRight className="h-4 w-4 text-neutral-400 transition-transform group-hover:translate-x-0.5 group-hover:text-neutral-900" />
</div> </div>
<p className={'mb-6 leading-relaxed text-neutral-600'}>{competitor.description}</p> <div>
<div className={'mb-6 space-y-2'}> <p className={'text-sm text-neutral-600'}>{competitor.description}</p>
<div className={'mt-4 flex flex-wrap gap-1.5'}>
{competitor.features.map(feature => ( {competitor.features.map(feature => (
<div key={feature} className={'flex items-center gap-2 text-sm text-neutral-600'}> <span
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-900'} /> key={feature}
<span>{feature}</span> style={{fontFamily: 'var(--font-mono)'}}
</div> className={'text-[10px] uppercase tracking-[0.12em] text-neutral-400'}
>
{feature}
</span>
))} ))}
</div> </div>
</motion.div> </div>
</Link> </Link>
</motion.div>
))} ))}
</div> </div>
</div>
</section> </section>
{/* Why Choose Plunk */} {/* Why Plunk */}
<section className={'py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div <motion.div
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'} className={'mb-16'}
> >
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Why Choose Plunk</h2> <h2
style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}
>
Why Plunk wins
</h2>
<p className={'mt-4 text-lg text-neutral-600'}>One platform for all your email needs</p> <p className={'mt-4 text-lg text-neutral-600'}>One platform for all your email needs</p>
</motion.div> </motion.div>
<div className={'grid gap-8 lg:grid-cols-3'}> <div className={'grid gap-px bg-neutral-200 sm:grid-cols-3'}>
{[
{
icon: <Mail className="h-5 w-5" />,
title: 'Transactional + Marketing',
body: 'Send transactional emails with the same reliability as dedicated providers, plus marketing campaigns, automation, and segmentation. All in one platform.',
},
{
icon: <Code className="h-5 w-5" />,
title: 'Open Source & Self-Hostable',
body: 'AGPL-3.0 licensed code you can inspect, modify, and self-host. Full control over your data and infrastructure. No vendor lock-in.',
},
{
icon: <DollarSign className="h-5 w-5" />,
title: 'Simple Pricing',
body: 'Pay-as-you-go with all features included. No separate charges for transactional vs marketing emails. No tiers, no commitments.',
},
].map((item, i) => (
<motion.div <motion.div
key={item.title}
initial={{opacity: 0, y: 20}} initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.5, delay: i * 0.1, ease: [0.22, 1, 0.36, 1]}}
className={ className={'bg-white p-10'}
'rounded-2xl border border-neutral-200 bg-white p-8 transition hover:border-neutral-300 hover:shadow-lg'
}
> >
<Mail className="h-8 w-8 text-neutral-900 mb-4" /> <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}>
<h3 className={'text-2xl font-bold text-neutral-900'}>Transactional + Marketing</h3> {item.icon}
<p className={'mt-4 leading-relaxed text-neutral-600'}> </div>
Send transactional emails with the same reliability as dedicated providers, plus marketing campaigns, automation, and segmentation. All in one platform. <h3
</p> style={{fontFamily: 'var(--font-display)'}}
</motion.div> className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
className={
'rounded-2xl border border-neutral-200 bg-white p-8 transition hover:border-neutral-300 hover:shadow-lg'
}
> >
<Code className="h-8 w-8 text-neutral-900 mb-4" /> {item.title}
<h3 className={'text-2xl font-bold text-neutral-900'}>Open Source & Self-Hostable</h3> </h3>
<p className={'mt-4 leading-relaxed text-neutral-600'}> <p className={'mt-3 leading-relaxed text-neutral-600'}>{item.body}</p>
AGPL-3.0 licensed code you can inspect, modify, and self-host. Full control over your data and
infrastructure. No vendor lock-in.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
className={
'rounded-2xl border border-neutral-200 bg-white p-8 transition hover:border-neutral-300 hover:shadow-lg'
}
>
<DollarSign className="h-8 w-8 text-neutral-900 mb-4" />
<h3 className={'text-2xl font-bold text-neutral-900'}>Simple Pricing</h3>
<p className={'mt-4 leading-relaxed text-neutral-600'}>
Pay-as-you-go pricing with all features included. No separate charges for transactional vs marketing
emails. No tiers, no commitments.
</p>
</motion.div> </motion.div>
))}
</div>
</div> </div>
</section> </section>
{/* CTA */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2
} initial={{opacity: 0, y: 16}}
/>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}} whileInView={{opacity: 1, y: 0}}
viewport={{once: true}} viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-3xl text-center'} style={{fontFamily: 'var(--font-display)'}}
className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}
> >
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Ready to try Plunk?</h2> Ready to try Plunk?
<p className={'mt-6 text-lg text-neutral-600'}> </motion.h2>
Join thousands of developers using Plunk for reliable email delivery. Start free, scale as you grow. <motion.div
initial={{opacity: 0, y: 16}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}}
className={'flex max-w-md flex-col gap-6'}
>
<p className={'text-base text-neutral-300 sm:text-lg'}>
Start free. No credit card required.
</p> </p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> <div className={'flex flex-wrap gap-3'}>
<motion.a <motion.a
whileHover={{scale: 1.02}} whileHover={{scale: 1.015}}
whileTap={{scale: 0.98}} whileTap={{scale: 0.985}}
href={`${DASHBOARD_URI}/auth/signup`} href={`${DASHBOARD_URI}/auth/signup`}
className={ className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
> >
<span className={'flex items-center gap-2'}>
Get started free Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" /> <ArrowRight className="h-4 w-4" />
</span>
</motion.a> </motion.a>
<Link <Link
href="/pricing" href={'/pricing'}
className={ className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
> >
View pricing View pricing
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main> </main>
<Footer /> <Footer />
+83 -322
View File
@@ -4,7 +4,7 @@ import {DASHBOARD_URI, WIKI_URI} from '../../lib/constants';
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {ArrowRight, Code2, DollarSign, Globe, Package, PackageOpen, Zap} from 'lucide-react'; import {ArrowRight, Check, Code2, DollarSign, Globe, Package, PackageOpen, Zap} from 'lucide-react';
import type {ComparisonRow} from '../../components/ComparisonTable'; import type {ComparisonRow} from '../../components/ComparisonTable';
import type {FAQ} from '../../components/FAQSection'; import type {FAQ} from '../../components/FAQSection';
@@ -49,9 +49,6 @@ const faqs: FAQ[] = [
}, },
]; ];
/**
* Plunk vs Klaviyo comparison page
*/
export default function KlaviyoComparison() { export default function KlaviyoComparison() {
return ( return (
<> <>
@@ -70,368 +67,132 @@ export default function KlaviyoComparison() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-32 sm:py-48'}>
<div
className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]'
}
/>
<motion.div {/* Hero */}
initial={{opacity: 0, y: 20}} <section className={'relative overflow-hidden'}>
animate={{opacity: 1, y: 0}} <div aria-hidden className={'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'} />
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
className={'mx-auto max-w-4xl text-center'} <motion.div initial={{opacity: 0, y: 16}} animate={{opacity: 1, y: 0}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}>
> <div style={{fontFamily: 'var(--font-mono)'}} className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>
<div Plunk vs Klaviyo
className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2'
}
>
<span className={'text-sm text-neutral-600'}>Comparing</span>
<span className={'text-sm font-semibold text-neutral-900'}>Plunk vs Klaviyo</span>
</div> </div>
<h1 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'}>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}>
Open-source alternative Open-source alternative
<br /> <br />
for Klaviyo for Klaviyo
</h1> </h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>Klaviyo is powerful for e-commerce but extremely expensive. Plunk delivers the same email automation, including full e-commerce support, at a fraction of the cost. No hidden fees, no contact-based pricing.</p>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <div className={'mt-10 flex flex-wrap gap-3'}>
Klaviyo is powerful for e-commerce but extremely expensive. Plunk delivers the same email automation, including full e-commerce support, at a fraction of the cost. No hidden fees, no contact-based pricing. <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'}>
</p> Get started free <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={WIKI_URI} target={'_blank'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'}>
href={WIKI_URI}
target={'_blank'}
className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Pricing Model Comparison */} {/* Pricing comparison */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>
E-commerce Email Without the Premium Price E-commerce Email Without the Premium Price
</h2> </h2>
<p className={'mt-4 text-lg text-neutral-600'}>Pay for emails sent, not contacts stored</p> <p className={'mt-4 text-lg text-neutral-600'}>Pay for emails sent, not contacts stored</p>
</motion.div> </motion.div>
<div className={'grid gap-4 lg:grid-cols-2'}>
<div className={'grid gap-8 lg:grid-cols-2'}> <motion.div initial={{opacity: 0, x: -20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-900 bg-neutral-900 p-10 text-white'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-400'}>Plunk</div>
initial={{opacity: 0, x: -20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-white'}>Pay per email sent</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-300'}>Pay-as-you-go pricing. Only pay for emails sent, not contacts stored. Predictable costs as you scale.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-white'}>Pay-as-you-go</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border-2 border-neutral-900 bg-white p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Unlimited contacts at no extra cost</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />No surprise charges as you grow</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-900 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Typical savings: 60-90% vs Klaviyo</li>
<span className={'text-sm font-semibold text-white'}>Plunk</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Pay per email sent</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay-as-you-go pricing. Only pay for emails sent, not contacts stored. Predictable costs as you scale.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Pay-as-you-go</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Unlimited contacts at no extra cost</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>No surprise charges as you grow</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Typical savings: 60-90% vs Klaviyo</span>
</div>
</div>
</motion.div> </motion.div>
<motion.div initial={{opacity: 0, x: 20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-200 bg-white p-10'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>Klaviyo</div>
initial={{opacity: 0, x: 20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-neutral-900'}>Contact-based tiers</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Expensive pricing based on contact count. Costs escalate quickly as your list grows.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-neutral-900'}>From $20/month</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border border-neutral-200 bg-neutral-50 p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />10K contacts = $150-300+/month</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Price increases with contact list growth</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-200 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Hidden costs for additional features</li>
<span className={'text-sm font-semibold text-neutral-900'}>Klaviyo</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Contact-based tiers</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Expensive pricing based on contact count. Costs escalate quickly as your list grows.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>From $20/month</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>10K contacts = $150-300+/month</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Price increases with contact list growth</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Hidden costs for additional features</span>
</div>
</div>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Key Advantages */} {/* Key advantages */}
<section className={'py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>E-commerce Email, Developer-Friendly</h2>
viewport={{once: true}} <p className={'mt-4 text-lg text-neutral-600'}>All the automation power, at a fraction of the cost</p>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-20 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>
E-commerce Email, Developer-Friendly
</h2>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}>
<motion.div {[
initial={{opacity: 0, y: 20}} {icon: <DollarSign className="h-5 w-5" />, title: 'Affordable Pricing', body: 'Pay-as-you-go instead of expensive contact-based tiers. Save 60-90% compared to Klaviyo while getting the same email automation power.'},
whileInView={{opacity: 1, y: 0}} {icon: <Package className="h-5 w-5" />, title: 'E-commerce Ready', body: 'Handle order confirmations, shipping notifications, abandoned carts, and product campaigns. All e-commerce email use cases via flexible API.'},
viewport={{once: true}} {icon: <Code2 className="h-5 w-5" />, title: 'Developer-Friendly', body: 'Modern API designed for developers. Integrate with Shopify, WooCommerce, or any e-commerce platform via webhooks and API calls.'},
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}} {icon: <PackageOpen className="h-5 w-5" />, title: 'Open Source', body: 'AGPL-3.0 licensed. Full transparency into how your emails work. No black-box algorithms or proprietary systems. Klaviyo is closed-source.'},
className={'group bg-white p-12 transition hover:bg-neutral-50'} {icon: <Globe className="h-5 w-5" />, title: 'Self-Hostable', body: 'Run on your infrastructure with Docker. Full data ownership, compliance control, cost optimization at scale. Klaviyo is cloud-only.'},
> {icon: <Zap className="h-5 w-5" />, title: 'Simple Integration', body: 'Connect your store via webhooks or API. No complex Shopify app to configure. Build exactly the integration you need with full control.'},
<div ].map((item, i) => (
className={ <motion.div key={item.title} initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: i * 0.1, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110' <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}>{item.icon}</div>
} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>{item.title}</h3>
> <p className={'mt-3 leading-relaxed text-neutral-600'}>{item.body}</p>
<DollarSign className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Affordable Pricing</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay-as-you-go instead of expensive contact-based tiers. Save 60-90% compared to Klaviyo while getting
the same email automation power.
</p>
</motion.div> </motion.div>
))}
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Package className="h-5 w-5" />
</div> </div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>E-commerce Ready</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Handle order confirmations, shipping notifications, abandoned carts, and product campaigns. All
e-commerce email use cases via flexible API.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Code2 className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Developer-Friendly</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Modern API designed for developers. Integrate with Shopify, WooCommerce, or any e-commerce platform via
webhooks and API calls.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<PackageOpen className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Open Source</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
AGPL-3.0 licensed. Full transparency into how your emails work. No black-box algorithms or proprietary
systems. Klaviyo is closed-source.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Globe className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Self-Hostable</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Run on your infrastructure with Docker. Full data ownership, compliance control, cost optimization at
scale. Klaviyo is cloud-only.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Zap className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Simple Integration</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Connect your store via webhooks or API. No complex Shopify app to configure. Build exactly the
integration you need with full control.
</p>
</motion.div>
</div> </div>
</section> </section>
{/* Feature Comparison */} {/* Feature comparison table */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Feature comparison</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Feature Comparison</h2>
</motion.div> </motion.div>
<ComparisonTable competitorName="Klaviyo" rows={comparisonData} /> <ComparisonTable competitorName="Klaviyo" rows={comparisonData} />
</div>
</section> </section>
{/* FAQ */} {/* FAQ */}
<FAQSection faqs={faqs} schemaId="faq-schema-klaviyo" /> <FAQSection faqs={faqs} schemaId="faq-schema-klaviyo" />
{/* CTA */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2 initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}} style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}>
} E-commerce email at a fraction of the cost.
/> </motion.h2>
<motion.div <motion.div initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}} className={'flex max-w-md flex-col gap-6'}>
initial={{opacity: 0, y: 20}} <p className={'text-base text-neutral-300 sm:text-lg'}>Save 60-90% vs Klaviyo. Open-source, self-hostable, pay-as-you-go. No contact-based tiers. Start free.</p>
whileInView={{opacity: 1, y: 0}} <div className={'flex flex-wrap gap-3'}>
viewport={{once: true}} <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} Get started free <ArrowRight className="h-4 w-4" />
className={'mx-auto max-w-3xl text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>
E-commerce email at a fraction of the cost
</h2>
<p className={'mt-6 text-lg text-neutral-600'}>
Join e-commerce developers who've switched from Klaviyo to Plunk for dramatic cost savings and better API
design.
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={'/pricing'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}>
href="/pricing"
className={
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View pricing View pricing
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main>
</main>
<Footer /> <Footer />
</> </>
); );
+95 -308
View File
@@ -4,7 +4,7 @@ import {DASHBOARD_URI, WIKI_URI} from '../../lib/constants';
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {ArrowRight, BarChart3, DollarSign, Globe, PackageOpen, Users, Zap} from 'lucide-react'; import {ArrowRight, BarChart3, Check, DollarSign, Globe, PackageOpen, Users, Zap} from 'lucide-react';
import type {ComparisonRow} from '../../components/ComparisonTable'; import type {ComparisonRow} from '../../components/ComparisonTable';
import type {FAQ} from '../../components/FAQSection'; import type {FAQ} from '../../components/FAQSection';
@@ -69,366 +69,153 @@ export default function LoopsComparison() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-32 sm:py-48'}>
<div
className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]'
}
/>
<motion.div {/* Hero */}
initial={{opacity: 0, y: 20}} <section className={'relative overflow-hidden'}>
animate={{opacity: 1, y: 0}} <div aria-hidden className={'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'} />
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
className={'mx-auto max-w-4xl text-center'} <motion.div initial={{opacity: 0, y: 16}} animate={{opacity: 1, y: 0}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}>
> <div style={{fontFamily: 'var(--font-mono)'}} className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>
<div Plunk vs Loops
className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2'
}
>
<span className={'text-sm text-neutral-600'}>Comparing</span>
<span className={'text-sm font-semibold text-neutral-900'}>Plunk vs Loops</span>
</div> </div>
<h1 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'}>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}>
Open-source alternative Open-source alternative
<br /> <br />
for Loops for Loops
</h1> </h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>Same modern features, but open-source and self-hostable. No contact limits, no proprietary lock-in, no hidden costs. Built for transparency.</p>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <div className={'mt-10 flex flex-wrap gap-3'}>
Same modern features, but open-source and self-hostable. No contact limits, no proprietary lock-in, no <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'}>
hidden costs. Built for transparency. Get started free <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={WIKI_URI} target={'_blank'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'}>
href={WIKI_URI}
target={'_blank'}
className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Pricing Model Comparison */} {/* Pricing comparison */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>
Transparent Pricing vs Vendor Lock-In Transparent Pricing vs Vendor Lock-In
</h2> </h2>
<p className={'mt-4 text-lg text-neutral-600'}>Pay per email, not per contact</p> <p className={'mt-4 text-lg text-neutral-600'}>Pay per email, not per contact</p>
</motion.div> </motion.div>
<div className={'grid gap-4 lg:grid-cols-2'}>
<div className={'grid gap-8 lg:grid-cols-2'}> <motion.div initial={{opacity: 0, x: -20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-900 bg-neutral-900 p-10 text-white'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-400'}>Plunk</div>
initial={{opacity: 0, x: -20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-white'}>Pay per email sent</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-300'}>Pay-as-you-go pricing with unlimited contacts. No monthly commitments or contact-based limits.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-white'}>$0.001/email</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border-2 border-neutral-900 bg-white p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Unlimited contacts at no extra cost</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />All features included on all plans</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-900 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Open-source and self-hostable</li>
<span className={'text-sm font-semibold text-white'}>Plunk</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Pay per email sent</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay-as-you-go pricing with unlimited contacts. No monthly commitments or contact-based limits.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>$0.001/email</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Unlimited contacts at no extra cost</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>All features included on all plans</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Open-source and self-hostable</span>
</div>
</div>
</motion.div> </motion.div>
<motion.div initial={{opacity: 0, x: 20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-200 bg-white p-10'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>Loops</div>
initial={{opacity: 0, x: 20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-neutral-900'}>Subscription tiers by contacts</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Monthly subscription based on contact count with tier-based limits and feature restrictions.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-neutral-900'}>Tiered pricing</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border border-neutral-200 bg-neutral-50 p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Contact-based pricing limits</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Feature limits on lower tiers</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-200 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Proprietary, cloud-only platform</li>
<span className={'text-sm font-semibold text-neutral-900'}>Loops</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Subscription tiers by contacts</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Monthly subscription based on contact count with tier-based limits and feature restrictions.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Tiered pricing</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Contact-based pricing limits</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Feature limits on lower tiers</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Proprietary, cloud-only platform</span>
</div>
</div>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Key Advantages */} {/* Key advantages */}
<section className={'py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Why Choose Plunk Over Loops</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-20 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Why Choose Plunk Over Loops</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Open-source transparency meets modern SaaS features</p> <p className={'mt-4 text-lg text-neutral-600'}>Open-source transparency meets modern SaaS features</p>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><PackageOpen className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Open Source & Transparent</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>AGPL-3.0 licensed. Inspect the code, contribute features, understand exactly how your emails are sent. No black boxes.</p>
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<PackageOpen className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Open Source & Transparent</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
AGPL-3.0 licensed. Inspect the code, contribute features, understand exactly how your emails are sent.
No black boxes.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Globe className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Self-Hostable</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Run on your infrastructure with Docker. Full data control, compliance-ready, cost-optimized for scale. Loops is cloud-only.</p>
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Globe className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Self-Hostable</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Run on your infrastructure with Docker. Full data control, compliance-ready, cost-optimized for scale.
Loops is cloud-only.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Users className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Unlimited Contacts</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>No contact-based limits. Grow your audience without worrying about tier upgrades or surprise charges. Pay for emails, not contacts.</p>
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Users className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Unlimited Contacts</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
No contact-based limits. Grow your audience without worrying about tier upgrades or surprise charges.
Pay for emails, not contacts.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><DollarSign className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Predictable Pricing</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Pay-as-you-go per email. No surprise costs as you grow. No forced tier upgrades. No sales calls. Just simple, transparent pricing.</p>
transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<DollarSign className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Predictable Pricing</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay-as-you-go per email. No surprise costs as you grow. No forced tier upgrades. No sales calls. Just
simple, transparent pricing.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Zap className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Full API Access</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Complete API access on all plans. No feature restrictions, no "contact sales" for API access. Everything documented and ready to use.</p>
transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Zap className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Full API Access</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Complete API access on all plans. No feature restrictions, no "contact sales" for API access. Everything
documented and ready to use.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><BarChart3 className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>All Features Included</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Transactional emails, campaigns, workflows, segmentation. All included. No artificial feature gating based on your plan.</p>
transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<BarChart3 className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>All Features Included</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Transactional emails, campaigns, workflows, segmentation. All included. No artificial feature gating based on your plan.
</p>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Feature Comparison */} {/* Feature comparison table */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Feature comparison</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Feature-by-Feature Comparison</h2>
<p className={'mt-4 text-lg text-neutral-600'}>See exactly what you get with each platform</p>
</motion.div> </motion.div>
<ComparisonTable competitorName="Loops" rows={comparisonData} /> <ComparisonTable competitorName="Loops" rows={comparisonData} />
</div>
</section> </section>
{/* FAQ */} {/* FAQ */}
<FAQSection faqs={faqs} schemaId="faq-schema-loops" /> <FAQSection faqs={faqs} schemaId="faq-schema-loops" />
{/* CTA */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2 initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}} style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}>
} Switch to open source
/> </motion.h2>
<motion.div <motion.div initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}} className={'flex max-w-md flex-col gap-6'}>
initial={{opacity: 0, y: 20}} <p className={'text-base text-neutral-300 sm:text-lg'}>Join developers choosing transparency and control over proprietary platforms. Start free, no credit card required.</p>
whileInView={{opacity: 1, y: 0}} <div className={'flex flex-wrap gap-3'}>
viewport={{once: true}} <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} Get started free <ArrowRight className="h-4 w-4" />
className={'mx-auto max-w-3xl text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Switch to open source</h2>
<p className={'mt-6 text-lg text-neutral-600'}>
Join developers choosing transparency and control over proprietary platforms. Start free, no credit card
required.
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={'/pricing'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}>
href="/pricing" View pricing
className={
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View pricing details
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main>
</main>
<Footer /> <Footer />
</> </>
); );
+97 -303
View File
@@ -4,7 +4,7 @@ import {DASHBOARD_URI, WIKI_URI} from '../../lib/constants';
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {ArrowRight, Code2, DollarSign, Mail, PackageOpen, Zap} from 'lucide-react'; import {ArrowRight, Check, Code2, DollarSign, Mail, PackageOpen, Zap} from 'lucide-react';
import type {ComparisonRow} from '../../components/ComparisonTable'; import type {ComparisonRow} from '../../components/ComparisonTable';
import type {FAQ} from '../../components/FAQSection'; import type {FAQ} from '../../components/FAQSection';
@@ -70,360 +70,154 @@ export default function MailchimpComparison() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-32 sm:py-48'}>
<div
className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]'
}
/>
<motion.div {/* Hero */}
initial={{opacity: 0, y: 20}} <section className={'relative overflow-hidden'}>
animate={{opacity: 1, y: 0}} <div aria-hidden className={'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'} />
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
className={'mx-auto max-w-4xl text-center'} <motion.div initial={{opacity: 0, y: 16}} animate={{opacity: 1, y: 0}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}>
> <div style={{fontFamily: 'var(--font-mono)'}} className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>
<div Plunk vs Mailchimp
className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2'
}
>
<span className={'text-sm text-neutral-600'}>Comparing</span>
<span className={'text-sm font-semibold text-neutral-900'}>Plunk vs Mailchimp</span>
</div> </div>
<h1 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'}>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}>
Open-source alternative Open-source alternative
<br /> <br />
for Mailchimp for Mailchimp
</h1> </h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>Mailchimp is for marketers. Plunk is for developers who need full control, modern API, and transparent pay-as-you-go pricing. Same features, better DX.</p>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <div className={'mt-10 flex flex-wrap gap-3'}>
Mailchimp is for marketers. Plunk is for developers who need full control, modern API, and transparent <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'}>
pay-as-you-go pricing. Same features, better DX. Try Plunk free <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Try Plunk free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={WIKI_URI} target={'_blank'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'}>
href={WIKI_URI}
target={'_blank'}
className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Pricing Model Comparison */} {/* Pricing comparison */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>
viewport={{once: true}} The Pricing Model That Makes Sense
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} </h2>
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>The Pricing Model That Makes Sense</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Pay for what you use, not for what you store</p> <p className={'mt-4 text-lg text-neutral-600'}>Pay for what you use, not for what you store</p>
</motion.div> </motion.div>
<div className={'grid gap-4 lg:grid-cols-2'}>
<div className={'grid gap-8 lg:grid-cols-2'}> {/* Plunk card - DARK */}
<motion.div <motion.div initial={{opacity: 0, x: -20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-900 bg-neutral-900 p-10 text-white'}>
initial={{opacity: 0, x: -20}} <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-400'}>Plunk</div>
whileInView={{opacity: 1, x: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-white'}>Pay per email sent</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-300'}>Pay-as-you-go pricing. Only pay for emails you actually send, not for contacts stored.</p>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-white'}>Pay-as-you-go</div>
className={'rounded-2xl border-2 border-neutral-900 bg-white p-10'} <ul className={'mt-8 space-y-3'}>
> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Only pay for emails you actually send</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-900 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Unlimited contacts in your database</li>
<span className={'text-sm font-semibold text-white'}>Plunk</span> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />No penalties for growing your list</li>
</div> </ul>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Pay per email sent</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay-as-you-go pricing. Only pay for emails you actually send, not for contacts stored.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Pay-as-you-go</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Only pay for emails you actually send</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Unlimited contacts in your database</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>No penalties for growing your list</span>
</div>
</div>
</motion.div> </motion.div>
{/* Competitor card - LIGHT */}
<motion.div <motion.div initial={{opacity: 0, x: 20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-200 bg-white p-10'}>
initial={{opacity: 0, x: 20}} <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>Mailchimp</div>
whileInView={{opacity: 1, x: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-neutral-900'}>Pay per contact stored</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Charged for every contact in your list, whether you email them or not.</p>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-neutral-900'}>Fixed subscription</div>
className={'rounded-2xl border border-neutral-200 bg-neutral-50 p-10'} <ul className={'mt-8 space-y-3'}>
> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Pay for contacts even if you don't email them</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-200 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Growing your list = automatic price increase</li>
<span className={'text-sm font-semibold text-neutral-900'}>Mailchimp</span> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Duplicate contacts count multiple times</li>
</div> </ul>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Pay per contact stored</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Charged for every contact in your list, whether you email them or not.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Fixed subscription</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Pay for contacts even if you don't email them</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Growing your list = automatic price increase</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Duplicate contacts count multiple times</span>
</div>
</div>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Key Advantages */} {/* Key advantages */}
<section className={'py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Why Developers Choose Plunk</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-20 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Why Developers Choose Plunk</h2>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><DollarSign className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Pay-as-you-go Pricing</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Only pay for emails you send, not for contacts you store. No monthly minimums or fixed subscription costs.</p>
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<DollarSign className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Pay-as-you-go Pricing</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Only pay for emails you send, not for contacts you store. No monthly minimums or fixed subscription
costs.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Code2 className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>API-First</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Modern REST API designed for developers. 10x easier to integrate than Mailchimp's marketing-focused API.</p>
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Code2 className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>API-First</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Modern REST API designed for developers. 10x easier to integrate than Mailchimp's marketing-focused API.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Zap className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>5-Minute Setup</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Start sending in minutes. No audiences to configure, no lists to manage. Just send emails.</p>
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Zap className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>5-Minute Setup</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Start sending in minutes. No audiences to configure, no lists to manage. Just send emails.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><PackageOpen className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Open Source</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>AGPL-3.0 licensed. Inspect the code, self-host, no vendor lock-in. Mailchimp is proprietary.</p>
transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<PackageOpen className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Open Source</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
AGPL-3.0 licensed. Inspect the code, self-host, no vendor lock-in. Mailchimp is proprietary.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Mail className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>All-in-One</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Transactional and marketing emails in one platform. No need for separate Mandrill account.</p>
transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Mail className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>All-in-One</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Transactional and marketing emails in one platform. No need for separate Mandrill account.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><ArrowRight className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Event-Driven</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Trigger workflows based on user actions. Advanced automation that Mailchimp can't match.</p>
transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<ArrowRight className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Event-Driven</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Trigger workflows based on user actions. Advanced automation that Mailchimp can't match.
</p>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Feature Comparison */} {/* Feature comparison table */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Feature comparison</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Feature Comparison</h2>
</motion.div> </motion.div>
<ComparisonTable competitorName="Mailchimp" rows={comparisonData} /> <ComparisonTable competitorName="Mailchimp" rows={comparisonData} />
</div>
</section> </section>
{/* FAQ */} {/* FAQ */}
<FAQSection faqs={faqs} schemaId="faq-schema-mailchimp" /> <FAQSection faqs={faqs} schemaId="faq-schema-mailchimp" />
{/* CTA */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2 initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}} style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}>
}
/>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mx-auto max-w-3xl text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>
Ready for a better developer experience? Ready for a better developer experience?
</h2> </motion.h2>
<p className={'mt-6 text-lg text-neutral-600'}> <motion.div initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}} className={'flex max-w-md flex-col gap-6'}>
Join developers who've switched from Mailchimp to Plunk for better DX and transparent pay-as-you-go <p className={'text-base text-neutral-300 sm:text-lg'}>Join developers who've switched from Mailchimp to Plunk for better DX and transparent pay-as-you-go pricing.</p>
pricing. <div className={'flex flex-wrap gap-3'}>
</p> <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}> Get started free <ArrowRight className="h-4 w-4" />
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={'/pricing'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}>
href="/pricing"
className={
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View pricing View pricing
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main>
</main>
<Footer /> <Footer />
</> </>
); );
+83 -323
View File
@@ -4,7 +4,7 @@ import {DASHBOARD_URI, WIKI_URI} from '../../lib/constants';
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {ArrowRight, Code2, DollarSign, Globe, PackageOpen, Users, Zap} from 'lucide-react'; import {ArrowRight, Check, Code2, DollarSign, Globe, PackageOpen, Users, Zap} from 'lucide-react';
import type {ComparisonRow} from '../../components/ComparisonTable'; import type {ComparisonRow} from '../../components/ComparisonTable';
import type {FAQ} from '../../components/FAQSection'; import type {FAQ} from '../../components/FAQSection';
@@ -49,9 +49,6 @@ const faqs: FAQ[] = [
}, },
]; ];
/**
* Plunk vs MailerLite comparison page
*/
export default function MailerliteComparison() { export default function MailerliteComparison() {
return ( return (
<> <>
@@ -70,369 +67,132 @@ export default function MailerliteComparison() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-32 sm:py-48'}>
<div
className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]'
}
/>
<motion.div {/* Hero */}
initial={{opacity: 0, y: 20}} <section className={'relative overflow-hidden'}>
animate={{opacity: 1, y: 0}} <div aria-hidden className={'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'} />
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
className={'mx-auto max-w-4xl text-center'} <motion.div initial={{opacity: 0, y: 16}} animate={{opacity: 1, y: 0}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}>
> <div style={{fontFamily: 'var(--font-mono)'}} className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>
<div Plunk vs MailerLite
className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2'
}
>
<span className={'text-sm text-neutral-600'}>Comparing</span>
<span className={'text-sm font-semibold text-neutral-900'}>Plunk vs MailerLite</span>
</div> </div>
<h1 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'}>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}>
Open-source alternative Open-source alternative
<br /> <br />
for MailerLite for MailerLite
</h1> </h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>MailerLite is developer-friendly. Plunk is developer-FIRST. Open-source, self-hostable, with API-first design and pay-as-you-go pricing instead of subscriber tiers.</p>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <div className={'mt-10 flex flex-wrap gap-3'}>
MailerLite is developer-friendly. Plunk is developer-FIRST. Open-source, self-hostable, with API-first <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'}>
design and pay-as-you-go pricing instead of subscriber tiers. Get started free <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={WIKI_URI} target={'_blank'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'}>
href={WIKI_URI}
target={'_blank'}
className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Pricing Model Comparison */} {/* Pricing comparison */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>
Open Source Meets Developer Experience Open Source Meets Developer Experience
</h2> </h2>
<p className={'mt-4 text-lg text-neutral-600'}>Pay for emails sent, not subscribers stored</p> <p className={'mt-4 text-lg text-neutral-600'}>Pay for emails sent, not subscribers stored</p>
</motion.div> </motion.div>
<div className={'grid gap-4 lg:grid-cols-2'}>
<div className={'grid gap-8 lg:grid-cols-2'}> <motion.div initial={{opacity: 0, x: -20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-900 bg-neutral-900 p-10 text-white'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-400'}>Plunk</div>
initial={{opacity: 0, x: -20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-white'}>Pay per email sent</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-300'}>Pay-as-you-go pricing. Open-source and self-hostable for full control.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-white'}>Pay-as-you-go</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border-2 border-neutral-900 bg-white p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Unlimited contacts, no subscriber fees</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Self-host or use our cloud</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-900 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Full code transparency (AGPL-3.0)</li>
<span className={'text-sm font-semibold text-white'}>Plunk</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Pay per email sent</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay-as-you-go pricing. Open-source and self-hostable for full control.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Pay-as-you-go</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Unlimited contacts, no subscriber fees</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Self-host or use our cloud</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Full code transparency (AGPL-3.0)</span>
</div>
</div>
</motion.div> </motion.div>
<motion.div initial={{opacity: 0, x: 20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-200 bg-white p-10'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>MailerLite</div>
initial={{opacity: 0, x: 20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-neutral-900'}>Pay per subscriber count</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Monthly subscription based on total subscribers. Proprietary cloud-only platform.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-neutral-900'}>From $10/month</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border border-neutral-200 bg-neutral-50 p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Pricing based on subscriber count</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Cloud-only, no self-hosting</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-200 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Proprietary closed-source code</li>
<span className={'text-sm font-semibold text-neutral-900'}>MailerLite</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Pay per subscriber count</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Monthly subscription based on total subscribers. Proprietary cloud-only platform.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>From $10/month</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Pricing based on subscriber count</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Cloud-only, no self-hosting</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Proprietary closed-source code</span>
</div>
</div>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Key Advantages */} {/* Key advantages */}
<section className={'py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>The Truly Developer-First Alternative</h2>
viewport={{once: true}} <p className={'mt-4 text-lg text-neutral-600'}>Full control, transparent code, pay only for what you send</p>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-20 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>
The Truly Developer-First Alternative
</h2>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}>
<motion.div {[
initial={{opacity: 0, y: 20}} {icon: <PackageOpen className="h-5 w-5" />, title: 'Open Source', body: 'AGPL-3.0 licensed. Inspect the code, contribute features, understand exactly how your platform works. MailerLite is proprietary.'},
whileInView={{opacity: 1, y: 0}} {icon: <Code2 className="h-5 w-5" />, title: 'API-First Design', body: 'Built for developers from day one. Modern REST API with comprehensive documentation. Integrate email into your product seamlessly.'},
viewport={{once: true}} {icon: <DollarSign className="h-5 w-5" />, title: 'Pay per Email', body: 'Only pay for emails sent, not subscribers stored. Grow your contact list without worrying about tier upgrades or price increases.'},
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}} {icon: <Globe className="h-5 w-5" />, title: 'Self-Hostable', body: 'Deploy on your infrastructure with Docker. Full data ownership, compliance control, no vendor lock-in. MailerLite is cloud-only.'},
className={'group bg-white p-12 transition hover:bg-neutral-50'} {icon: <Zap className="h-5 w-5" />, title: 'Fast Setup', body: 'Start sending in 5 minutes. Simple authentication, clean API endpoints, comprehensive docs. No visual builder learning curve.'},
> {icon: <Users className="h-5 w-5" />, title: 'Unlimited Contacts', body: 'Store unlimited contacts without additional cost. Your database grows freely, pricing stays predictable based on emails sent.'},
<div ].map((item, i) => (
className={ <motion.div key={item.title} initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: i * 0.1, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110' <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}>{item.icon}</div>
} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>{item.title}</h3>
> <p className={'mt-3 leading-relaxed text-neutral-600'}>{item.body}</p>
<PackageOpen className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Open Source</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
AGPL-3.0 licensed. Inspect the code, contribute features, understand exactly how your platform works.
MailerLite is proprietary.
</p>
</motion.div> </motion.div>
))}
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Code2 className="h-5 w-5" />
</div> </div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>API-First Design</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Built for developers from day one. Modern REST API with comprehensive documentation. Integrate email
into your product seamlessly.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<DollarSign className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Pay per Email</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Only pay for emails sent, not subscribers stored. Grow your contact list without worrying about tier
upgrades or price increases.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Globe className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Self-Hostable</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Deploy on your infrastructure with Docker. Full data ownership, compliance control, no vendor lock-in.
MailerLite is cloud-only.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Zap className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Fast Setup</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Start sending in 5 minutes. Simple authentication, clean API endpoints, comprehensive docs. No visual
builder learning curve.
</p>
</motion.div>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Users className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Unlimited Contacts</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Store unlimited contacts without additional cost. Your database grows freely, pricing stays predictable
based on emails sent.
</p>
</motion.div>
</div> </div>
</section> </section>
{/* Feature Comparison */} {/* Feature comparison table */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Feature comparison</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Feature Comparison</h2>
</motion.div> </motion.div>
<ComparisonTable competitorName="MailerLite" rows={comparisonData} /> <ComparisonTable competitorName="MailerLite" rows={comparisonData} />
</div>
</section> </section>
{/* FAQ */} {/* FAQ */}
<FAQSection faqs={faqs} schemaId="faq-schema-mailerlite" /> <FAQSection faqs={faqs} schemaId="faq-schema-mailerlite" />
{/* CTA */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2 initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}} style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}>
} Experience true developer-first email.
/> </motion.h2>
<motion.div <motion.div initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}} className={'flex max-w-md flex-col gap-6'}>
initial={{opacity: 0, y: 20}} <p className={'text-base text-neutral-300 sm:text-lg'}>Open-source transparency and API-first design. Unlimited contacts. Pay only for emails sent. Start free.</p>
whileInView={{opacity: 1, y: 0}} <div className={'flex flex-wrap gap-3'}>
viewport={{once: true}} <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} Get started free <ArrowRight className="h-4 w-4" />
className={'mx-auto max-w-3xl text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>
Experience true developer-first email
</h2>
<p className={'mt-6 text-lg text-neutral-600'}>
Join developers choosing open-source transparency and API-first design. Start free, no credit card
required.
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={'/pricing'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}>
href="/pricing"
className={
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View pricing View pricing
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main>
</main>
<Footer /> <Footer />
</> </>
); );
+101 -309
View File
@@ -4,7 +4,7 @@ import {DASHBOARD_URI, WIKI_URI} from '../../lib/constants';
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {ArrowRight, BarChart3, Globe, Layers, PackageOpen, Users, Workflow} from 'lucide-react'; import {ArrowRight, BarChart3, Check, Globe, Layers, PackageOpen, Users, Workflow} from 'lucide-react';
import type {ComparisonRow} from '../../components/ComparisonTable'; import type {ComparisonRow} from '../../components/ComparisonTable';
import type {FAQ} from '../../components/FAQSection'; import type {FAQ} from '../../components/FAQSection';
@@ -65,361 +65,153 @@ export default function MailgunComparison() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-32 sm:py-48'}>
<div
className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]'
}
/>
<motion.div {/* Hero */}
initial={{opacity: 0, y: 20}} <section className={'relative overflow-hidden'}>
animate={{opacity: 1, y: 0}} <div aria-hidden className={'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'} />
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
className={'mx-auto max-w-4xl text-center'} <motion.div initial={{opacity: 0, y: 16}} animate={{opacity: 1, y: 0}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}>
> <div style={{fontFamily: 'var(--font-mono)'}} className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>
<div Plunk vs Mailgun
className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2'
}
>
<span className={'text-sm text-neutral-600'}>Comparing</span>
<span className={'text-sm font-semibold text-neutral-900'}>Plunk vs Mailgun</span>
</div> </div>
<h1 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'}>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}>
Open-source alternative Open-source alternative
<br /> <br />
for Mailgun for Mailgun
</h1> </h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>Mailgun only handles transactional email. Plunk adds marketing campaigns, workflow automation, and segmentation on top, all open-source and self-hostable at $0.001 per email.</p>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <div className={'mt-10 flex flex-wrap gap-3'}>
Mailgun only handles transactional email. Plunk adds marketing campaigns, workflow automation, and segmentation on top, all open-source and self-hostable at $0.001 per email. <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'}>
</p> Try Plunk free <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Try Plunk free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={WIKI_URI} target={'_blank'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'}>
href={WIKI_URI}
target={'_blank'}
className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Pricing Model Comparison */} {/* Pricing comparison */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>
viewport={{once: true}} The Pricing Model That Makes Sense
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} </h2>
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>The Pricing Model That Makes Sense</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Pay for what you use, not fixed subscriptions</p> <p className={'mt-4 text-lg text-neutral-600'}>Pay for what you use, not fixed subscriptions</p>
</motion.div> </motion.div>
<div className={'grid gap-4 lg:grid-cols-2'}>
<div className={'grid gap-8 lg:grid-cols-2'}> <motion.div initial={{opacity: 0, x: -20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-900 bg-neutral-900 p-10 text-white'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-400'}>Plunk</div>
initial={{opacity: 0, x: -20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-white'}>Pay per email sent</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-300'}>Pay-as-you-go pricing. Only pay for emails you actually send.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-white'}>Pay-as-you-go</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border-2 border-neutral-900 bg-white p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Only pay for emails you actually send</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Scale up or down without commitment</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-900 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Marketing and automation included</li>
<span className={'text-sm font-semibold text-white'}>Plunk</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Pay per email sent</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay-as-you-go pricing. Only pay for emails you actually send.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Pay-as-you-go</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Only pay for emails you actually send</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Scale up or down without commitment</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Marketing and automation included</span>
</div>
</div>
</motion.div> </motion.div>
<motion.div initial={{opacity: 0, x: 20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-200 bg-white p-10'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>Mailgun</div>
initial={{opacity: 0, x: 20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-neutral-900'}>Tiered monthly plans</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Monthly subscription with tiered email volume limits.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-neutral-900'}>Fixed tiers</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border border-neutral-200 bg-neutral-50 p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Locked into monthly subscription tiers</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Need to upgrade plan as you grow</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-200 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Transactional only, no marketing</li>
<span className={'text-sm font-semibold text-neutral-900'}>Mailgun</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Tiered monthly plans</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Monthly subscription with tiered email volume limits.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Fixed tiers</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Locked into monthly subscription tiers</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Need to upgrade plan as you grow</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Transactional only, no marketing</span>
</div>
</div>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Feature Comparison */} {/* Key advantages */}
<section className={'py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>What Plunk Adds</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Feature-by-Feature</h2>
</motion.div>
<ComparisonTable competitorName="Mailgun" rows={comparisonData} />
</section>
{/* What Plunk Adds */}
<section className={'py-32'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-20 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>What Plunk Adds</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Beyond transactional emails</p> <p className={'mt-4 text-lg text-neutral-600'}>Beyond transactional emails</p>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-3'}> <div className={'grid gap-px bg-neutral-200 sm:grid-cols-3'}>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><BarChart3 className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Marketing Campaigns</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Send one-time broadcasts to all contacts or specific segments. Schedule sends, track performance. Mailgun doesn't offer this.</p>
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<BarChart3 className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Marketing Campaigns</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Send one-time broadcasts to all contacts or specific segments. Schedule sends, track performance.
Mailgun doesn't offer this.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Workflow className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Workflow Automation</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Build multi-step email sequences with triggers, delays, and conditions. Perfect for onboarding, drip campaigns, cart abandonment.</p>
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Workflow className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Workflow Automation</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Build multi-step email sequences with triggers, delays, and conditions. Perfect for onboarding, drip
campaigns, cart abandonment.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Users className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Dynamic Segmentation</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Create audience segments that update automatically based on contact data and behavior. Target campaigns precisely.</p>
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Users className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Dynamic Segmentation</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Create audience segments that update automatically based on contact data and behavior. Target campaigns
precisely.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><PackageOpen className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Open Source</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>AGPL-3.0 licensed. Inspect the code, contribute features, no vendor lock-in. Mailgun is proprietary.</p>
transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<PackageOpen className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Open Source</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
AGPL-3.0 licensed. Inspect the code, contribute features, no vendor lock-in. Mailgun is proprietary.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Globe className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Self-Hostable</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Run on your infrastructure with Docker. Full data control, compliance-ready. Pay only AWS SES fees when self-hosting.</p>
transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Globe className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Self-Hostable</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Run on your infrastructure with Docker. Full data control, compliance-ready. Pay only AWS SES fees when
self-hosting.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Layers className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>All-in-One Platform</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>One platform for transactional, marketing, and automation. No need for multiple tools or integrations.</p>
transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Layers className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>All-in-One Platform</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
One platform for transactional, marketing, and automation. No need for multiple tools or integrations.
</p>
</motion.div> </motion.div>
</div> </div>
</div>
</section>
{/* Feature comparison table */}
<section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
<h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Feature comparison</h2>
</motion.div>
<ComparisonTable competitorName="Mailgun" rows={comparisonData} />
</div>
</section> </section>
{/* FAQ */} {/* FAQ */}
<FAQSection faqs={faqs} schemaId="faq-schema-mailgun" /> <FAQSection faqs={faqs} schemaId="faq-schema-mailgun" />
{/* CTA */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2 initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}} style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}>
} Try Plunk free
/> </motion.h2>
<motion.div <motion.div initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}} className={'flex max-w-md flex-col gap-6'}>
initial={{opacity: 0, y: 20}} <p className={'text-base text-neutral-300 sm:text-lg'}>1,000 emails/month free. No credit card required. Add marketing and automation when you need it.</p>
whileInView={{opacity: 1, y: 0}} <div className={'flex flex-wrap gap-3'}>
viewport={{once: true}} <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} Get started free <ArrowRight className="h-4 w-4" />
className={'mx-auto max-w-3xl text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Try Plunk free</h2>
<p className={'mt-6 text-lg text-neutral-600'}>
1,000 emails/month free. No credit card required. Add marketing and automation when you need it.
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={'/pricing'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}>
href={WIKI_URI} View pricing
target={'_blank'}
className={
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
Read documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main>
</main>
<Footer /> <Footer />
</> </>
); );
+97 -309
View File
@@ -4,7 +4,7 @@ import {DASHBOARD_URI, WIKI_URI} from '../../lib/constants';
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {ArrowRight, BarChart3, DollarSign, Globe, PackageOpen, Users, Zap} from 'lucide-react'; import {ArrowRight, BarChart3, Check, DollarSign, Globe, PackageOpen, Users, Zap} from 'lucide-react';
import type {ComparisonRow} from '../../components/ComparisonTable'; import type {ComparisonRow} from '../../components/ComparisonTable';
import type {FAQ} from '../../components/FAQSection'; import type {FAQ} from '../../components/FAQSection';
@@ -66,365 +66,153 @@ export default function PostmarkComparison() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-32 sm:py-48'}>
<div
className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]'
}
/>
<motion.div {/* Hero */}
initial={{opacity: 0, y: 20}} <section className={'relative overflow-hidden'}>
animate={{opacity: 1, y: 0}} <div aria-hidden className={'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'} />
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
className={'mx-auto max-w-4xl text-center'} <motion.div initial={{opacity: 0, y: 16}} animate={{opacity: 1, y: 0}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}>
> <div style={{fontFamily: 'var(--font-mono)'}} className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>
<div Plunk vs Postmark
className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2'
}
>
<span className={'text-sm text-neutral-600'}>Comparing</span>
<span className={'text-sm font-semibold text-neutral-900'}>Plunk vs Postmark</span>
</div> </div>
<h1 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'}>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}>
Open-source alternative Open-source alternative
<br /> <br />
for Postmark for Postmark
</h1> </h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>Everything Postmark offers for transactional emails, plus marketing campaigns, workflow automation, and segmentation. One platform, no extra cost.</p>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <div className={'mt-10 flex flex-wrap gap-3'}>
Everything Postmark offers for transactional emails, plus marketing campaigns, workflow automation, and <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'}>
segmentation. One platform, no extra cost. Get started free <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={WIKI_URI} target={'_blank'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'}>
href={WIKI_URI}
target={'_blank'}
className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Pricing Model Comparison */} {/* Pricing comparison */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>
viewport={{once: true}} One Platform for All Your Emails
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} </h2>
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>One Platform for All Your Emails</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Transactional reliability meets marketing power</p> <p className={'mt-4 text-lg text-neutral-600'}>Transactional reliability meets marketing power</p>
</motion.div> </motion.div>
<div className={'grid gap-4 lg:grid-cols-2'}>
<div className={'grid gap-8 lg:grid-cols-2'}> <motion.div initial={{opacity: 0, x: -20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-900 bg-neutral-900 p-10 text-white'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-400'}>Plunk</div>
initial={{opacity: 0, x: -20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-white'}>Transactional + Marketing</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-300'}>Reliable transactional emails plus marketing campaigns, workflows, and segmentation in one platform.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-white'}>All-in-one</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border-2 border-neutral-900 bg-white p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Transactional emails included</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Marketing campaigns included</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-900 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Workflow automation included</li>
<span className={'text-sm font-semibold text-white'}>Plunk</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Transactional + Marketing</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Reliable transactional emails plus marketing campaigns, workflows, and segmentation in one platform.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>All-in-one</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Transactional emails included</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Marketing campaigns included</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Workflow automation included</span>
</div>
</div>
</motion.div> </motion.div>
<motion.div initial={{opacity: 0, x: 20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-200 bg-white p-10'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>Postmark</div>
initial={{opacity: 0, x: 20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-neutral-900'}>Transactional only</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Excellent for transactional emails, but no marketing features. Need a second service for campaigns.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-neutral-900'}>Limited scope</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border border-neutral-200 bg-neutral-50 p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Transactional emails only</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />No marketing campaigns</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-200 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />No workflow automation</li>
<span className={'text-sm font-semibold text-neutral-900'}>Postmark</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Transactional only</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Excellent for transactional emails, but no marketing features. Need a second service for campaigns.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Limited scope</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Transactional emails only</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>No marketing campaigns</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>No workflow automation</span>
</div>
</div>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Key Advantages */} {/* Key advantages */}
<section className={'py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Why Choose Plunk Over Postmark</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-20 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Why Choose Plunk Over Postmark</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Do more with one platform instead of two</p> <p className={'mt-4 text-lg text-neutral-600'}>Do more with one platform instead of two</p>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><BarChart3 className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Marketing Campaigns Included</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Send newsletters, announcements, and promotional emails without needing a separate marketing platform. One platform, one bill.</p>
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<BarChart3 className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Marketing Campaigns Included</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Send newsletters, announcements, and promotional emails without needing a separate marketing platform.
One platform, one bill.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Zap className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Workflow Automation</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Build automated email sequences with triggers, delays, and conditions. Onboard users, nurture leads, re-engage customers. All automated.</p>
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Zap className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Workflow Automation</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Build automated email sequences with triggers, delays, and conditions. Onboard users, nurture leads,
re-engage customers. All automated.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Users className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Dynamic Segmentation</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Segment your audience based on behavior, properties, and engagement. Send targeted emails to the right people at the right time.</p>
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Users className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Dynamic Segmentation</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Segment your audience based on behavior, properties, and engagement. Send targeted emails to the right
people at the right time.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><PackageOpen className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Open Source & Transparent</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>AGPL-3.0 licensed. Inspect the code, contribute features, understand exactly how it works. No proprietary black boxes.</p>
transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<PackageOpen className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Open Source & Transparent</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
AGPL-3.0 licensed. Inspect the code, contribute features, understand exactly how it works. No
proprietary black boxes.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Globe className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Self-Hostable</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Run on your infrastructure with Docker. Full data control, compliance-ready, cost-optimized. Postmark is cloud-only.</p>
transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Globe className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Self-Hostable</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Run on your infrastructure with Docker. Full data control, compliance-ready, cost-optimized. Postmark is
cloud-only.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><DollarSign className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Pay-As-You-Go Pricing</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Simple per-email pricing with all features included. No separate charges for transactional vs marketing emails. No tiers, no commitments.</p>
transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<DollarSign className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Pay-As-You-Go Pricing</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Simple per-email pricing with all features included. No separate charges for transactional vs marketing
emails. No tiers, no commitments.
</p>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Feature Comparison */} {/* Feature comparison table */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Feature comparison</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Feature-by-Feature Comparison</h2>
<p className={'mt-4 text-lg text-neutral-600'}>See exactly what you get with each platform</p>
</motion.div> </motion.div>
<ComparisonTable competitorName="Postmark" rows={comparisonData} /> <ComparisonTable competitorName="Postmark" rows={comparisonData} />
</div>
</section> </section>
{/* FAQ */} {/* FAQ */}
<FAQSection faqs={faqs} schemaId="faq-schema-postmark" /> <FAQSection faqs={faqs} schemaId="faq-schema-postmark" />
{/* CTA */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2 initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}} style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}>
} Get more from your email platform
/> </motion.h2>
<motion.div <motion.div initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}} className={'flex max-w-md flex-col gap-6'}>
initial={{opacity: 0, y: 20}} <p className={'text-base text-neutral-300 sm:text-lg'}>Stop juggling multiple tools. Get transactional reliability plus marketing power in one platform. Start free.</p>
whileInView={{opacity: 1, y: 0}} <div className={'flex flex-wrap gap-3'}>
viewport={{once: true}} <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} Get started free <ArrowRight className="h-4 w-4" />
className={'mx-auto max-w-3xl text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Get more from your email platform</h2>
<p className={'mt-6 text-lg text-neutral-600'}>
Stop juggling multiple tools. Get transactional reliability plus marketing power in one platform. Start
free.
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={'/pricing'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}>
href="/pricing" View pricing
className={
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View pricing details
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main>
</main>
<Footer /> <Footer />
</> </>
); );
+101 -309
View File
@@ -4,7 +4,7 @@ import {DASHBOARD_URI, WIKI_URI} from '../../lib/constants';
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {ArrowRight, BarChart3, Globe, Layers, PackageOpen, Users, Workflow} from 'lucide-react'; import {ArrowRight, BarChart3, Check, Globe, Layers, PackageOpen, Users, Workflow} from 'lucide-react';
import type {ComparisonRow} from '../../components/ComparisonTable'; import type {ComparisonRow} from '../../components/ComparisonTable';
import type {FAQ} from '../../components/FAQSection'; import type {FAQ} from '../../components/FAQSection';
@@ -65,361 +65,153 @@ export default function ResendComparison() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-32 sm:py-48'}>
<div
className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]'
}
/>
<motion.div {/* Hero */}
initial={{opacity: 0, y: 20}} <section className={'relative overflow-hidden'}>
animate={{opacity: 1, y: 0}} <div aria-hidden className={'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'} />
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
className={'mx-auto max-w-4xl text-center'} <motion.div initial={{opacity: 0, y: 16}} animate={{opacity: 1, y: 0}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}>
> <div style={{fontFamily: 'var(--font-mono)'}} className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>
<div Plunk vs Resend
className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2'
}
>
<span className={'text-sm text-neutral-600'}>Comparing</span>
<span className={'text-sm font-semibold text-neutral-900'}>Plunk vs Resend</span>
</div> </div>
<h1 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'}>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}>
Open-source alternative Open-source alternative
<br /> <br />
for Resend for Resend
</h1> </h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>Resend is transactional-only. Plunk gives you transactional emails, marketing campaigns, and workflow automation in a single open-source platform. No second tool, no second bill.</p>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <div className={'mt-10 flex flex-wrap gap-3'}>
Resend is transactional-only. Plunk gives you transactional emails, marketing campaigns, and workflow automation in a single open-source platform. No second tool, no second bill. <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'}>
</p> Try Plunk free <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Try Plunk free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={WIKI_URI} target={'_blank'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'}>
href={WIKI_URI}
target={'_blank'}
className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Pricing Model Comparison */} {/* Pricing comparison */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>
viewport={{once: true}} The Pricing Model That Makes Sense
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} </h2>
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>The Pricing Model That Makes Sense</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Pay for what you use, not fixed subscriptions</p> <p className={'mt-4 text-lg text-neutral-600'}>Pay for what you use, not fixed subscriptions</p>
</motion.div> </motion.div>
<div className={'grid gap-4 lg:grid-cols-2'}>
<div className={'grid gap-8 lg:grid-cols-2'}> <motion.div initial={{opacity: 0, x: -20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-900 bg-neutral-900 p-10 text-white'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-400'}>Plunk</div>
initial={{opacity: 0, x: -20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-white'}>Pay per email sent</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-300'}>Pay-as-you-go pricing. Only pay for emails you actually send.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-white'}>Pay-as-you-go</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border-2 border-neutral-900 bg-white p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Only pay for emails you actually send</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Scale up or down without commitment</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-900 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Marketing and automation included</li>
<span className={'text-sm font-semibold text-white'}>Plunk</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Pay per email sent</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay-as-you-go pricing. Only pay for emails you actually send.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Pay-as-you-go</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Only pay for emails you actually send</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Scale up or down without commitment</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Marketing and automation included</span>
</div>
</div>
</motion.div> </motion.div>
<motion.div initial={{opacity: 0, x: 20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-200 bg-white p-10'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>Resend</div>
initial={{opacity: 0, x: 20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-neutral-900'}>Fixed subscription tiers</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Monthly subscription with fixed email limits per tier.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-neutral-900'}>Fixed subscription</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border border-neutral-200 bg-neutral-50 p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Locked into monthly subscription tiers</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Need to upgrade plan as you grow</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-200 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Transactional only, no marketing</li>
<span className={'text-sm font-semibold text-neutral-900'}>Resend</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Fixed subscription tiers</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Monthly subscription with fixed email limits per tier.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Fixed subscription</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Locked into monthly subscription tiers</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Need to upgrade plan as you grow</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Transactional only, no marketing</span>
</div>
</div>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Feature Comparison */} {/* Key advantages */}
<section className={'py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>What Plunk Adds</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Feature-by-Feature</h2>
</motion.div>
<ComparisonTable competitorName="Resend" rows={comparisonData} />
</section>
{/* What Plunk Adds */}
<section className={'py-32'}>
<motion.div
initial={{opacity: 0, y: 20}}
whileInView={{opacity: 1, y: 0}}
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-20 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>What Plunk Adds</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Beyond transactional emails</p> <p className={'mt-4 text-lg text-neutral-600'}>Beyond transactional emails</p>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-3'}> <div className={'grid gap-px bg-neutral-200 sm:grid-cols-3'}>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><BarChart3 className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Marketing Campaigns</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Send one-time broadcasts to all contacts or specific segments. Schedule sends, track performance. Resend doesn't offer this.</p>
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<BarChart3 className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Marketing Campaigns</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Send one-time broadcasts to all contacts or specific segments. Schedule sends, track performance. Resend
doesn't offer this.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Workflow className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Workflow Automation</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Build multi-step email sequences with triggers, delays, and conditions. Perfect for onboarding, drip campaigns, cart abandonment.</p>
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Workflow className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Workflow Automation</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Build multi-step email sequences with triggers, delays, and conditions. Perfect for onboarding, drip
campaigns, cart abandonment.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Users className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Dynamic Segmentation</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Create audience segments that update automatically based on contact data and behavior. Target campaigns precisely.</p>
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Users className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Dynamic Segmentation</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Create audience segments that update automatically based on contact data and behavior. Target campaigns
precisely.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><PackageOpen className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Open Source</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>AGPL-3.0 licensed. Inspect the code, contribute features, no vendor lock-in. Resend is proprietary.</p>
transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<PackageOpen className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Open Source</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
AGPL-3.0 licensed. Inspect the code, contribute features, no vendor lock-in. Resend is proprietary.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Globe className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Self-Hostable</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Run on your infrastructure with Docker. Full data control, compliance-ready. Pay only AWS SES fees when self-hosting.</p>
transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Globe className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Self-Hostable</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Run on your infrastructure with Docker. Full data control, compliance-ready. Pay only AWS SES fees when
self-hosting.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Layers className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>All-in-One Platform</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>One platform for transactional, marketing, and automation. No need for multiple tools or integrations.</p>
transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Layers className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>All-in-One Platform</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
One platform for transactional, marketing, and automation. No need for multiple tools or integrations.
</p>
</motion.div> </motion.div>
</div> </div>
</div>
</section>
{/* Feature comparison table */}
<section className={'border-t border-neutral-200'}>
<div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
<motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
<h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Feature comparison</h2>
</motion.div>
<ComparisonTable competitorName="Resend" rows={comparisonData} />
</div>
</section> </section>
{/* FAQ */} {/* FAQ */}
<FAQSection faqs={faqs} schemaId="faq-schema-resend" /> <FAQSection faqs={faqs} schemaId="faq-schema-resend" />
{/* CTA */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2 initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}} style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}>
} Try Plunk free
/> </motion.h2>
<motion.div <motion.div initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}} className={'flex max-w-md flex-col gap-6'}>
initial={{opacity: 0, y: 20}} <p className={'text-base text-neutral-300 sm:text-lg'}>1,000 emails/month free. No credit card required. Add marketing and automation when you need it.</p>
whileInView={{opacity: 1, y: 0}} <div className={'flex flex-wrap gap-3'}>
viewport={{once: true}} <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} Get started free <ArrowRight className="h-4 w-4" />
className={'mx-auto max-w-3xl text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Try Plunk free</h2>
<p className={'mt-6 text-lg text-neutral-600'}>
1,000 emails/month free. No credit card required. Add marketing and automation when you need it.
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={'/pricing'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}>
href={WIKI_URI} View pricing
target={'_blank'}
className={
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
Read documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main>
</main>
<Footer /> <Footer />
</> </>
); );
+97 -308
View File
@@ -4,7 +4,7 @@ import {DASHBOARD_URI, WIKI_URI} from '../../lib/constants';
import React from 'react'; import React from 'react';
import Link from 'next/link'; import Link from 'next/link';
import {NextSeo} from 'next-seo'; import {NextSeo} from 'next-seo';
import {ArrowRight, BarChart3, DollarSign, Globe, PackageOpen, Users, Zap} from 'lucide-react'; import {ArrowRight, BarChart3, Check, DollarSign, Globe, PackageOpen, Users, Zap} from 'lucide-react';
import type {ComparisonRow} from '../../components/ComparisonTable'; import type {ComparisonRow} from '../../components/ComparisonTable';
import type {FAQ} from '../../components/FAQSection'; import type {FAQ} from '../../components/FAQSection';
@@ -69,364 +69,153 @@ export default function SendGridComparison() {
<Navbar /> <Navbar />
<main className={'mx-auto max-w-7xl px-8 sm:px-0'}> <main className={'text-neutral-800'}>
{/* Hero Section */}
<section className={'relative py-32 sm:py-48'}>
<div
className={
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_110%)]'
}
/>
<motion.div {/* Hero */}
initial={{opacity: 0, y: 20}} <section className={'relative overflow-hidden'}>
animate={{opacity: 1, y: 0}} <div aria-hidden className={'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#eeeeee_1px,transparent_1px),linear-gradient(to_bottom,#eeeeee_1px,transparent_1px)] bg-[size:6rem_6rem] [mask-image:radial-gradient(ellipse_70%_60%_at_50%_30%,#000_40%,transparent_95%)]'} />
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <div className={'mx-auto max-w-[88rem] px-6 pb-20 pt-20 sm:px-10 sm:pt-28 sm:pb-28'}>
className={'mx-auto max-w-4xl text-center'} <motion.div initial={{opacity: 0, y: 16}} animate={{opacity: 1, y: 0}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}>
> <div style={{fontFamily: 'var(--font-mono)'}} className={'mb-6 text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>
<div Plunk vs SendGrid
className={
'mb-6 inline-flex items-center gap-2 rounded-full border border-neutral-200 bg-white px-4 py-2'
}
>
<span className={'text-sm text-neutral-600'}>Comparing</span>
<span className={'text-sm font-semibold text-neutral-900'}>Plunk vs SendGrid</span>
</div> </div>
<h1 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.75rem,7vw,6.5rem)] font-extrabold leading-[0.92] tracking-[-0.04em] text-neutral-900'}>
<h1 className={'text-6xl font-bold tracking-tight text-neutral-900 sm:text-7xl lg:text-8xl text-balance'}>
Open-source alternative Open-source alternative
<br /> <br />
for SendGrid for SendGrid
</h1> </h1>
<p className={'mt-6 max-w-2xl text-xl text-neutral-600'}>Pay-as-you-go instead of fixed subscriptions. No complex setup, no feature gating, no enterprise sales pitches. Built for developers, not procurement teams.</p>
<p className={'mx-auto mt-8 max-w-2xl text-xl text-neutral-600'}> <div className={'mt-10 flex flex-wrap gap-3'}>
Pay-as-you-go instead of fixed subscriptions. No complex setup, no feature gating, no enterprise sales <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'group inline-flex items-center gap-2 rounded-full bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-[0_10px_30px_-10px_rgba(23,23,23,0.35)] transition hover:bg-neutral-800'}>
pitches. Built for developers, not procurement teams. Get started free <ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" />
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white shadow-lg shadow-neutral-900/10 transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={WIKI_URI} target={'_blank'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-900'}>
href={WIKI_URI}
target={'_blank'}
className={
'rounded-lg border border-neutral-300 bg-white px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View documentation View documentation
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</section> </section>
{/* Pricing Model Comparison */} {/* Pricing comparison */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>
viewport={{once: true}} The Pricing Model That Makes Sense
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} </h2>
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>The Pricing Model That Makes Sense</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Pay for what you use, not for what you might use</p> <p className={'mt-4 text-lg text-neutral-600'}>Pay for what you use, not for what you might use</p>
</motion.div> </motion.div>
<div className={'grid gap-4 lg:grid-cols-2'}>
<div className={'grid gap-8 lg:grid-cols-2'}> <motion.div initial={{opacity: 0, x: -20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-900 bg-neutral-900 p-10 text-white'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-400'}>Plunk</div>
initial={{opacity: 0, x: -20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-white'}>Pay per email sent</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-300'}>Pay-as-you-go pricing. Only pay for emails you actually send, no monthly minimums.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-white'}>Pay-as-you-go</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border-2 border-neutral-900 bg-white p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />No monthly minimum or commitment</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Marketing campaigns included</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-900 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-300'}><Check className="h-4 w-4 flex-shrink-0 text-neutral-400" />Workflow automation included</li>
<span className={'text-sm font-semibold text-white'}>Plunk</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Pay per email sent</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay-as-you-go pricing. Only pay for emails you actually send, no monthly minimums.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Pay-as-you-go</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>No monthly minimum or commitment</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Marketing campaigns included</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-900 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-white'} />
</div>
<span>Workflow automation included</span>
</div>
</div>
</motion.div> </motion.div>
<motion.div initial={{opacity: 0, x: 20}} whileInView={{opacity: 1, x: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'rounded-[24px] border border-neutral-200 bg-white p-10'}>
<motion.div <div style={{fontFamily: 'var(--font-mono)'}} className={'text-[11px] uppercase tracking-[0.18em] text-neutral-500'}>SendGrid</div>
initial={{opacity: 0, x: 20}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-2xl font-bold tracking-[-0.025em] text-neutral-900'}>Monthly subscription tiers</h3>
whileInView={{opacity: 1, x: 0}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Fixed monthly fees based on email volume tiers with feature restrictions.</p>
viewport={{once: true}} <div style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-4xl font-extrabold tracking-[-0.03em] text-neutral-900'}>Fixed subscription</div>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} <ul className={'mt-8 space-y-3'}>
className={'rounded-2xl border border-neutral-200 bg-neutral-50 p-10'} <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Locked into monthly subscription plan</li>
> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Marketing is a separate paid product</li>
<div className={'mb-4 inline-flex items-center gap-2 rounded-full bg-neutral-200 px-4 py-1.5'}> <li className={'flex items-center gap-3 text-sm text-neutral-600'}><div className={'h-1.5 w-1.5 flex-shrink-0 rounded-full bg-neutral-400'} />Automation locked to enterprise tier</li>
<span className={'text-sm font-semibold text-neutral-900'}>SendGrid</span> </ul>
</div>
<h3 className={'mt-6 text-2xl font-bold text-neutral-900'}>Monthly subscription tiers</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Fixed monthly fees based on email volume tiers with feature restrictions.
</p>
<div className={'mt-6 text-4xl font-bold text-neutral-900'}>Fixed subscription</div>
<div className={'mt-8 space-y-3'}>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Locked into monthly subscription plan</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Marketing is a separate paid product</span>
</div>
<div className={'flex items-center gap-3 text-sm text-neutral-600'}>
<div className={'h-5 w-5 rounded-full bg-neutral-300 flex items-center justify-center'}>
<div className={'h-1.5 w-1.5 rounded-full bg-neutral-600'} />
</div>
<span>Automation locked to enterprise tier</span>
</div>
</div>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Key Advantages */} {/* Key advantages */}
<section className={'py-32'}> <section className={'border-t border-neutral-200 bg-neutral-50/60'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Why Choose Plunk Over SendGrid</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-20 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Why Choose Plunk Over SendGrid</h2>
<p className={'mt-4 text-lg text-neutral-600'}>Built for modern developers, not enterprise sales teams</p> <p className={'mt-4 text-lg text-neutral-600'}>Built for modern developers, not enterprise sales teams</p>
</motion.div> </motion.div>
<div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}> <div className={'grid gap-px bg-neutral-200 sm:grid-cols-2 lg:grid-cols-3'}>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><DollarSign className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Simple, Transparent Pricing</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Pay-as-you-go per email. No hidden fees, no complex tiers, no enterprise sales calls. Start free, scale as you grow.</p>
transition={{duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<DollarSign className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Simple, Transparent Pricing</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Pay-as-you-go per email. No hidden fees, no complex tiers, no enterprise sales calls. Start free, scale
as you grow.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Zap className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>5-Minute Setup</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Start sending emails in minutes, not hours. Modern API, clear documentation, no complex configuration. Copy-paste and go.</p>
transition={{duration: 0.5, delay: 0.2, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Zap className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>5-Minute Setup</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Start sending emails in minutes, not hours. Modern API, clear documentation, no complex configuration.
Copy-paste and go.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><BarChart3 className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Marketing Included</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Campaigns, workflows, and segmentation at no extra cost. SendGrid requires their separate Marketing Campaigns product with additional fees.</p>
transition={{duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<BarChart3 className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Marketing Included</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Campaigns, workflows, and segmentation at no extra cost. SendGrid requires their separate Marketing
Campaigns product with additional fees.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><PackageOpen className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Open Source & Transparent</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>AGPL-3.0 licensed. Inspect the code, contribute features, self-host if needed. No black boxes, no vendor lock-in.</p>
transition={{duration: 0.5, delay: 0.4, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<PackageOpen className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Open Source & Transparent</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
AGPL-3.0 licensed. Inspect the code, contribute features, self-host if needed. No black boxes, no vendor
lock-in.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Globe className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>Self-Hostable</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>Run on your infrastructure with Docker. Full data control, compliance-ready, cost-optimized. SendGrid is cloud-only.</p>
transition={{duration: 0.5, delay: 0.5, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Globe className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>Self-Hostable</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
Run on your infrastructure with Docker. Full data control, compliance-ready, cost-optimized. SendGrid is
cloud-only.
</p>
</motion.div> </motion.div>
<motion.div <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}} className={'bg-white p-10'}>
initial={{opacity: 0, y: 20}} <div className={'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white'}><Users className="h-5 w-5" /></div>
whileInView={{opacity: 1, y: 0}} <h3 style={{fontFamily: 'var(--font-display)'}} className={'mt-6 text-xl font-bold tracking-[-0.02em] text-neutral-900'}>No Feature Gating</h3>
viewport={{once: true}} <p className={'mt-3 leading-relaxed text-neutral-600'}>All features available on all plans. No artificial limits, no forced upgrades to "enterprise" for basic automation.</p>
transition={{duration: 0.5, delay: 0.6, ease: [0.22, 1, 0.36, 1]}}
className={'group bg-white p-12 transition hover:bg-neutral-50'}
>
<div
className={
'flex h-12 w-12 items-center justify-center rounded-xl bg-neutral-900 text-white transition group-hover:scale-110'
}
>
<Users className="h-5 w-5" />
</div>
<h3 className={'mt-6 text-xl font-semibold text-neutral-900'}>No Feature Gating</h3>
<p className={'mt-3 leading-relaxed text-neutral-600'}>
All features available on all plans. No artificial limits, no forced upgrades to "enterprise" for basic
automation.
</p>
</motion.div> </motion.div>
</div> </div>
</div>
</section> </section>
{/* Feature Comparison */} {/* Feature comparison table */}
<section className={'py-32'}> <section className={'border-t border-neutral-200'}>
<motion.div <div className={'mx-auto max-w-[88rem] px-6 py-20 sm:px-10'}>
initial={{opacity: 0, y: 20}} <motion.div initial={{opacity: 0, y: 20}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16'}>
whileInView={{opacity: 1, y: 0}} <h2 style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2rem,5vw,4rem)] font-extrabold leading-[0.95] tracking-[-0.03em] text-neutral-900'}>Feature comparison</h2>
viewport={{once: true}}
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}}
className={'mb-16 text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Feature-by-Feature Comparison</h2>
<p className={'mt-4 text-lg text-neutral-600'}>See exactly what you get with each platform</p>
</motion.div> </motion.div>
<ComparisonTable competitorName="SendGrid" rows={comparisonData} /> <ComparisonTable competitorName="SendGrid" rows={comparisonData} />
</div>
</section> </section>
{/* FAQ */} {/* FAQ */}
<FAQSection faqs={faqs} schemaId="faq-schema-sendgrid" /> <FAQSection faqs={faqs} schemaId="faq-schema-sendgrid" />
{/* CTA */} {/* CTA */}
<section className={'relative overflow-hidden border-t border-neutral-200 py-32'}> <section className={'relative overflow-hidden border-t border-neutral-900 bg-neutral-900 text-white'}>
<div <div className={'mx-auto max-w-[88rem] px-6 py-32 sm:px-10 sm:py-40'}>
className={ <div className={'flex flex-col items-start gap-12 lg:flex-row lg:items-end lg:justify-between'}>
'absolute inset-0 -z-10 h-full w-full bg-white bg-[linear-gradient(to_right,#e5e7eb_1px,transparent_1px),linear-gradient(to_bottom,#e5e7eb_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_100%,#000_70%,transparent_110%)]' <motion.h2 initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, ease: [0.22, 1, 0.36, 1]}} style={{fontFamily: 'var(--font-display)'}} className={'text-[clamp(2.5rem,7vw,6rem)] font-extrabold leading-[0.95] tracking-[-0.035em]'}>
} Make the switch today
/> </motion.h2>
<motion.div <motion.div initial={{opacity: 0, y: 16}} whileInView={{opacity: 1, y: 0}} viewport={{once: true}} transition={{duration: 0.9, delay: 0.15, ease: [0.22, 1, 0.36, 1]}} className={'flex max-w-md flex-col gap-6'}>
initial={{opacity: 0, y: 20}} <p className={'text-base text-neutral-300 sm:text-lg'}>Join hundreds of developers who've ditched SendGrid's complexity for Plunk's simplicity.</p>
whileInView={{opacity: 1, y: 0}} <div className={'flex flex-wrap gap-3'}>
viewport={{once: true}} <motion.a whileHover={{scale: 1.015}} whileTap={{scale: 0.985}} href={`${DASHBOARD_URI}/auth/signup`} className={'inline-flex items-center gap-2 rounded-full bg-white px-7 py-3.5 text-sm font-semibold text-neutral-900 transition hover:bg-neutral-100'}>
transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} Get started free <ArrowRight className="h-4 w-4" />
className={'mx-auto max-w-3xl text-center'}
>
<h2 className={'text-5xl font-bold tracking-tight text-neutral-900 text-balance'}>Make the switch today</h2>
<p className={'mt-6 text-lg text-neutral-600'}>
Join hundreds of developers who've ditched SendGrid's complexity for Plunk's simplicity.
</p>
<div className={'mt-12 flex flex-wrap justify-center gap-4'}>
<motion.a
whileHover={{scale: 1.02}}
whileTap={{scale: 0.98}}
href={`${DASHBOARD_URI}/auth/signup`}
className={
'group rounded-lg bg-neutral-900 px-8 py-4 text-base font-semibold text-white transition hover:bg-neutral-800'
}
>
<span className={'flex items-center gap-2'}>
Get started free
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-1" />
</span>
</motion.a> </motion.a>
<Link <Link href={'/pricing'} className={'inline-flex items-center gap-2 rounded-full border border-neutral-700 px-7 py-3.5 text-sm font-semibold text-white transition hover:border-white'}>
href="/pricing" View pricing
className={
'rounded-lg border border-neutral-300 px-8 py-4 text-base font-semibold text-neutral-900 transition hover:border-neutral-400'
}
>
View pricing details
</Link> </Link>
</div> </div>
</motion.div> </motion.div>
</div>
</div>
</section> </section>
</main>
</main>
<Footer /> <Footer />
</> </>
); );
+20
View File
@@ -161,6 +161,26 @@
body { body {
@apply bg-background text-neutral-800; @apply bg-background text-neutral-800;
font-family: var(--font-body, ui-sans-serif, system-ui, sans-serif);
font-feature-settings: "rlig" 1, "calt" 1; font-feature-settings: "rlig" 1, "calt" 1;
} }
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-display, ui-sans-serif, system-ui, sans-serif);
}
}
@keyframes marquee-x {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
.marquee-track {
animation: marquee-x 40s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
.marquee-track {
animation: none;
}
} }