From 19ea8b012291ef88649cd58461770b25698a775b Mon Sep 17 00:00:00 2001 From: Dries Augustyns Date: Sun, 19 Apr 2026 09:03:50 +0200 Subject: [PATCH] ui: Polish details --- .../src/components/ComparisonTable.tsx | 4 +- apps/landing/src/components/FAQSection.tsx | 4 +- .../src/components/guides/GuideLayout.tsx | 21 ++-- .../src/pages/features/email-editor.tsx | 70 ++++++----- .../src/pages/features/inbound-email.tsx | 71 ++++++----- apps/landing/src/pages/features/segments.tsx | 63 +++++----- apps/landing/src/pages/features/smtp.tsx | 68 +++++----- apps/landing/src/pages/features/workflows.tsx | 71 +++++------ .../src/pages/guides/email-api-guide.tsx | 22 ++-- .../pages/guides/email-click-through-rate.tsx | 22 ++-- .../src/pages/guides/email-deliverability.tsx | 10 +- .../guides/email-marketing-best-practices.tsx | 16 +-- .../src/pages/guides/email-open-rate.tsx | 14 +-- .../pages/guides/email-sender-reputation.tsx | 18 +-- apps/landing/src/pages/guides/index.tsx | 117 +++++++++--------- .../landing/src/pages/guides/what-is-dkim.tsx | 20 +-- .../src/pages/guides/what-is-dmarc.tsx | 8 +- apps/landing/src/pages/guides/what-is-spf.tsx | 16 +-- apps/landing/src/pages/index.tsx | 34 ++--- apps/landing/src/pages/pricing.tsx | 51 ++++---- apps/landing/src/pages/tools/verify-email.tsx | 6 +- apps/landing/src/pages/vs/activecampaign.tsx | 14 +-- apps/landing/src/pages/vs/bento.tsx | 14 +-- apps/landing/src/pages/vs/brevo.tsx | 14 +-- apps/landing/src/pages/vs/convertkit.tsx | 14 +-- apps/landing/src/pages/vs/customerio.tsx | 14 +-- apps/landing/src/pages/vs/index.tsx | 32 ++--- apps/landing/src/pages/vs/klaviyo.tsx | 14 +-- apps/landing/src/pages/vs/loops.tsx | 14 +-- apps/landing/src/pages/vs/mailchimp.tsx | 14 +-- apps/landing/src/pages/vs/mailerlite.tsx | 14 +-- apps/landing/src/pages/vs/mailgun.tsx | 14 +-- apps/landing/src/pages/vs/postmark.tsx | 14 +-- apps/landing/src/pages/vs/resend.tsx | 14 +-- apps/landing/src/pages/vs/sendgrid.tsx | 14 +-- 35 files changed, 478 insertions(+), 462 deletions(-) diff --git a/apps/landing/src/components/ComparisonTable.tsx b/apps/landing/src/components/ComparisonTable.tsx index 283950d..0fad9b5 100644 --- a/apps/landing/src/components/ComparisonTable.tsx +++ b/apps/landing/src/components/ComparisonTable.tsx @@ -39,9 +39,9 @@ export function ComparisonTable({competitorName, rows}: ComparisonTableProps) { className={'grid grid-cols-3 gap-px bg-neutral-200'} >
- {row.feature} + {row.feature}
-
+
{typeof row.plunk === 'boolean' ? ( row.plunk ? ( diff --git a/apps/landing/src/components/FAQSection.tsx b/apps/landing/src/components/FAQSection.tsx index 6c3fe94..ac4b4e2 100644 --- a/apps/landing/src/components/FAQSection.tsx +++ b/apps/landing/src/components/FAQSection.tsx @@ -35,13 +35,13 @@ export function FAQSection({faqs, schemaId = 'faq-schema'}: FAQSectionProps) { />
-
+

-

+

{title}

On this page

diff --git a/apps/landing/src/pages/features/smtp.tsx b/apps/landing/src/pages/features/smtp.tsx index 872f12b..d75f140 100644 --- a/apps/landing/src/pages/features/smtp.tsx +++ b/apps/landing/src/pages/features/smtp.tsx @@ -111,9 +111,11 @@ export default function SMTPFeature() { >
- SMTP + Features + + SMTP

-
+
-
+
{features.map((feature, index) => { const highlighted = feature.featured; return ( @@ -222,7 +224,7 @@ export default function SMTPFeature() { {/* Comparison table */}
-
+
-
+
Perfect for these scenarios

-
+
    {useCases.map((useCase, index) => ( - -
    -
    - {useCase.icon} -
    -
    -

    - {useCase.title} -

    -

    {useCase.description}

    -
    -
    - {useCase.benefit} -
    -
    + + {String(index + 1).padStart(2, '0')} + +

    + {useCase.title} +

    +
    +

    {useCase.description}

    + + → {useCase.benefit} +
    - + ))} -
    +
diff --git a/apps/landing/src/pages/features/workflows.tsx b/apps/landing/src/pages/features/workflows.tsx index 80f8137..e4cebc9 100644 --- a/apps/landing/src/pages/features/workflows.tsx +++ b/apps/landing/src/pages/features/workflows.tsx @@ -100,9 +100,11 @@ export default function WorkflowsFeature() { >
- Workflow Automation + Features + + Workflow Automation

-
+
Powerful features that make complex automations simple

-
+
{features.map((feature, index) => { const highlighted = feature.featured; return ( @@ -211,13 +213,13 @@ export default function WorkflowsFeature() { {/* How it works */}
-
+

-
+
From onboarding to re-engagement, workflows handle it all

-
+
    {useCases.map((useCase, index) => ( - -
    -
    - {useCase.icon} -
    -
    -

    - {useCase.title} -

    -

    {useCase.description}

    -
    -

    - {useCase.example} -

    -
    -
    + + {String(index + 1).padStart(2, '0')} + +

    + {useCase.title} +

    +
    +

    {useCase.description}

    +

    + {useCase.example} +

    - + ))} -
    +

diff --git a/apps/landing/src/pages/guides/email-api-guide.tsx b/apps/landing/src/pages/guides/email-api-guide.tsx index a504115..84095ea 100644 --- a/apps/landing/src/pages/guides/email-api-guide.tsx +++ b/apps/landing/src/pages/guides/email-api-guide.tsx @@ -78,7 +78,7 @@ export default function EmailAPIGuide() {

How Email APIs Work

-
+

1. Authentication

You authenticate requests using an API key (usually passed in headers). This identifies your account and @@ -86,14 +86,14 @@ export default function EmailAPIGuide() {

-
+

2. Make HTTP Request

Send a POST request to the API endpoint with email details (recipient, subject, body, etc.) as JSON.

-
+

3. API Validates & Queues

The API validates your request, queues the email for delivery, and returns a response with the email ID @@ -101,14 +101,14 @@ export default function EmailAPIGuide() {

-
+

4. Email Delivery

The service handles SMTP connections, retry logic, and delivery to the recipient's mail server.

-
+

5. Webhooks & Tracking

You receive webhook notifications for delivery events (delivered, bounced, opened, clicked) and can query @@ -535,7 +535,7 @@ func main() {

-
+

Deliverability Reputation

Choose providers with strong deliverability rates and sender reputation. Poor deliverability means your @@ -543,7 +543,7 @@ func main() {

-
+

Feature Set

Ensure the API supports your needs: templates, webhooks, analytics, scheduling, attachments, etc. Some @@ -551,7 +551,7 @@ func main() {

-
+

Pricing Model

Understand pricing: per-email charges, monthly tiers, overage fees. Calculate costs for your expected @@ -559,7 +559,7 @@ func main() {

-
+

Developer Experience

Good documentation, SDKs in your language, clear error messages, and responsive support make @@ -567,7 +567,7 @@ func main() {

-
+

Scalability & Reliability

Can the provider handle your peak volumes? What's their uptime guarantee (SLA)? Do they have redundancy @@ -575,7 +575,7 @@ func main() {

-
+

Compliance & Security

Ensure the provider complies with GDPR, CAN-SPAM, and other relevant regulations. Check their security diff --git a/apps/landing/src/pages/guides/email-click-through-rate.tsx b/apps/landing/src/pages/guides/email-click-through-rate.tsx index 1b8c2cd..41a0df0 100644 --- a/apps/landing/src/pages/guides/email-click-through-rate.tsx +++ b/apps/landing/src/pages/guides/email-click-through-rate.tsx @@ -141,7 +141,7 @@ CTOR = (294 ÷ 2,450) × 100 = 12.0%`}

What Affects Click-Through Rates?

-
+

1. Call-to-Action (CTA) Design

Your CTA's design, placement, and copy directly impact clicks. Clear, prominent, action-oriented CTAs @@ -149,7 +149,7 @@ CTOR = (294 ÷ 2,450) × 100 = 12.0%`}

-
+

2. Email Relevance

Targeted, personalized content generates 2-3x higher CTR than generic blasts. Segmentation and @@ -157,7 +157,7 @@ CTOR = (294 ÷ 2,450) × 100 = 12.0%`}

-
+

3. Value Proposition

Recipients need a clear reason to click. Compelling value propositions—exclusive content, limited offers, @@ -165,7 +165,7 @@ CTOR = (294 ÷ 2,450) × 100 = 12.0%`}

-
+

4. Mobile Optimization

60%+ of emails are read on mobile. Unoptimized emails with small links or poorly formatted content see 50% @@ -173,7 +173,7 @@ CTOR = (294 ÷ 2,450) × 100 = 12.0%`}

-
+

5. Content Scannability

Most people skim emails. Clear structure with headers, bullet points, and whitespace helps readers find @@ -181,7 +181,7 @@ CTOR = (294 ÷ 2,450) × 100 = 12.0%`}

-
+

6. Number of CTAs

More CTAs = divided attention. Emails with one primary CTA convert 371% better than those with multiple @@ -402,14 +402,14 @@ CTOR = (294 ÷ 2,450) × 100 = 12.0%`}

Common CTR Mistakes to Avoid

-
+

✗ Too Many CTAs

Multiple competing CTAs confuse readers and reduce overall clicks. Focus on one primary action per email.

-
+

✗ Vague CTA Copy

"Click here" and "Learn more" don't communicate value. Be specific: "Download free guide" or "Start 14-day @@ -417,7 +417,7 @@ CTOR = (294 ÷ 2,450) × 100 = 12.0%`}

-
+

✗ Image-Only CTAs

Many email clients block images by default. If your CTA is an image, users won't see it. Use HTML buttons @@ -425,14 +425,14 @@ CTOR = (294 ÷ 2,450) × 100 = 12.0%`}

-
+

✗ Small, Hard-to-Tap Links

Tiny text links are difficult to tap on mobile. Use large buttons (minimum 44x44px) for easy tapping.

-
+

✗ No Clear Value Proposition

Readers won't click if they don't know why they should. Clearly communicate the benefit of clicking before diff --git a/apps/landing/src/pages/guides/email-deliverability.tsx b/apps/landing/src/pages/guides/email-deliverability.tsx index e6dda91..f632c89 100644 --- a/apps/landing/src/pages/guides/email-deliverability.tsx +++ b/apps/landing/src/pages/guides/email-deliverability.tsx @@ -71,7 +71,7 @@ export default function EmailDeliverability() {

-
+

1. Sender Reputation

Email providers track your sending behavior over time. High engagement rates, low spam complaints, and few @@ -79,7 +79,7 @@ export default function EmailDeliverability() {

-
+

2. Email Authentication

SPF, DKIM, and DMARC authenticate your emails and prove they're legitimate. Without proper authentication, @@ -87,7 +87,7 @@ export default function EmailDeliverability() {

-
+

3. Email Content

Spam filters analyze your subject lines, body content, links, and images. Spammy language, excessive @@ -95,7 +95,7 @@ export default function EmailDeliverability() {

-
+

4. List Quality & Engagement

Sending to engaged subscribers who want your emails is crucial. High open rates and clicks signal quality. @@ -103,7 +103,7 @@ export default function EmailDeliverability() {

-
+

5. Technical Infrastructure

Your sending IP address, domain reputation, and email infrastructure affect how providers perceive your diff --git a/apps/landing/src/pages/guides/email-marketing-best-practices.tsx b/apps/landing/src/pages/guides/email-marketing-best-practices.tsx index 043484d..c77968a 100644 --- a/apps/landing/src/pages/guides/email-marketing-best-practices.tsx +++ b/apps/landing/src/pages/guides/email-marketing-best-practices.tsx @@ -107,7 +107,7 @@ export default function EmailMarketingBestPractices() {

Email Content Best Practices

-
+

1. Craft Compelling Subject Lines

Your subject line determines whether emails get opened. Keep them under 50 characters, create curiosity, @@ -125,7 +125,7 @@ export default function EmailMarketingBestPractices() {

-
+

2. Personalize Beyond First Names

Use behavioral data, purchase history, browsing activity, or preferences. Personalized emails deliver 6x @@ -133,7 +133,7 @@ export default function EmailMarketingBestPractices() {

-
+

3. Focus on One Primary Goal

Each email should have one clear call-to-action (CTA). Multiple CTAs confuse readers and reduce conversion @@ -141,7 +141,7 @@ export default function EmailMarketingBestPractices() {

-
+

4. Write Scannable Content

Most people skim emails. Structure content for easy scanning:

    @@ -153,7 +153,7 @@ export default function EmailMarketingBestPractices() {
-
+

5. Create Compelling CTAs

Effective CTAs are:

    @@ -172,7 +172,7 @@ export default function EmailMarketingBestPractices() {
-
+

6. Provide Real Value

Every email should benefit the reader. Share insights, solve problems, offer exclusive content, or provide @@ -361,7 +361,7 @@ export default function EmailMarketingBestPractices() {

-
+

What to A/B Test

  • @@ -385,7 +385,7 @@ export default function EmailMarketingBestPractices() {
-
+

A/B Testing Best Practices

  • • Test one variable at a time for clear results
  • diff --git a/apps/landing/src/pages/guides/email-open-rate.tsx b/apps/landing/src/pages/guides/email-open-rate.tsx index 07cf31d..c7cb666 100644 --- a/apps/landing/src/pages/guides/email-open-rate.tsx +++ b/apps/landing/src/pages/guides/email-open-rate.tsx @@ -131,7 +131,7 @@ Open Rate = (285 ÷ 950) × 100 = 30%`}

    What Affects Email Open Rates?

    -
    +

    1. Subject Line

    Your subject line is the #1 factor. It must be compelling, relevant, and create curiosity without being @@ -161,7 +161,7 @@ Open Rate = (285 ÷ 950) × 100 = 30%`}

    -
    +

    2. Sender Name

    Recipients decide whether to open based on who it's from. Use a recognizable name—either your brand or a @@ -169,7 +169,7 @@ Open Rate = (285 ÷ 950) × 100 = 30%`}

    -
    +

    3. Send Time & Day

    Timing impacts visibility. B2B emails typically perform best Tuesday-Thursday, 10am-2pm. B2C varies more @@ -177,7 +177,7 @@ Open Rate = (285 ÷ 950) × 100 = 30%`}

    -
    +

    4. List Quality & Segmentation

    Engaged subscribers open more. Segmenting by behavior, interests, or demographics ensures relevance. @@ -185,7 +185,7 @@ Open Rate = (285 ÷ 950) × 100 = 30%`}

    -
    +

    5. Deliverability & Sender Reputation

    If emails land in spam, they won't be opened. Maintain good sender reputation through proper @@ -193,7 +193,7 @@ Open Rate = (285 ÷ 950) × 100 = 30%`}

    -
    +

    6. Email Frequency

    Too frequent leads to fatigue and unsubscribes. Too infrequent and subscribers forget you. Find the sweet @@ -201,7 +201,7 @@ Open Rate = (285 ÷ 950) × 100 = 30%`}

    -
    +

    7. Mobile Optimization

    60%+ of emails are opened on mobile. Use short subject lines (40-50 characters), clear preview text, and diff --git a/apps/landing/src/pages/guides/email-sender-reputation.tsx b/apps/landing/src/pages/guides/email-sender-reputation.tsx index aa4e065..d8a5e0b 100644 --- a/apps/landing/src/pages/guides/email-sender-reputation.tsx +++ b/apps/landing/src/pages/guides/email-sender-reputation.tsx @@ -70,7 +70,7 @@ export default function EmailSenderReputation() {

    What Affects Sender Reputation?

    -
    +

    1. Spam Complaint Rate

    Impact: Critical. When recipients mark your emails as spam, it severely damages @@ -81,7 +81,7 @@ export default function EmailSenderReputation() {

    -
    +

    2. Engagement Metrics

    Impact: Very High. Email providers track opens, clicks, replies, forwards, and deletes. @@ -92,7 +92,7 @@ export default function EmailSenderReputation() {

    -
    +

    3. Bounce Rate

    Impact: High. High bounce rates (especially hard bounces) indicate poor list hygiene, @@ -103,7 +103,7 @@ export default function EmailSenderReputation() {

    -
    +

    4. Email Authentication

    Impact: High. Proper SPF, DKIM, and DMARC authentication proves your emails are @@ -114,7 +114,7 @@ export default function EmailSenderReputation() {

    -
    +

    5. Spam Trap Hits

    Impact: Critical. Spam traps are email addresses used to catch senders with poor @@ -125,7 +125,7 @@ export default function EmailSenderReputation() {

    -
    +

    6. Sending Volume & Consistency

    Impact: Moderate. Sudden spikes in volume look suspicious. Inconsistent sending (long @@ -136,7 +136,7 @@ export default function EmailSenderReputation() {

    -
    +

    7. Content Quality

    Impact: Moderate. Spammy content (excessive links, misleading subject lines, all caps) @@ -147,7 +147,7 @@ export default function EmailSenderReputation() {

    -
    +

    8. Blacklist Status

    Impact: Critical. Being listed on major blacklists (Spamhaus, Barracuda, SURBL) can block @@ -158,7 +158,7 @@ export default function EmailSenderReputation() {

    -
    +

    9. Sending History

    Impact: Cumulative. Reputation is built over time. New domains/IPs have no history (zero diff --git a/apps/landing/src/pages/guides/index.tsx b/apps/landing/src/pages/guides/index.tsx index fee422f..f2fa777 100644 --- a/apps/landing/src/pages/guides/index.tsx +++ b/apps/landing/src/pages/guides/index.tsx @@ -94,7 +94,13 @@ const guides: Guide[] = [ }, ]; +const badgeOrder = ['Authentication', 'Deliverability', 'Analytics', 'Technical', 'Best Practices', 'Fundamentals']; + export default function GuidesIndex() { + const categories = badgeOrder + .map(name => ({name, guides: guides.filter(g => g.badge === name)})) + .filter(c => c.guides.length > 0); + return ( <> - {/* Guides grid */} + {/* Guides - Categorized */}

    - -

    - Browse all guides -

    -

    Everything you need to master email

    -
    - -
    - {guides.map((guide, index) => { - const Icon = guide.icon; - return ( - - + {categories.map((category, catIndex) => ( + +
    + -
    -
    - -
    - {guide.badge && ( - - {guide.badge} - - )} -
    -
    -

    +
    +
    + +
    + {category.guides.map(guide => { + const Icon = guide.icon; + return ( + - {guide.title} -

    -

    {guide.description}

    -
    - - - ); - })} + +
    +

    + {guide.title} +

    +

    {guide.description}

    +
    + + + ); + })} +
    +
    + ))}
    diff --git a/apps/landing/src/pages/guides/what-is-dkim.tsx b/apps/landing/src/pages/guides/what-is-dkim.tsx index 7968228..b16d62c 100644 --- a/apps/landing/src/pages/guides/what-is-dkim.tsx +++ b/apps/landing/src/pages/guides/what-is-dkim.tsx @@ -33,7 +33,7 @@ export default function WhatIsDKIM() {

    -
    +

    1. The Sending Server Signs the Email

    When you send an email, your email server adds a DKIM signature to the email header. This signature is @@ -41,7 +41,7 @@ export default function WhatIsDKIM() {

    -
    +

    2. The Signature is Added to Headers

    The DKIM signature includes a hash of specific email components (like the subject, body, and sender) and @@ -49,7 +49,7 @@ export default function WhatIsDKIM() {

    -
    +

    3. The Receiving Server Verifies

    When the email arrives, the receiving server looks up your domain's public DKIM key in DNS, then uses it @@ -57,7 +57,7 @@ export default function WhatIsDKIM() {

    -
    +

    4. Delivery Decision

    Passing DKIM verification improves your sender reputation and deliverability. Failing or missing DKIM may @@ -252,7 +252,7 @@ export default function WhatIsDKIM() {

    DKIM Best Practices

    -
    +

    ✓ Use 2048-bit Keys

    While 1024-bit keys still work, 2048-bit keys provide better security and are recommended by Gmail and @@ -260,7 +260,7 @@ export default function WhatIsDKIM() {

    -
    +

    ✓ Implement SPF and DMARC Too

    DKIM works best when combined with SPF and DMARC for comprehensive email authentication. Use all three for @@ -268,7 +268,7 @@ export default function WhatIsDKIM() {

    -
    +

    ✓ Monitor DKIM Status

    Regularly check that your DKIM signatures are passing. Most email platforms provide authentication @@ -276,7 +276,7 @@ export default function WhatIsDKIM() {

    -
    +

    ✓ Rotate Keys Periodically

    For enhanced security, rotate your DKIM keys every 6-12 months. Plan key rotation carefully to avoid @@ -284,14 +284,14 @@ export default function WhatIsDKIM() {

    -
    +

    ✗ Don't Share Private Keys

    Your DKIM private key should never be shared or stored insecurely. Treat it like a password.

    -
    +

    ✗ Don't Use the Same Key Across Domains

    Each domain should have its own unique DKIM key pair for security and proper authentication. diff --git a/apps/landing/src/pages/guides/what-is-dmarc.tsx b/apps/landing/src/pages/guides/what-is-dmarc.tsx index 7bac48d..15fd591 100644 --- a/apps/landing/src/pages/guides/what-is-dmarc.tsx +++ b/apps/landing/src/pages/guides/what-is-dmarc.tsx @@ -32,7 +32,7 @@ export default function WhatIsDMARC() {

    -
    +

    1. Email Authentication

    When an email is received, the server first checks SPF and DKIM authentication. At least one of these must @@ -40,7 +40,7 @@ export default function WhatIsDMARC() {

    -
    +

    2. Alignment Check

    DMARC checks if the domain in the "From" header aligns with the domain that passed SPF or DKIM. This is @@ -48,7 +48,7 @@ export default function WhatIsDMARC() {

    -
    +

    3. Policy Application

    If authentication and alignment pass, the email is delivered. If they fail, the receiving server follows @@ -56,7 +56,7 @@ export default function WhatIsDMARC() {

    -
    +

    4. Reporting

    Receiving servers send daily reports to your specified email address, showing authentication results for diff --git a/apps/landing/src/pages/guides/what-is-spf.tsx b/apps/landing/src/pages/guides/what-is-spf.tsx index 8c50108..53291ce 100644 --- a/apps/landing/src/pages/guides/what-is-spf.tsx +++ b/apps/landing/src/pages/guides/what-is-spf.tsx @@ -32,7 +32,7 @@ export default function WhatIsSPF() {

    -
    +

    1. You Publish an SPF Record

    You add a TXT record to your domain's DNS that lists all IP addresses and services authorized to send @@ -40,7 +40,7 @@ export default function WhatIsSPF() {

    -
    +

    2. An Email is Sent

    When someone sends an email claiming to be from your domain, the receiving server notes the IP address of @@ -48,7 +48,7 @@ export default function WhatIsSPF() {

    -
    +

    3. The Receiving Server Checks SPF

    The receiving server looks up your domain's SPF record in DNS and checks if the sending server's IP @@ -56,7 +56,7 @@ export default function WhatIsSPF() {

    -
    +

    4. Pass or Fail

    If the IP matches, SPF passes. If not, SPF fails and the email may be flagged as spam or rejected, @@ -268,7 +268,7 @@ export default function WhatIsSPF() {

    Common SPF Mistakes to Avoid

    -
    +

    ✗ Multiple SPF Records

    Never create multiple SPF TXT records. You can only have ONE SPF record per domain. Combine all authorized @@ -276,7 +276,7 @@ export default function WhatIsSPF() {

    -
    +

    ✗ Exceeding 10 DNS Lookups

    Each include: mechanism counts toward the 10 lookup limit. Too many includes will cause SPF @@ -284,7 +284,7 @@ export default function WhatIsSPF() {

    -
    +

    ✗ Forgetting to Update SPF

    When you add new email services, remember to update your SPF record. Outdated SPF records cause legitimate @@ -292,7 +292,7 @@ export default function WhatIsSPF() {

    -
    +

    ✗ Using +all

    Never use +all (pass all). This completely defeats the purpose of SPF by allowing anyone to diff --git a/apps/landing/src/pages/index.tsx b/apps/landing/src/pages/index.tsx index 4aba914..6ed687f 100644 --- a/apps/landing/src/pages/index.tsx +++ b/apps/landing/src/pages/index.tsx @@ -284,7 +284,7 @@ export default function Index() {

    The open-source @@ -328,7 +328,7 @@ export default function Index() { viewport={{once: true, margin: '-10%'}} transition={{duration: 0.9, delay: 0.25, ease: [0.22, 1, 0.36, 1]}} className={ - 'mt-20 grid grid-cols-2 gap-x-8 gap-y-10 border-t border-neutral-200 pt-10 sm:mt-28 sm:grid-cols-4' + 'mt-20 grid grid-cols-2 gap-x-12 gap-y-10 border-t border-neutral-200 pt-10 sm:mt-28 sm:grid-cols-4 sm:gap-x-20' } > {[ @@ -391,7 +391,7 @@ export default function Index() { {/* ========== COMPETITORS — EDITORIAL LIST ========== */} -
    +
    -
      +
        {competitors.map((c, i) => ( -
        +
        {[ { tag: 'Setup', @@ -523,7 +523,7 @@ export default function Index() { subtitle={'Every Plunk install ships with the full platform — no upsell pages, no locked modules.'} /> -
        +
        {features.map((feature, index) => { const highlighted = feature.feature; return ( @@ -535,8 +535,8 @@ export default function Index() { transition={{duration: 0.5, delay: index * 0.06, ease: [0.22, 1, 0.36, 1]}} className={ highlighted - ? 'group relative flex min-h-[18rem] flex-col justify-between overflow-hidden rounded-[28px] border border-neutral-900 bg-neutral-900 p-8 text-white' - : 'group relative flex min-h-[18rem] flex-col justify-between overflow-hidden rounded-[28px] border border-neutral-200 bg-white p-8 transition hover:border-neutral-900' + ? 'flex min-h-72 flex-col justify-between overflow-hidden rounded-[28px] border border-neutral-900 bg-neutral-900 p-8 text-white' + : 'flex min-h-72 flex-col justify-between overflow-hidden rounded-[28px] border border-neutral-200 bg-white p-8 transition hover:border-neutral-900' } >
        @@ -622,8 +622,8 @@ export default function Index() { ))}
        -
        - +

    diff --git a/apps/landing/src/pages/tools/verify-email.tsx b/apps/landing/src/pages/tools/verify-email.tsx index 24b0cf7..3740823 100644 --- a/apps/landing/src/pages/tools/verify-email.tsx +++ b/apps/landing/src/pages/tools/verify-email.tsx @@ -205,7 +205,7 @@ export default function VerifyEmailPage() { subtitle={'Invalid addresses hurt deliverability. Verification keeps your list clean before you send.'} /> -
    +
    {EMAIL_VERIFICATION_FEATURES.map((feature, index) => { const Icon = feature.icon; return ( @@ -216,7 +216,7 @@ export default function VerifyEmailPage() { viewport={{once: true}} transition={{duration: 0.5, delay: index * 0.05, ease: [0.22, 1, 0.36, 1]}} className={ - 'flex min-h-[14rem] flex-col justify-between rounded-[28px] border border-neutral-200 bg-white p-8 transition hover:border-neutral-900' + 'flex flex-col gap-8 rounded-[20px] border border-neutral-200 bg-white p-8 transition hover:border-neutral-900' } >
    @@ -225,7 +225,7 @@ export default function VerifyEmailPage() {

    {feature.title}

    diff --git a/apps/landing/src/pages/vs/activecampaign.tsx b/apps/landing/src/pages/vs/activecampaign.tsx index ca7f99b..2c1432e 100644 --- a/apps/landing/src/pages/vs/activecampaign.tsx +++ b/apps/landing/src/pages/vs/activecampaign.tsx @@ -97,8 +97,8 @@ export default function ActiveCampaignComparison() { {/* Pricing comparison */}
    -
    - +
    +

    Enterprise Features Without Enterprise Prices

    @@ -133,8 +133,8 @@ export default function ActiveCampaignComparison() { {/* Key advantages */}
    -
    - +
    +

    Automation Without Complexity

    Powerful email workflows without the enterprise overhead

    @@ -159,8 +159,8 @@ export default function ActiveCampaignComparison() { {/* Feature comparison table */}
    -
    - +
    +

    Feature comparison

    @@ -172,7 +172,7 @@ export default function ActiveCampaignComparison() { {/* CTA */}
    -
    +
    Email automation, not enterprise complexity. diff --git a/apps/landing/src/pages/vs/bento.tsx b/apps/landing/src/pages/vs/bento.tsx index d70aa55..fc7b5cc 100644 --- a/apps/landing/src/pages/vs/bento.tsx +++ b/apps/landing/src/pages/vs/bento.tsx @@ -97,8 +97,8 @@ export default function BentoComparison() { {/* Pricing comparison */}
    -
    - +
    +

    Focused Email vs All-in-One Complexity

    @@ -133,8 +133,8 @@ export default function BentoComparison() { {/* Key advantages */}
    -
    - +
    +

    Developer-First Email Platform

    Everything you need for email, nothing you don't

    @@ -158,8 +158,8 @@ export default function BentoComparison() { {/* Feature comparison table */}
    -
    - +
    +

    Feature comparison

    @@ -171,7 +171,7 @@ export default function BentoComparison() { {/* CTA */}
    -
    +
    Focused email. No bloat. diff --git a/apps/landing/src/pages/vs/brevo.tsx b/apps/landing/src/pages/vs/brevo.tsx index 11af664..8d90df7 100644 --- a/apps/landing/src/pages/vs/brevo.tsx +++ b/apps/landing/src/pages/vs/brevo.tsx @@ -99,8 +99,8 @@ export default function BrevoComparison() { {/* Pricing comparison */}
    -
    - +
    +

    Pricing That Scales With You

    @@ -135,8 +135,8 @@ export default function BrevoComparison() { {/* Key advantages */}
    -
    - +
    +

    Why Choose Plunk Over Brevo

    Focus on email, not feature overload

    @@ -182,8 +182,8 @@ export default function BrevoComparison() { {/* Feature comparison table */}
    -
    - +
    +

    Feature comparison

    @@ -195,7 +195,7 @@ export default function BrevoComparison() { {/* CTA */}
    -
    +
    Make the switch to simplicity diff --git a/apps/landing/src/pages/vs/convertkit.tsx b/apps/landing/src/pages/vs/convertkit.tsx index 268621f..51371a2 100644 --- a/apps/landing/src/pages/vs/convertkit.tsx +++ b/apps/landing/src/pages/vs/convertkit.tsx @@ -100,8 +100,8 @@ export default function ConvertkitComparison() { {/* Pricing comparison */}
    -
    - +
    +

    Pay for Emails, Not Subscribers

    @@ -136,8 +136,8 @@ export default function ConvertkitComparison() { {/* Key advantages */}
    -
    - +
    +

    Built for Developers, Not Creators

    @@ -182,8 +182,8 @@ export default function ConvertkitComparison() { {/* Feature comparison table */}
    -
    - +
    +

    Feature comparison

    @@ -195,7 +195,7 @@ export default function ConvertkitComparison() { {/* CTA */}
    -
    +
    Ready for a developer-first email platform? diff --git a/apps/landing/src/pages/vs/customerio.tsx b/apps/landing/src/pages/vs/customerio.tsx index 48d9035..af6bb85 100644 --- a/apps/landing/src/pages/vs/customerio.tsx +++ b/apps/landing/src/pages/vs/customerio.tsx @@ -95,8 +95,8 @@ export default function CustomerioComparison() { {/* Pricing comparison */}
    -
    - +
    +

    Simple Pricing That Scales

    @@ -131,8 +131,8 @@ export default function CustomerioComparison() { {/* Key advantages */}
    -
    - +
    +

    Key Advantages

    Why developers choose Plunk

    @@ -178,8 +178,8 @@ export default function CustomerioComparison() { {/* Feature comparison table */}
    -
    - +
    +

    Feature comparison

    @@ -191,7 +191,7 @@ export default function CustomerioComparison() { {/* CTA */}
    -
    +
    Try Plunk free diff --git a/apps/landing/src/pages/vs/index.tsx b/apps/landing/src/pages/vs/index.tsx index 58198db..7563318 100644 --- a/apps/landing/src/pages/vs/index.tsx +++ b/apps/landing/src/pages/vs/index.tsx @@ -157,13 +157,13 @@ export default function CompetitorsIndex() { {/* Competitors grid */}
    -
    +

    {competitor.description}

    -
    - {competitor.features.map(feature => ( - - {feature} - +
    + {competitor.features.map((feature, i) => ( + + {i > 0 && ·} + + {feature} + + ))}
    @@ -219,13 +221,13 @@ export default function CompetitorsIndex() { {/* Why Plunk */}
    -
    +

    -
    +
    -
    - +
    +

    E-commerce Email Without the Premium Price

    @@ -133,8 +133,8 @@ export default function KlaviyoComparison() { {/* Key advantages */}
    -
    - +
    +

    E-commerce Email, Developer-Friendly

    All the automation power, at a fraction of the cost

    @@ -159,8 +159,8 @@ export default function KlaviyoComparison() { {/* Feature comparison table */}
    -
    - +
    +

    Feature comparison

    @@ -172,7 +172,7 @@ export default function KlaviyoComparison() { {/* CTA */}
    -
    +
    E-commerce email at a fraction of the cost. diff --git a/apps/landing/src/pages/vs/loops.tsx b/apps/landing/src/pages/vs/loops.tsx index 2f2b2eb..ff2c6ab 100644 --- a/apps/landing/src/pages/vs/loops.tsx +++ b/apps/landing/src/pages/vs/loops.tsx @@ -99,8 +99,8 @@ export default function LoopsComparison() { {/* Pricing comparison */}
    -
    - +
    +

    Transparent Pricing vs Vendor Lock-In

    @@ -135,8 +135,8 @@ export default function LoopsComparison() { {/* Key advantages */}
    -
    - +
    +

    Why Choose Plunk Over Loops

    Open-source transparency meets modern SaaS features

    @@ -182,8 +182,8 @@ export default function LoopsComparison() { {/* Feature comparison table */}
    -
    - +
    +

    Feature comparison

    @@ -195,7 +195,7 @@ export default function LoopsComparison() { {/* CTA */}
    -
    +
    Switch to open source diff --git a/apps/landing/src/pages/vs/mailchimp.tsx b/apps/landing/src/pages/vs/mailchimp.tsx index c3e4207..447636d 100644 --- a/apps/landing/src/pages/vs/mailchimp.tsx +++ b/apps/landing/src/pages/vs/mailchimp.tsx @@ -100,8 +100,8 @@ export default function MailchimpComparison() { {/* Pricing comparison */}
    -
    - +
    +

    The Pricing Model That Makes Sense

    @@ -138,8 +138,8 @@ export default function MailchimpComparison() { {/* Key advantages */}
    -
    - +
    +

    Why Developers Choose Plunk

    @@ -184,8 +184,8 @@ export default function MailchimpComparison() { {/* Feature comparison table */}
    -
    - +
    +

    Feature comparison

    @@ -197,7 +197,7 @@ export default function MailchimpComparison() { {/* CTA */}
    -
    +
    Ready for a better developer experience? diff --git a/apps/landing/src/pages/vs/mailerlite.tsx b/apps/landing/src/pages/vs/mailerlite.tsx index 834685f..fb26f04 100644 --- a/apps/landing/src/pages/vs/mailerlite.tsx +++ b/apps/landing/src/pages/vs/mailerlite.tsx @@ -97,8 +97,8 @@ export default function MailerliteComparison() { {/* Pricing comparison */}
    -
    - +
    +

    Open Source Meets Developer Experience

    @@ -133,8 +133,8 @@ export default function MailerliteComparison() { {/* Key advantages */}
    -
    - +
    +

    The Truly Developer-First Alternative

    Full control, transparent code, pay only for what you send

    @@ -159,8 +159,8 @@ export default function MailerliteComparison() { {/* Feature comparison table */}
    -
    - +
    +

    Feature comparison

    @@ -172,7 +172,7 @@ export default function MailerliteComparison() { {/* CTA */}
    -
    +
    Experience true developer-first email. diff --git a/apps/landing/src/pages/vs/mailgun.tsx b/apps/landing/src/pages/vs/mailgun.tsx index 51e8c87..4692960 100644 --- a/apps/landing/src/pages/vs/mailgun.tsx +++ b/apps/landing/src/pages/vs/mailgun.tsx @@ -95,8 +95,8 @@ export default function MailgunComparison() { {/* Pricing comparison */}
    -
    - +
    +

    The Pricing Model That Makes Sense

    @@ -131,8 +131,8 @@ export default function MailgunComparison() { {/* Key advantages */}
    -
    - +
    +

    What Plunk Adds

    Beyond transactional emails

    @@ -178,8 +178,8 @@ export default function MailgunComparison() { {/* Feature comparison table */}
    -
    - +
    +

    Feature comparison

    @@ -191,7 +191,7 @@ export default function MailgunComparison() { {/* CTA */}
    -
    +
    Try Plunk free diff --git a/apps/landing/src/pages/vs/postmark.tsx b/apps/landing/src/pages/vs/postmark.tsx index 49c1b9d..0e23c79 100644 --- a/apps/landing/src/pages/vs/postmark.tsx +++ b/apps/landing/src/pages/vs/postmark.tsx @@ -96,8 +96,8 @@ export default function PostmarkComparison() { {/* Pricing comparison */}
    -
    - +
    +

    One Platform for All Your Emails

    @@ -132,8 +132,8 @@ export default function PostmarkComparison() { {/* Key advantages */}
    -
    - +
    +

    Why Choose Plunk Over Postmark

    Do more with one platform instead of two

    @@ -179,8 +179,8 @@ export default function PostmarkComparison() { {/* Feature comparison table */}
    -
    - +
    +

    Feature comparison

    @@ -192,7 +192,7 @@ export default function PostmarkComparison() { {/* CTA */}
    -
    +
    Get more from your email platform diff --git a/apps/landing/src/pages/vs/resend.tsx b/apps/landing/src/pages/vs/resend.tsx index 02cf85d..cc499c8 100644 --- a/apps/landing/src/pages/vs/resend.tsx +++ b/apps/landing/src/pages/vs/resend.tsx @@ -95,8 +95,8 @@ export default function ResendComparison() { {/* Pricing comparison */}
    -
    - +
    +

    The Pricing Model That Makes Sense

    @@ -131,8 +131,8 @@ export default function ResendComparison() { {/* Key advantages */}
    -
    - +
    +

    What Plunk Adds

    Beyond transactional emails

    @@ -178,8 +178,8 @@ export default function ResendComparison() { {/* Feature comparison table */}
    -
    - +
    +

    Feature comparison

    @@ -191,7 +191,7 @@ export default function ResendComparison() { {/* CTA */}
    -
    +
    Try Plunk free diff --git a/apps/landing/src/pages/vs/sendgrid.tsx b/apps/landing/src/pages/vs/sendgrid.tsx index 8781142..aa6663d 100644 --- a/apps/landing/src/pages/vs/sendgrid.tsx +++ b/apps/landing/src/pages/vs/sendgrid.tsx @@ -99,8 +99,8 @@ export default function SendGridComparison() { {/* Pricing comparison */}
    -
    - +
    +

    The Pricing Model That Makes Sense

    @@ -135,8 +135,8 @@ export default function SendGridComparison() { {/* Key advantages */}
    -
    - +
    +

    Why Choose Plunk Over SendGrid

    Built for modern developers, not enterprise sales teams

    @@ -182,8 +182,8 @@ export default function SendGridComparison() { {/* Feature comparison table */}
    -
    - +
    +

    Feature comparison

    @@ -195,7 +195,7 @@ export default function SendGridComparison() { {/* CTA */}
    -
    +
    Make the switch today