From 7648f6e1ebc12a7c7aa8b4fdb79a9b0d89fe05f2 Mon Sep 17 00:00:00 2001 From: Dries Augustyns Date: Wed, 31 Dec 2025 15:08:26 +0100 Subject: [PATCH] chore: Replace references to deprecated services --- .env.self-host.example | 8 +++--- CLAUDE.md | 6 ++-- CONTRIBUTING.md | 6 ++-- apps/landing/next-sitemap.config.js | 2 +- .../src/components/guides/GuideLayout.tsx | 6 ++-- apps/landing/src/pages/_app.tsx | 2 +- .../src/pages/guides/email-api-guide.tsx | 12 ++++---- .../src/pages/guides/email-bounce-rate.tsx | 2 +- .../pages/guides/email-click-through-rate.tsx | 2 +- .../src/pages/guides/email-deliverability.tsx | 6 ++-- .../guides/email-marketing-best-practices.tsx | 2 +- .../src/pages/guides/email-open-rate.tsx | 2 +- .../pages/guides/email-sender-reputation.tsx | 2 +- apps/landing/src/pages/guides/index.tsx | 6 ++-- .../transactional-vs-marketing-email.tsx | 2 +- .../landing/src/pages/guides/what-is-dkim.tsx | 2 +- .../src/pages/guides/what-is-dmarc.tsx | 2 +- apps/landing/src/pages/guides/what-is-spf.tsx | 2 +- apps/landing/src/pages/privacy.tsx | 4 +-- apps/landing/src/pages/terms.tsx | 8 +++--- apps/landing/src/pages/tools/index.tsx | 6 ++-- .../src/pages/tools/markdown-to-email.tsx | 6 ++-- apps/landing/src/pages/tools/verify-email.tsx | 6 ++-- apps/landing/src/pages/vs/activecampaign.tsx | 18 ++++++------ apps/landing/src/pages/vs/bento.tsx | 26 ++++++++--------- apps/landing/src/pages/vs/brevo.tsx | 6 ++-- apps/landing/src/pages/vs/convertkit.tsx | 12 ++++---- apps/landing/src/pages/vs/customerio.tsx | 6 ++-- apps/landing/src/pages/vs/index.tsx | 6 ++-- apps/landing/src/pages/vs/klaviyo.tsx | 8 +++--- apps/landing/src/pages/vs/loops.tsx | 6 ++-- apps/landing/src/pages/vs/mailchimp.tsx | 6 ++-- apps/landing/src/pages/vs/mailerlite.tsx | 18 ++++++------ apps/landing/src/pages/vs/mailgun.tsx | 6 ++-- apps/landing/src/pages/vs/postmark.tsx | 6 ++-- apps/landing/src/pages/vs/resend.tsx | 6 ++-- apps/landing/src/pages/vs/sendgrid.tsx | 6 ++-- apps/web/next-sitemap.config.js | 2 +- apps/wiki/app/layout.config.tsx | 2 +- apps/wiki/app/layout.tsx | 8 +++--- apps/wiki/components/api-url.tsx | 4 +-- .../content/docs/api-reference/errors.mdx | 6 ++-- apps/wiki/lib/remark-replace-env.mjs | 18 +++++------- apps/wiki/next-sitemap.config.mjs | 6 ++-- apps/wiki/openapi.json | 28 ++++++++++--------- packages/email/src/common/Footer.tsx | 12 ++------ .../email/src/emails/BillingLimitExceeded.tsx | 4 +-- .../email/src/emails/BillingLimitWarning.tsx | 4 +-- .../email/src/emails/EmailVerification.tsx | 2 +- packages/email/src/emails/PasswordReset.tsx | 8 ++---- packages/email/src/emails/ProjectDisabled.tsx | 4 +-- 51 files changed, 163 insertions(+), 183 deletions(-) diff --git a/.env.self-host.example b/.env.self-host.example index 1f173c7..90a2df3 100644 --- a/.env.self-host.example +++ b/.env.self-host.example @@ -27,10 +27,10 @@ WIKI_URI=http://localhost:1000 # NEXT_PUBLIC_* variables are used for client-side code and sitemap generation # Use placeholder URLs that will be replaced at Docker container runtime -NEXT_PUBLIC_API_URI=https://api.useplunk.com -NEXT_PUBLIC_DASHBOARD_URI=https://app.useplunk.com -NEXT_PUBLIC_LANDING_URI=https://www.useplunk.com -NEXT_PUBLIC_WIKI_URI=https://docs.useplunk.com +NEXT_PUBLIC_API_URI=https://next-api.useplunk.com +NEXT_PUBLIC_DASHBOARD_URI=https://next-app.useplunk.com +NEXT_PUBLIC_LANDING_URI=https://next.useplunk.com +NEXT_PUBLIC_WIKI_URI=https://next-wiki.useplunk.com # Set to 'true' if using HTTPS in production (behind a reverse proxy/load balancer) # This affects how application URIs are auto-generated from domain names diff --git a/CLAUDE.md b/CLAUDE.md index d7855aa..b937dce 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -67,9 +67,9 @@ to run them separately (e.g., for debugging), use `dev:server` and `dev:worker` - HTTP API endpoints for the platform - Background cron jobs (workflow processor, domain verification) - **Worker process** (separate): BullMQ worker for processing email, campaign, and workflow queues -- **web**: Next.js app (Pages Router) - Main platform (app.useplunk.com) -- **landing**: Next.js app (Pages Router) - Marketing site (www.useplunk.com) -- **wiki**: Next.js app - Documentation site (docs.useplunk.com) +- **web**: Next.js app (Pages Router) - Main platform (next-app.useplunk.com) +- **landing**: Next.js app (Pages Router) - Marketing site (next.useplunk.com) +- **wiki**: Next.js app - Documentation site (next-wiki.useplunk.com) ### Background Job Architecture diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f2d860e..1316b8e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,8 +10,8 @@ Plunk V2 is built as a modern Turborepo monorepo with the following structure: - **api**: Express.js API server with background worker process (BullMQ) - **web**: Next.js dashboard application (app.useplunk.com) -- **landing**: Next.js marketing site (www.useplunk.com) -- **wiki**: Next.js documentation site (docs.useplunk.com) +- **landing**: Next.js marketing site (next.useplunk.com) +- **wiki**: Next.js documentation site (next-wiki.useplunk.com) ### Shared Packages (`packages/`) @@ -135,7 +135,7 @@ between groups. ## Need Help? -- Check the [documentation](https://docs.useplunk.com) +- Check the [documentation](https://next-wiki.useplunk.com) - Open an issue for bugs or feature requests - Join our community discussions diff --git a/apps/landing/next-sitemap.config.js b/apps/landing/next-sitemap.config.js index 24bb943..7dc80ab 100644 --- a/apps/landing/next-sitemap.config.js +++ b/apps/landing/next-sitemap.config.js @@ -1,5 +1,5 @@ /** @type {import('next-sitemap').IConfig} */ module.exports = { - siteUrl: process.env.NEXT_PUBLIC_LANDING_URI || 'https://www.useplunk.com', + siteUrl: process.env.NEXT_PUBLIC_LANDING_URI || 'https://next.useplunk.com', generateRobotsTxt: true, }; diff --git a/apps/landing/src/components/guides/GuideLayout.tsx b/apps/landing/src/components/guides/GuideLayout.tsx index 189335d..b1ac43a 100644 --- a/apps/landing/src/components/guides/GuideLayout.tsx +++ b/apps/landing/src/components/guides/GuideLayout.tsx @@ -25,7 +25,7 @@ export function GuideLayout({ readTime, children, canonical, - ogImage = 'https://www.useplunk.com/assets/card.png', + ogImage = 'https://next.useplunk.com/assets/card.png', }: GuideLayoutProps) { const [headings, setHeadings] = useState<{id: string; text: string; level: number}[]>([]); const [activeId, setActiveId] = useState(''); @@ -74,8 +74,8 @@ export function GuideLayout({ // Generate breadcrumb items const breadcrumbItems = [ - {position: 1, name: 'Home', item: 'https://www.useplunk.com'}, - {position: 2, name: 'Guides', item: 'https://www.useplunk.com/guides'}, + {position: 1, name: 'Home', item: 'https://next.useplunk.com'}, + {position: 2, name: 'Guides', item: 'https://next.useplunk.com/guides'}, {position: 3, name: title, item: canonical || ''}, ]; diff --git a/apps/landing/src/pages/_app.tsx b/apps/landing/src/pages/_app.tsx index f295623..ebae776 100644 --- a/apps/landing/src/pages/_app.tsx +++ b/apps/landing/src/pages/_app.tsx @@ -63,7 +63,7 @@ export default function WithProviders(props: AppProps) { title: 'Plunk | The Open-Source Email Platform', description: 'Open-source email automation platform with workflows, segments, and developer API. Scale from 0 to millions of emails at $0.001 per email. Self-hostable and privacy-first.', - images: [{url: 'https://www.useplunk.com/assets/card.png', alt: 'Plunk'}], + images: [{url: 'https://next.useplunk.com/assets/card.png', alt: 'Plunk'}], }} additionalMetaTags={[{property: 'title', content: 'Plunk | The Open-Source Email Platform'}]} /> diff --git a/apps/landing/src/pages/guides/email-api-guide.tsx b/apps/landing/src/pages/guides/email-api-guide.tsx index f4e49ce..d642aa1 100644 --- a/apps/landing/src/pages/guides/email-api-guide.tsx +++ b/apps/landing/src/pages/guides/email-api-guide.tsx @@ -10,7 +10,7 @@ export default function EmailAPIGuide() { description="Complete guide to email APIs: how they work, implementation examples, best practices, and choosing the right solution for your application." lastUpdated="2025-12-20" readTime="12 min" - canonical="https://www.useplunk.com/guides/email-api-guide" + canonical="https://next.useplunk.com/guides/email-api-guide" > {/* Introduction */}
@@ -132,7 +132,7 @@ export default function EmailAPIGuide() { language="javascript" title="Node.js Example" code={`// Using fetch (Node.js 18+ or with node-fetch) -const response = await fetch('https://api.useplunk.com/v1/send', { +const response = await fetch('https://next-api.useplunk.com/v1/send', { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -167,7 +167,7 @@ if (response.ok) { code={`import requests response = requests.post( - 'https://api.useplunk.com/v1/send', + 'https://next-api.useplunk.com/v1/send', headers={ 'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_API_KEY' @@ -195,7 +195,7 @@ else: language="php" title="PHP Example" code={` {/* Introduction */}
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..40264ef 100644 --- a/apps/landing/src/pages/guides/email-click-through-rate.tsx +++ b/apps/landing/src/pages/guides/email-click-through-rate.tsx @@ -10,7 +10,7 @@ export default function EmailClickThroughRate() { description="Learn what affects email click-through rates, industry benchmarks, and proven tactics to optimize CTAs and boost engagement." lastUpdated="2025-12-20" readTime="10 min" - canonical="https://www.useplunk.com/guides/email-click-through-rate" + canonical="https://next.useplunk.com/guides/email-click-through-rate" > {/* Introduction */}
diff --git a/apps/landing/src/pages/guides/email-deliverability.tsx b/apps/landing/src/pages/guides/email-deliverability.tsx index 46d34aa..d4adecb 100644 --- a/apps/landing/src/pages/guides/email-deliverability.tsx +++ b/apps/landing/src/pages/guides/email-deliverability.tsx @@ -9,7 +9,7 @@ export default function EmailDeliverability() { description="Learn proven strategies to improve email deliverability, avoid spam filters, and maximize inbox placement rates. Complete guide with best practices." lastUpdated="2025-12-20" readTime="12 min" - canonical="https://www.useplunk.com/guides/email-deliverability" + canonical="https://next.useplunk.com/guides/email-deliverability" > {/* Introduction */}
@@ -306,9 +306,7 @@ export default function EmailDeliverability() { {/* Monitoring */}

Monitoring Email Deliverability

-

- Track these metrics to stay on top of deliverability: -

+

Track these metrics to stay on top of deliverability:

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..2a07bb1 100644 --- a/apps/landing/src/pages/guides/email-marketing-best-practices.tsx +++ b/apps/landing/src/pages/guides/email-marketing-best-practices.tsx @@ -9,7 +9,7 @@ export default function EmailMarketingBestPractices() { description="Master email marketing with proven best practices for content, design, timing, deliverability, and compliance. Comprehensive guide for 2025." lastUpdated="2025-12-20" readTime="15 min" - canonical="https://www.useplunk.com/guides/email-marketing-best-practices" + canonical="https://next.useplunk.com/guides/email-marketing-best-practices" > {/* Introduction */}
diff --git a/apps/landing/src/pages/guides/email-open-rate.tsx b/apps/landing/src/pages/guides/email-open-rate.tsx index 07cf31d..5dbe953 100644 --- a/apps/landing/src/pages/guides/email-open-rate.tsx +++ b/apps/landing/src/pages/guides/email-open-rate.tsx @@ -10,7 +10,7 @@ export default function EmailOpenRate() { description="Learn what affects email open rates, industry benchmarks, and proven tactics to improve opens. Complete guide with actionable tips." lastUpdated="2025-12-20" readTime="10 min" - canonical="https://www.useplunk.com/guides/email-open-rate" + canonical="https://next.useplunk.com/guides/email-open-rate" > {/* Introduction */}
diff --git a/apps/landing/src/pages/guides/email-sender-reputation.tsx b/apps/landing/src/pages/guides/email-sender-reputation.tsx index aa4e065..d26e433 100644 --- a/apps/landing/src/pages/guides/email-sender-reputation.tsx +++ b/apps/landing/src/pages/guides/email-sender-reputation.tsx @@ -10,7 +10,7 @@ export default function EmailSenderReputation() { description="Learn how sender reputation works, what affects it, and proven strategies to build and maintain a positive reputation for maximum deliverability." lastUpdated="2025-12-20" readTime="11 min" - canonical="https://www.useplunk.com/guides/email-sender-reputation" + canonical="https://next.useplunk.com/guides/email-sender-reputation" > {/* Introduction */}
diff --git a/apps/landing/src/pages/guides/index.tsx b/apps/landing/src/pages/guides/index.tsx index 9445710..84a6351 100644 --- a/apps/landing/src/pages/guides/index.tsx +++ b/apps/landing/src/pages/guides/index.tsx @@ -103,13 +103,13 @@ export default function GuidesIndex() { diff --git a/apps/landing/src/pages/guides/transactional-vs-marketing-email.tsx b/apps/landing/src/pages/guides/transactional-vs-marketing-email.tsx index 1e7fbc1..a41c327 100644 --- a/apps/landing/src/pages/guides/transactional-vs-marketing-email.tsx +++ b/apps/landing/src/pages/guides/transactional-vs-marketing-email.tsx @@ -9,7 +9,7 @@ export default function TransactionalVsMarketingEmail() { description="Understand the critical differences between transactional and marketing emails, including legal requirements, deliverability, and best practices." lastUpdated="2025-12-20" readTime="10 min" - canonical="https://www.useplunk.com/guides/transactional-vs-marketing-email" + canonical="https://next.useplunk.com/guides/transactional-vs-marketing-email" > {/* Introduction */}
diff --git a/apps/landing/src/pages/guides/what-is-dkim.tsx b/apps/landing/src/pages/guides/what-is-dkim.tsx index 7968228..ca93320 100644 --- a/apps/landing/src/pages/guides/what-is-dkim.tsx +++ b/apps/landing/src/pages/guides/what-is-dkim.tsx @@ -10,7 +10,7 @@ export default function WhatIsDKIM() { description="Learn how DKIM (DomainKeys Identified Mail) protects your emails from spoofing and improves deliverability. Complete guide with setup examples." lastUpdated="2025-12-20" readTime="8 min" - canonical="https://www.useplunk.com/guides/what-is-dkim" + canonical="https://next.useplunk.com/guides/what-is-dkim" > {/* Introduction */}
diff --git a/apps/landing/src/pages/guides/what-is-dmarc.tsx b/apps/landing/src/pages/guides/what-is-dmarc.tsx index 7bac48d..be8947b 100644 --- a/apps/landing/src/pages/guides/what-is-dmarc.tsx +++ b/apps/landing/src/pages/guides/what-is-dmarc.tsx @@ -10,7 +10,7 @@ export default function WhatIsDMARC() { description="Learn how DMARC works with SPF and DKIM to protect your domain from email spoofing. Complete setup guide with policy examples." lastUpdated="2025-12-20" readTime="9 min" - canonical="https://www.useplunk.com/guides/what-is-dmarc" + canonical="https://next.useplunk.com/guides/what-is-dmarc" > {/* Introduction */}
diff --git a/apps/landing/src/pages/guides/what-is-spf.tsx b/apps/landing/src/pages/guides/what-is-spf.tsx index 8c50108..2aaf6c2 100644 --- a/apps/landing/src/pages/guides/what-is-spf.tsx +++ b/apps/landing/src/pages/guides/what-is-spf.tsx @@ -10,7 +10,7 @@ export default function WhatIsSPF() { description="Learn how SPF records work, prevent email spoofing, and improve deliverability. Complete guide with setup examples and best practices." lastUpdated="2025-12-20" readTime="7 min" - canonical="https://www.useplunk.com/guides/what-is-spf" + canonical="https://next.useplunk.com/guides/what-is-spf" > {/* Introduction */}
diff --git a/apps/landing/src/pages/privacy.tsx b/apps/landing/src/pages/privacy.tsx index ce92025..9c73da5 100644 --- a/apps/landing/src/pages/privacy.tsx +++ b/apps/landing/src/pages/privacy.tsx @@ -110,8 +110,8 @@ export default function Index() { Visit our website at{' '} - - https://www.useplunk.com + + https://next.useplunk.com diff --git a/apps/landing/src/pages/terms.tsx b/apps/landing/src/pages/terms.tsx index 1599694..085e6e0 100644 --- a/apps/landing/src/pages/terms.tsx +++ b/apps/landing/src/pages/terms.tsx @@ -390,8 +390,8 @@ export default function Index() { data-id="fdf30452-99b8-c68b-5cdf-34af764cd1fd" data-type="question" > - - https://www.useplunk.com + + https://next.useplunk.com {' '} website as well as any other media form, media channel, mobile website or mobile application related, @@ -3165,8 +3165,8 @@ export default function Index() { data-id="d10c7fd7-0685-12ac-c717-cbc45ff916d1" data-type="question" > - - https://www.useplunk.com/privacy + + https://next.useplunk.com/privacy diff --git a/apps/landing/src/pages/tools/index.tsx b/apps/landing/src/pages/tools/index.tsx index 697048d..1340258 100644 --- a/apps/landing/src/pages/tools/index.tsx +++ b/apps/landing/src/pages/tools/index.tsx @@ -32,13 +32,13 @@ export default function ToolsIndex() { diff --git a/apps/landing/src/pages/tools/markdown-to-email.tsx b/apps/landing/src/pages/tools/markdown-to-email.tsx index 383f510..4e952ad 100644 --- a/apps/landing/src/pages/tools/markdown-to-email.tsx +++ b/apps/landing/src/pages/tools/markdown-to-email.tsx @@ -28,13 +28,13 @@ export default function MarkdownToEmail() { diff --git a/apps/landing/src/pages/tools/verify-email.tsx b/apps/landing/src/pages/tools/verify-email.tsx index 9de19b0..afd5859 100644 --- a/apps/landing/src/pages/tools/verify-email.tsx +++ b/apps/landing/src/pages/tools/verify-email.tsx @@ -36,12 +36,12 @@ export default function VerifyEmailPage() { diff --git a/apps/landing/src/pages/vs/activecampaign.tsx b/apps/landing/src/pages/vs/activecampaign.tsx index 8d616d8..dbfd109 100644 --- a/apps/landing/src/pages/vs/activecampaign.tsx +++ b/apps/landing/src/pages/vs/activecampaign.tsx @@ -33,7 +33,7 @@ const faqs: FAQ[] = [ 'ActiveCampaign starts at $29/month for basic features and quickly scales to $149/month or more for automation features. Plunk uses pay-as-you-go pricing—you only pay for emails sent. For email-focused needs, Plunk typically costs 50-80% less than ActiveCampaign while providing the same email automation capabilities.', }, { - question: 'Can Plunk match ActiveCampaign\'s automation capabilities?', + question: "Can Plunk match ActiveCampaign's automation capabilities?", answer: 'For email automation, yes. Plunk supports workflow automation, event-based triggers, and audience segmentation just like ActiveCampaign. The difference is Plunk focuses purely on email, while ActiveCampaign includes CRM, sales automation, and ML-powered recommendations. If you need email automation without sales/CRM features, Plunk delivers the same capability with simpler implementation.', }, @@ -45,7 +45,7 @@ const faqs: FAQ[] = [ { question: 'What ActiveCampaign features does Plunk not have?', answer: - 'Plunk focuses on email, so it doesn\'t include ActiveCampaign\'s CRM, sales pipeline management, lead scoring, SMS marketing, or machine learning features. If you need those, ActiveCampaign is better. If you want powerful email automation without the enterprise complexity, Plunk is the simpler choice.', + "Plunk focuses on email, so it doesn't include ActiveCampaign's CRM, sales pipeline management, lead scoring, SMS marketing, or machine learning features. If you need those, ActiveCampaign is better. If you want powerful email automation without the enterprise complexity, Plunk is the simpler choice.", }, ]; @@ -58,13 +58,13 @@ export default function ActiveCampaignComparison() { @@ -233,9 +233,7 @@ export default function ActiveCampaignComparison() { transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-20 text-center'} > -

- Automation Without Complexity -

+

Automation Without Complexity

@@ -318,8 +316,8 @@ export default function ActiveCampaignComparison() {

Open Source

- AGPL-3.0 licensed. Full transparency into how your emails are processed. Contribute features, - understand the system. ActiveCampaign is proprietary. + AGPL-3.0 licensed. Full transparency into how your emails are processed. Contribute features, understand + the system. ActiveCampaign is proprietary.

diff --git a/apps/landing/src/pages/vs/bento.tsx b/apps/landing/src/pages/vs/bento.tsx index f23fab6..6ab5d89 100644 --- a/apps/landing/src/pages/vs/bento.tsx +++ b/apps/landing/src/pages/vs/bento.tsx @@ -25,7 +25,7 @@ const faqs: FAQ[] = [ { question: 'When should I choose Bento over Plunk?', answer: - 'Choose Bento if you need an all-in-one platform with CRM, live chat, and customer relationship features alongside email. Bento is designed for small businesses and creators who want everything in one place. Choose Plunk if you\'re a developer who needs focused email automation without CRM bloat—perfect for integrating email into your product.', + "Choose Bento if you need an all-in-one platform with CRM, live chat, and customer relationship features alongside email. Bento is designed for small businesses and creators who want everything in one place. Choose Plunk if you're a developer who needs focused email automation without CRM bloat—perfect for integrating email into your product.", }, { question: 'What is the pricing difference between Plunk and Bento?', @@ -45,7 +45,7 @@ const faqs: FAQ[] = [ { question: 'Is migration from Bento to Plunk easy?', answer: - 'For email features, yes. Export your contacts from Bento, import them to Plunk, recreate your workflows using our API or dashboard, and integrate Plunk into your application. If you rely heavily on Bento\'s CRM, live chat, or multi-channel features, you\'ll need separate tools for those. Most email-only migrations take a few hours.', + "For email features, yes. Export your contacts from Bento, import them to Plunk, recreate your workflows using our API or dashboard, and integrate Plunk into your application. If you rely heavily on Bento's CRM, live chat, or multi-channel features, you'll need separate tools for those. Most email-only migrations take a few hours.", }, ]; @@ -58,13 +58,13 @@ export default function BentoComparison() { @@ -233,9 +233,7 @@ export default function BentoComparison() { transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-20 text-center'} > -

- Developer-First Email Platform -

+

Developer-First Email Platform

@@ -339,8 +337,8 @@ export default function BentoComparison() {

Self-Hostable

- Deploy on your infrastructure with Docker. Full data control, compliance-ready, no vendor lock-in. - Bento is cloud-only. + Deploy on your infrastructure with Docker. Full data control, compliance-ready, no vendor lock-in. Bento + is cloud-only.

@@ -360,8 +358,8 @@ export default function BentoComparison() {

Email-Focused

- Do one thing exceptionally well: email. No feature bloat, no CRM complexity, no multi-channel - confusion. Just powerful email automation. + Do one thing exceptionally well: email. No feature bloat, no CRM complexity, no multi-channel confusion. + Just powerful email automation.

@@ -394,9 +392,7 @@ export default function BentoComparison() { transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mx-auto max-w-3xl text-center'} > -

- Get focused email automation -

+

Get focused email automation

Join developers choosing focused email solutions over all-in-one complexity. Start free, no credit card required. diff --git a/apps/landing/src/pages/vs/brevo.tsx b/apps/landing/src/pages/vs/brevo.tsx index 9c38a4d..5e1dc0a 100644 --- a/apps/landing/src/pages/vs/brevo.tsx +++ b/apps/landing/src/pages/vs/brevo.tsx @@ -57,13 +57,13 @@ export default function BrevoComparison() { diff --git a/apps/landing/src/pages/vs/convertkit.tsx b/apps/landing/src/pages/vs/convertkit.tsx index b7b9f0a..d2a2d9d 100644 --- a/apps/landing/src/pages/vs/convertkit.tsx +++ b/apps/landing/src/pages/vs/convertkit.tsx @@ -45,7 +45,7 @@ const faqs: FAQ[] = [ { question: 'How easy is it to migrate from ConvertKit to Plunk?', answer: - 'Migration is straightforward. Export your subscribers from ConvertKit as CSV, import them to Plunk via our API or dashboard, recreate your email sequences using our workflow builder, and update your forms to use Plunk\'s API. Most migrations can be completed in a few hours. You\'ll need to rebuild landing pages separately if you rely on ConvertKit\'s landing page feature.', + "Migration is straightforward. Export your subscribers from ConvertKit as CSV, import them to Plunk via our API or dashboard, recreate your email sequences using our workflow builder, and update your forms to use Plunk's API. Most migrations can be completed in a few hours. You'll need to rebuild landing pages separately if you rely on ConvertKit's landing page feature.", }, ]; @@ -58,13 +58,13 @@ export default function ConvertkitComparison() { @@ -141,9 +141,7 @@ export default function ConvertkitComparison() { transition={{duration: 0.7, ease: [0.22, 1, 0.36, 1]}} className={'mb-16 text-center'} > -

- Pay for Emails, Not Subscribers -

+

Pay for Emails, Not Subscribers

Pricing that grows with usage, not list size

diff --git a/apps/landing/src/pages/vs/customerio.tsx b/apps/landing/src/pages/vs/customerio.tsx index 95862f3..1da5c9e 100644 --- a/apps/landing/src/pages/vs/customerio.tsx +++ b/apps/landing/src/pages/vs/customerio.tsx @@ -53,13 +53,13 @@ export default function CustomerioComparison() { diff --git a/apps/landing/src/pages/vs/index.tsx b/apps/landing/src/pages/vs/index.tsx index 980d251..4f32061 100644 --- a/apps/landing/src/pages/vs/index.tsx +++ b/apps/landing/src/pages/vs/index.tsx @@ -96,13 +96,13 @@ export default function CompetitorsIndex() { diff --git a/apps/landing/src/pages/vs/klaviyo.tsx b/apps/landing/src/pages/vs/klaviyo.tsx index ea01e41..80c320f 100644 --- a/apps/landing/src/pages/vs/klaviyo.tsx +++ b/apps/landing/src/pages/vs/klaviyo.tsx @@ -45,7 +45,7 @@ const faqs: FAQ[] = [ { question: 'What Klaviyo features does Plunk not have?', answer: - 'Plunk focuses on email, so it doesn\'t include Klaviyo\'s SMS marketing, native e-commerce platform integrations, AI-powered product recommendations, or predictive analytics. If you need those enterprise features and have the budget, Klaviyo is better. If you want powerful email automation at a fraction of the cost, Plunk delivers.', + "Plunk focuses on email, so it doesn't include Klaviyo's SMS marketing, native e-commerce platform integrations, AI-powered product recommendations, or predictive analytics. If you need those enterprise features and have the budget, Klaviyo is better. If you want powerful email automation at a fraction of the cost, Plunk delivers.", }, ]; @@ -58,13 +58,13 @@ export default function KlaviyoComparison() { diff --git a/apps/landing/src/pages/vs/loops.tsx b/apps/landing/src/pages/vs/loops.tsx index dae5e0b..30f0259 100644 --- a/apps/landing/src/pages/vs/loops.tsx +++ b/apps/landing/src/pages/vs/loops.tsx @@ -57,13 +57,13 @@ export default function LoopsComparison() { diff --git a/apps/landing/src/pages/vs/mailchimp.tsx b/apps/landing/src/pages/vs/mailchimp.tsx index 2d0d78d..101563e 100644 --- a/apps/landing/src/pages/vs/mailchimp.tsx +++ b/apps/landing/src/pages/vs/mailchimp.tsx @@ -58,13 +58,13 @@ export default function MailchimpComparison() { diff --git a/apps/landing/src/pages/vs/mailerlite.tsx b/apps/landing/src/pages/vs/mailerlite.tsx index 791557d..da471ed 100644 --- a/apps/landing/src/pages/vs/mailerlite.tsx +++ b/apps/landing/src/pages/vs/mailerlite.tsx @@ -25,7 +25,7 @@ const faqs: FAQ[] = [ { question: 'What is the main difference between Plunk and MailerLite?', answer: - 'The main difference is that Plunk is open-source and self-hostable, while MailerLite is proprietary SaaS. Plunk uses pay-per-email pricing versus MailerLite\'s pay-per-subscriber model. Both are developer-friendly, but Plunk is API-first with full code transparency, while MailerLite focuses more on visual email builders with good API support.', + "The main difference is that Plunk is open-source and self-hostable, while MailerLite is proprietary SaaS. Plunk uses pay-per-email pricing versus MailerLite's pay-per-subscriber model. Both are developer-friendly, but Plunk is API-first with full code transparency, while MailerLite focuses more on visual email builders with good API support.", }, { question: 'Is Plunk more expensive than MailerLite?', @@ -40,12 +40,12 @@ const faqs: FAQ[] = [ { question: 'Does Plunk have a drag-and-drop builder like MailerLite?', answer: - 'Plunk has a basic email editor, but most users manage templates using HTML/code for full control, version control, and reusability. MailerLite excels at visual drag-and-drop building for non-technical users. If you\'re a developer who prefers code-based templates, Plunk is better. If you need rich visual builders for marketers, MailerLite is better.', + "Plunk has a basic email editor, but most users manage templates using HTML/code for full control, version control, and reusability. MailerLite excels at visual drag-and-drop building for non-technical users. If you're a developer who prefers code-based templates, Plunk is better. If you need rich visual builders for marketers, MailerLite is better.", }, { - question: 'How does Plunk\'s API compare to MailerLite?', + question: "How does Plunk's API compare to MailerLite?", answer: - 'Both have modern REST APIs, but Plunk\'s API is designed with developers as the primary user. Plunk prioritizes API-first workflows, making it easier to integrate email into your application. MailerLite has a good API but is built UI-first with API as secondary. For programmatic email sending and automation, Plunk offers a superior developer experience.', + "Both have modern REST APIs, but Plunk's API is designed with developers as the primary user. Plunk prioritizes API-first workflows, making it easier to integrate email into your application. MailerLite has a good API but is built UI-first with API as secondary. For programmatic email sending and automation, Plunk offers a superior developer experience.", }, ]; @@ -58,13 +58,13 @@ export default function MailerliteComparison() { @@ -360,8 +360,8 @@ export default function MailerliteComparison() {

Unlimited Contacts

- Store unlimited contacts without additional cost. Your database grows freely, pricing stays - predictable based on emails sent. + Store unlimited contacts without additional cost. Your database grows freely, pricing stays predictable + based on emails sent.

diff --git a/apps/landing/src/pages/vs/mailgun.tsx b/apps/landing/src/pages/vs/mailgun.tsx index 23ad74a..49cf6fa 100644 --- a/apps/landing/src/pages/vs/mailgun.tsx +++ b/apps/landing/src/pages/vs/mailgun.tsx @@ -53,13 +53,13 @@ export default function MailgunComparison() { diff --git a/apps/landing/src/pages/vs/postmark.tsx b/apps/landing/src/pages/vs/postmark.tsx index 4173766..9a3807f 100644 --- a/apps/landing/src/pages/vs/postmark.tsx +++ b/apps/landing/src/pages/vs/postmark.tsx @@ -54,13 +54,13 @@ export default function PostmarkComparison() { diff --git a/apps/landing/src/pages/vs/resend.tsx b/apps/landing/src/pages/vs/resend.tsx index b055d3a..5f1554c 100644 --- a/apps/landing/src/pages/vs/resend.tsx +++ b/apps/landing/src/pages/vs/resend.tsx @@ -53,13 +53,13 @@ export default function ResendComparison() { diff --git a/apps/landing/src/pages/vs/sendgrid.tsx b/apps/landing/src/pages/vs/sendgrid.tsx index b061467..c346d70 100644 --- a/apps/landing/src/pages/vs/sendgrid.tsx +++ b/apps/landing/src/pages/vs/sendgrid.tsx @@ -57,13 +57,13 @@ export default function SendGridComparison() { diff --git a/apps/web/next-sitemap.config.js b/apps/web/next-sitemap.config.js index 9a9703b..47e4f0d 100644 --- a/apps/web/next-sitemap.config.js +++ b/apps/web/next-sitemap.config.js @@ -1,5 +1,5 @@ /** @type {import('next-sitemap').IConfig} */ module.exports = { - siteUrl: process.env.NEXT_PUBLIC_DASHBOARD_URI || 'https://app.useplunk.com', + siteUrl: process.env.NEXT_PUBLIC_DASHBOARD_URI || 'https://next-app.useplunk.com', generateRobotsTxt: true, }; diff --git a/apps/wiki/app/layout.config.tsx b/apps/wiki/app/layout.config.tsx index ffdc732..14d72a7 100644 --- a/apps/wiki/app/layout.config.tsx +++ b/apps/wiki/app/layout.config.tsx @@ -26,7 +26,7 @@ export const baseOptions: BaseLayoutProps = { { icon: , text: 'Dashboard', - url: 'https://app.useplunk.com', + url: 'https://next-app.useplunk.com', }, { icon: , diff --git a/apps/wiki/app/layout.tsx b/apps/wiki/app/layout.tsx index acd3fc5..1f8b760 100644 --- a/apps/wiki/app/layout.tsx +++ b/apps/wiki/app/layout.tsx @@ -25,23 +25,23 @@ export default function Layout({children}: {children: ReactNode}) { {/* Open Graph / Facebook */} - + - + {/* Twitter */} - + - + {/* Fonts */} diff --git a/apps/wiki/components/api-url.tsx b/apps/wiki/components/api-url.tsx index 45bbe56..056044e 100644 --- a/apps/wiki/components/api-url.tsx +++ b/apps/wiki/components/api-url.tsx @@ -29,7 +29,7 @@ const getRuntimeEnv = (key: keyof NonNullable) => { }; export function ApiUrl({path = ''}: {path?: string}) { - const baseUrl = getRuntimeEnv('API_URI') || process.env.NEXT_PUBLIC_API_URI || 'https://api.useplunk.com'; + const baseUrl = getRuntimeEnv('API_URI') || process.env.NEXT_PUBLIC_API_URI || 'https://next-api.useplunk.com'; return ( {baseUrl} @@ -40,7 +40,7 @@ export function ApiUrl({path = ''}: {path?: string}) { export function DashboardUrl({path = ''}: {path?: string}) { const baseUrl = - getRuntimeEnv('DASHBOARD_URI') || process.env.NEXT_PUBLIC_DASHBOARD_URI || 'https://app.useplunk.com'; + getRuntimeEnv('DASHBOARD_URI') || process.env.NEXT_PUBLIC_DASHBOARD_URI || 'https://next-app.useplunk.com'; return ( {baseUrl} diff --git a/apps/wiki/content/docs/api-reference/errors.mdx b/apps/wiki/content/docs/api-reference/errors.mdx index 32ebad9..39fd6e7 100644 --- a/apps/wiki/content/docs/api-reference/errors.mdx +++ b/apps/wiki/content/docs/api-reference/errors.mdx @@ -303,7 +303,7 @@ Successful API requests return a standardized format with `success: true` and a ```typescript try { - const response = await fetch('https://api.useplunk.com/v1/track', { + const response = await fetch('https://next-api.useplunk.com/v1/track', { method: 'POST', headers: { 'Authorization': `Bearer ${publicKey}`, @@ -361,7 +361,7 @@ try { import requests response = requests.post( - 'https://api.useplunk.com/v1/track', + 'https://next-api.useplunk.com/v1/track', headers={ 'Authorization': f'Bearer {public_key}', 'Content-Type': 'application/json' @@ -426,7 +426,7 @@ Request IDs are included in: ```javascript // Example: Logging request ID in your application -const response = await fetch('https://api.useplunk.com/v1/send', { +const response = await fetch('https://next-api.useplunk.com/v1/send', { // ... your request }); diff --git a/apps/wiki/lib/remark-replace-env.mjs b/apps/wiki/lib/remark-replace-env.mjs index 2a85900..51103c3 100644 --- a/apps/wiki/lib/remark-replace-env.mjs +++ b/apps/wiki/lib/remark-replace-env.mjs @@ -1,24 +1,20 @@ -import { visit } from 'unist-util-visit'; +import {visit} from 'unist-util-visit'; // Default URLs that will be replaced at container startup by sed -const API_URL = process.env.NEXT_PUBLIC_API_URI || 'https://api.useplunk.com'; -const DASHBOARD_URL = process.env.NEXT_PUBLIC_DASHBOARD_URI || 'https://app.useplunk.com'; +const API_URL = process.env.NEXT_PUBLIC_API_URI || 'https://next-api.useplunk.com'; +const DASHBOARD_URL = process.env.NEXT_PUBLIC_DASHBOARD_URI || 'https://next-app.useplunk.com'; export function remarkReplaceEnv() { - return (tree) => { - visit(tree, ['code', 'inlineCode', 'text', 'link'], (node) => { + return tree => { + visit(tree, ['code', 'inlineCode', 'text', 'link'], node => { // Replace in text values if (node.value && typeof node.value === 'string') { - node.value = node.value - .replace(/\{\{API_URL\}\}/g, API_URL) - .replace(/\{\{DASHBOARD_URL\}\}/g, DASHBOARD_URL); + node.value = node.value.replace(/\{\{API_URL\}\}/g, API_URL).replace(/\{\{DASHBOARD_URL\}\}/g, DASHBOARD_URL); } // Replace in link URLs if (node.url && typeof node.url === 'string') { - node.url = node.url - .replace(/\{\{API_URL\}\}/g, API_URL) - .replace(/\{\{DASHBOARD_URL\}\}/g, DASHBOARD_URL); + node.url = node.url.replace(/\{\{API_URL\}\}/g, API_URL).replace(/\{\{DASHBOARD_URL\}\}/g, DASHBOARD_URL); } }); }; diff --git a/apps/wiki/next-sitemap.config.mjs b/apps/wiki/next-sitemap.config.mjs index b910bc4..552e56d 100644 --- a/apps/wiki/next-sitemap.config.mjs +++ b/apps/wiki/next-sitemap.config.mjs @@ -13,7 +13,7 @@ const __dirname = path.dirname(__filename); function findMdxFiles(dir, fileList = []) { const files = fs.readdirSync(dir); - files.forEach((file) => { + files.forEach(file => { const filePath = path.join(dir, file); const stat = fs.statSync(filePath); @@ -46,7 +46,7 @@ function filePathToUrl(filePath) { } const config = { - siteUrl: process.env.NEXT_PUBLIC_WIKI_URI || 'https://docs.useplunk.com', + siteUrl: process.env.NEXT_PUBLIC_WIKI_URI || 'https://next-wiki.useplunk.com', generateRobotsTxt: true, additionalPaths: async () => { const contentDocsPath = path.join(__dirname, 'content', 'docs'); @@ -55,7 +55,7 @@ const config = { const mdxFiles = findMdxFiles(contentDocsPath); // Convert to sitemap entries - return mdxFiles.map((filePath) => ({ + return mdxFiles.map(filePath => ({ loc: filePathToUrl(filePath), changefreq: 'weekly', priority: 0.7, diff --git a/apps/wiki/openapi.json b/apps/wiki/openapi.json index 1423124..695cc09 100644 --- a/apps/wiki/openapi.json +++ b/apps/wiki/openapi.json @@ -6,12 +6,12 @@ "version": "1.0.0", "contact": { "name": "Plunk Support", - "url": "https://useplunk.com" + "url": "https://next.useplunk.com" } }, "servers": [ { - "url": "https://api.useplunk.com", + "url": "https://next-api.useplunk.com", "description": "Production server" } ], @@ -694,7 +694,16 @@ "description": "Array of human-readable reasons describing the verification results" } }, - "required": ["email", "valid", "isDisposable", "isTypo", "isPlusAddressed", "domainExists", "hasMxRecords", "reasons"] + "required": [ + "email", + "valid", + "isDisposable", + "isTypo", + "isPlusAddressed", + "domainExists", + "hasMxRecords", + "reasons" + ] } } }, @@ -711,9 +720,7 @@ "isPlusAddressed": false, "domainExists": true, "hasMxRecords": true, - "reasons": [ - "Email appears to be valid" - ] + "reasons": ["Email appears to be valid"] } } }, @@ -730,10 +737,7 @@ "domainExists": false, "hasMxRecords": false, "suggestedEmail": "user@gmail.com", - "reasons": [ - "Possible typo detected, did you mean gmail.com?", - "Domain does not exist" - ] + "reasons": ["Possible typo detected, did you mean gmail.com?", "Domain does not exist"] } } }, @@ -749,9 +753,7 @@ "isPlusAddressed": false, "domainExists": true, "hasMxRecords": true, - "reasons": [ - "Email appears to be valid" - ] + "reasons": ["Email appears to be valid"] } } } diff --git a/packages/email/src/common/Footer.tsx b/packages/email/src/common/Footer.tsx index 832033d..e127d2e 100644 --- a/packages/email/src/common/Footer.tsx +++ b/packages/email/src/common/Footer.tsx @@ -6,7 +6,7 @@ interface FooterProps { landingUrl?: string; } -export function Footer({projectId, landingUrl = 'https://www.useplunk.com'}: FooterProps) { +export function Footer({projectId, landingUrl = 'https://next.useplunk.com'}: FooterProps) { return (
@@ -22,17 +22,11 @@ export function Footer({projectId, landingUrl = 'https://www.useplunk.com'}: Foo Plunk {' • '} - + Privacy {' • '} - + Terms diff --git a/packages/email/src/emails/BillingLimitExceeded.tsx b/packages/email/src/emails/BillingLimitExceeded.tsx index f5b6023..b8ccfe8 100644 --- a/packages/email/src/emails/BillingLimitExceeded.tsx +++ b/packages/email/src/emails/BillingLimitExceeded.tsx @@ -20,8 +20,8 @@ export function BillingLimitExceededEmail({ usage = 10000, limit = 10000, sourceType = 'Transactional', - dashboardUrl = 'https://app.useplunk.com', - landingUrl = 'https://www.useplunk.com', + dashboardUrl = 'https://next-app.useplunk.com', + landingUrl = 'https://next.useplunk.com', }: BillingLimitExceededEmailProps) { return ( diff --git a/packages/email/src/emails/BillingLimitWarning.tsx b/packages/email/src/emails/BillingLimitWarning.tsx index dfded7e..40698bd 100644 --- a/packages/email/src/emails/BillingLimitWarning.tsx +++ b/packages/email/src/emails/BillingLimitWarning.tsx @@ -22,8 +22,8 @@ export function BillingLimitWarningEmail({ limit = 10000, percentage = 85, sourceType = 'Transactional', - dashboardUrl = 'https://app.useplunk.com', - landingUrl = 'https://www.useplunk.com', + dashboardUrl = 'https://next-app.useplunk.com', + landingUrl = 'https://next.useplunk.com', }: BillingLimitWarningEmailProps) { const percentageRounded = Math.round(percentage); const remaining = limit - usage; diff --git a/packages/email/src/emails/EmailVerification.tsx b/packages/email/src/emails/EmailVerification.tsx index f135130..7d076f1 100644 --- a/packages/email/src/emails/EmailVerification.tsx +++ b/packages/email/src/emails/EmailVerification.tsx @@ -13,7 +13,7 @@ interface EmailVerificationEmailProps { export function EmailVerificationEmail({ email = 'user@example.com', verificationUrl = 'https://api.useplunk.com/auth/verify-email?token=abc123', - landingUrl = 'https://www.useplunk.com', + landingUrl = 'https://next.useplunk.com', }: EmailVerificationEmailProps) { return ( diff --git a/packages/email/src/emails/PasswordReset.tsx b/packages/email/src/emails/PasswordReset.tsx index 7452d76..104c1e8 100644 --- a/packages/email/src/emails/PasswordReset.tsx +++ b/packages/email/src/emails/PasswordReset.tsx @@ -12,17 +12,15 @@ interface PasswordResetEmailProps { export function PasswordResetEmail({ email = 'user@example.com', - resetUrl = 'https://app.useplunk.com/auth/reset-password?token=abc123', - landingUrl = 'https://www.useplunk.com', + resetUrl = 'https://next-app.useplunk.com/auth/reset-password?token=abc123', + landingUrl = 'https://next.useplunk.com', }: PasswordResetEmailProps) { return (
- - Reset your password - + Reset your password We received a request to reset your password. Click the button below to create a new password. diff --git a/packages/email/src/emails/ProjectDisabled.tsx b/packages/email/src/emails/ProjectDisabled.tsx index 66c2cf7..0a47ff2 100644 --- a/packages/email/src/emails/ProjectDisabled.tsx +++ b/packages/email/src/emails/ProjectDisabled.tsx @@ -16,8 +16,8 @@ export function ProjectDisabledEmail({ projectName = 'My Project', projectId = 'proj_example123', violations = ['Bounce rate exceeded 10% threshold', 'Complaint rate exceeded 0.5% threshold'], - dashboardUrl = 'https://app.useplunk.com', - landingUrl = 'https://www.useplunk.com', + dashboardUrl = 'https://next-app.useplunk.com', + landingUrl = 'https://next.useplunk.com', }: ProjectDisabledEmailProps) { return (