Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new pricing tier #325

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,194 changes: 1,189 additions & 5 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@gsap/react": "^2.1.1",
"@inkeep/widgets": "^0.2.289",
"@netlify/functions": "^2.8.2",
"@novu/node": "^2.6.5",
"@octokit/rest": "^20.0.2",
"@react-hook/throttle": "^2.2.0",
"@rive-app/canvas": "^2.20.0",
Expand Down Expand Up @@ -55,6 +56,7 @@
"mixpanel-browser": "^2.55.1",
"moment": "^2.30.1",
"node-emojify": "0.0.15",
"novu": "^2.6.5",
"object-hash": "^3.0.0",
"prop-types": "^15.8.1",
"react": "^18.3.1",
Expand Down
2 changes: 1 addition & 1 deletion src/components/pages/pricing/faq/faq.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ const FAQ_DATA = [
{
question: 'Can I use Novu free of charge?',
answer:
'Yes, you can. If you send less than 30K events per month, then Novu Cloud is entirely free. Another option is to deploy the Open-Source version of Novu onto your own infrastructure, but that does not give you the unique SLA and global redundancy we have in the Cloud version of Novu.',
'Yes, you can. If you send less than 10K events per month, then Novu Cloud is entirely free. Another option is to deploy the Open-Source version of Novu onto your own infrastructure, but that does not give you the unique SLA and global redundancy we have in the Cloud version of Novu.',
},
];

Expand Down
63 changes: 19 additions & 44 deletions src/components/pages/pricing/pricing-plans-cards/card/card.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,18 @@ const Card = ({ plan }) => {
} = plan;

const isFree = title.toLowerCase() === 'free';
const isBusiness = title.toLowerCase() === 'business';
const isPro = title.toLowerCase() === 'pro';
const isTeam = title.toLowerCase() === 'team';
const isEnterprise = title.toLowerCase() === 'enterprise';

return (
<li className="relative min-h-[394px] rounded-xl">
<div
className={clsx('relative z-20 h-full overflow-hidden rounded-xl p-6 pb-[30px]', {
'bg-[#111018] bg-[radial-gradient(87.74%_83.27%_at_81.56%_3.42%,_rgba(102,_122,_152,_0.22)_0%,_rgba(102,_122,_152,_0)_88.97%)]':
isFree,
'bg-[#00000033] bg-[linear-gradient(152deg,#0B1122_0.45%,#10101E_98.47%)]': isEnterprise,
'bg-[linear-gradient(152deg,#1F1122_0.45%,#1B1529_98.47%)]': isBusiness,
isPro,
'bg-[#00000033] bg-[linear-gradient(152deg,#0B1122_0.45%,#10101E_98.47%)]':
isTeam || isEnterprise || isFree,
})}
>
<div className="relative z-20">
Expand Down Expand Up @@ -75,39 +76,27 @@ const Card = ({ plan }) => {
>
<CheckIcon
className={clsx('relative left-0.5 top-1 w-3.5 shrink-0 text-gray-8 sm:top-0.5', {
'text-purple-3': isBusiness,
'text-purple-3': isPro,
})}
/>
{item}
</li>
))}
</ul>
</div>
{(isBusiness || isEnterprise) && (
{(isEnterprise || isTeam || isFree) && (
<>
<span
className={clsx(
'pointer-events-none absolute -right-[66px] -top-[101px] h-[240px] w-[280px] rounded-full mix-blend-overlay blur-[32px]',
{
'bg-[#DABCCB]': isBusiness,
'bg-[#BCC3DA] opacity-80': isEnterprise,
}
)}
aria-hidden
/>
<span
className={clsx(
'pointer-events-none absolute -right-[202px] -top-[102px] h-[340px] w-[562px] rounded-full mix-blend-overlay blur-[52px]',
{
'bg-[#DABCD0]': isBusiness,
'bg-[#BCC3DA] opacity-60': isEnterprise,
}
)}
aria-hidden
<img
className="pointer-events-none absolute inset-0 z-10 h-full w-full object-cover object-center"
src={patternBlue}
alt=""
width={656}
height={778}
/>
<BlueShine className="pointer-events-none absolute inset-0 h-full w-full" aria-hidden />
</>
)}
{isBusiness && (
{isPro && (
<>
<PinkShine className="pointer-events-none absolute inset-0 h-full w-full" aria-hidden />
<img
Expand All @@ -119,37 +108,23 @@ const Card = ({ plan }) => {
/>
</>
)}
{isEnterprise && (
<>
<img
className="pointer-events-none absolute inset-0 z-10 h-full w-full object-cover object-center"
src={patternBlue}
alt=""
width={656}
height={778}
/>
<BlueShine className="pointer-events-none absolute inset-0 h-full w-full" aria-hidden />
</>
)}
{hasAdditionalLabel && additionalLabelText && <Label text={additionalLabelText} />}
<GradientBorder
className={clsx({
'border-image-pink-gradient-border': isBusiness,
'border-image-[linear-gradient(246.73deg,rgba(51,51,71,0.6)_15.63%,rgba(43,43,59,0.4)_84.63%)]':
isFree,
'border-image-pink-gradient-border': isPro,
'border-image-[radial-gradient(114.29%_113.4%_at_18.33%_-13.4%,_rgba(209,_213,_250,_0.1)_10.74%,_rgba(82,_83,_122,_0.3)_41.53%,_rgba(168,_148,_209,_0.1)_100%)]':
isEnterprise,
isEnterprise || isTeam || isFree,
})}
aria-hidden
/>
</div>
{isEnterprise && (
{(isEnterprise || isPro || isFree) && (
<span
className="bg-shine pointer-events-none absolute -top-[47px] left-[7px] z-0 h-[277px] w-[391px] rounded-full bg-[radial-gradient(130.45%_66.34%_at_74.29%_61.64%,_#B7C9FF_27.2%,_#96B0FF_80.5%,_#4775FF_100%)] opacity-10 blur-3xl md:hidden"
aria-hidden
/>
)}
{isBusiness && (
{isPro && (
<>
<Shine
className="pointer-events-none absolute -right-3 -top-2.5 z-30 h-[98px] w-[209px]"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React from 'react';
import Card from './card';

const PricingPlanCards = ({ plans }) => (
<ul className="mx-auto mt-[50px] grid max-w-[1024px] auto-rows-max grid-cols-3 items-stretch justify-between gap-5 xl:gap-6 lg:mt-[47px] lg:max-w-[960px] lg:gap-[17px] md:mt-11 md:max-w-[384px] md:grid-cols-1 md:gap-y-[15px] sm:mt-[39px] sm:max-w-[360px] sm:px-5">
<ul className="mx-auto mt-[50px] grid max-w-[1280px] auto-rows-max grid-cols-4 items-stretch justify-between gap-5 xl:gap-6 lg:mt-[47px] lg:max-w-[960px] lg:grid-cols-2 md:mt-11 md:max-w-[384px] md:grid-cols-1 md:gap-y-[15px] sm:mt-[39px] sm:max-w-[360px] sm:px-5">
{plans.map((plan, index) => (
<Card key={index} plan={plan} />
))}
Expand Down
142 changes: 86 additions & 56 deletions src/components/pages/pricing/pricing-table/data/pricing-plans.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,82 @@ const PLANS = {
// FREE TIER
free: {
title: 'Free',
linkText: 'Try Novu',
linkText: 'Start Building',
linkUrl: 'https://dashboard-v2.novu.co/auth/sign-up?utm_campaign=ws_pricing_table_free',
linkTarget: '_blank',
common: {},
platform: {
events: '30k',
monthlyCost: 'Free',
annualCost: 'Free',
events: '10k',
additionalEvents: false,
environments: '2',
environments: false,
maxRPS: '60/20/30 per second',
channels: true,
subscribers: 'Unlimited',
guiWorkflow: true,
codeWorkflow: true,
subscriberManagement: true,
multiTenant: false,
workflows: '20',
providers: 'Unlimited',
feedRetention: '24 hours',
delay: '24 hours',
digest: '24 hours',
stepControl: true,
blockEmailEditor: true,
branding: false,
},
framework: {
workflows: 'Unlimited',
inbox: {
inboxComponent: true,
preferencesComponent: true,
},
account: {
teamMembers: '3',
rbac: false,
standardSAML: true,
customSAML: false,
local: true,
mfa: true,
},
compliance: {
gdpr: true,
soc2: false,
hipaa: false,
customSOC: false,
dpa: 'Standard',
},
},
// PRO TIER
pro: {
title: 'Pro',
linkText: 'Try Now',
linkUrl: 'https://dashboard-v2.novu.co/auth/sign-up?utm_campaign=ws_pricing_table_pro',
linkTarget: '_blank',
common: {},
platform: {
monthlyCost: '$30',
annualCost: '$330',
events: '30k',
additionalEvents: '$1.20 per 1,000',
environments: false,
maxRPS: '240/80/120 per second',
channels: true,
subscribers: 'Unlimited',
guiWorkflow: true,
codeWorkflow: true,
subscriberManagement: true,
workflows: '20',
providers: 'Unlimited',
feedRetention: '30 days',
digest: true,
feedRetention: '7 days',
delay: '7 days',
digest: '7 days',
stepControl: true,
translations: true,
blockEmailEditor: true,
branding: true,
},
inbox: {
inboxComponent: true,
preferencesComponent: true,
bellComponent: true,
notificationsComponent: true,
inboxContentComponent: true,
branding: false,
},
account: {
teamMembers: '3',
Expand All @@ -51,41 +95,37 @@ const PLANS = {
dpa: 'Standard',
},
},
// BUSINESS TIER
business: {
title: 'Business',
linkText: 'Try Novu',
linkUrl: 'https://dashboard-v2.novu.co/auth/sign-up?utm_campaign=ws_pricing_table_business',
// Team TIER
team: {
title: 'Team',
linkText: 'Get Started',
linkUrl: 'https://dashboard-v2.novu.co/auth/sign-up?utm_campaign=ws_pricing_table_team',
linkTarget: '_blank',
common: {},
platform: {
monthlyCost: '$250',
annualCost: '$2,700',
events: '250k',
additionalEvents: '$1.20 per 1,000',
environments: '10',
environments: true,
maxRPS: '600/200/300 per second',
channels: true,
subscribers: `Unlimited`,
subscribers: 'Unlimited',
guiWorkflow: true,
codeWorkflow: true,
subscriberManagement: true,
multiTenant: 'Q1 2025',
},
framework: {
workflows: 'Unlimited',
providers: 'Unlimited',
feedRetention: '90 days',
digest: true,
delay: '90 days',
digest: '90 days',
stepControl: true,
translations: true,
blockEmailEditor: true,
branding: true,
},
inbox: {
inboxComponent: true,
preferencesComponent: true,
bellComponent: true,
notificationsComponent: true,
inboxContentComponent: true,
branding: true,
},
account: {
teamMembers: 'Unlimited',
Expand All @@ -108,35 +148,32 @@ const PLANS = {
title: 'Enterprise',
linkText: 'Contact Us',
linkUrl: 'https://novu.co/contact-us/?utm_campaign=ws_pricing_table_enterprise',
linkTarget: '_blank',
common: {},
platform: {
monthlyCost: 'Contact Us',
annualCost: 'Contact Us',
events: '5 million',
additionalEvents: 'Custom',
environments: 'Unlimited',
environments: true,
maxRPS: '6k/2k/3k per second',
channels: true,
subscribers: `Unlimited`,
subscribers: 'Unlimited',
guiWorkflow: true,
codeWorkflow: true,
subscriberManagement: true,
multiTenant: 'Q1 2025',
},
framework: {
workflows: 'Unlimited',
providers: 'Unlimited',
feedRetention: 'Unlimited',
digest: true,
delay: 'Unlimited',
digest: 'Unlimited',
stepControl: true,
translations: true,
blockEmailEditor: true,
branding: true,
},
inbox: {
inboxComponent: true,
preferencesComponent: true,
bellComponent: true,
notificationsComponent: true,
inboxContentComponent: true,
branding: true,
},
account: {
teamMembers: 'Unlimited',
Expand Down Expand Up @@ -164,43 +201,36 @@ const LABELS = [
{
title: 'Platform',
items: {
monthlyCost: 'Monthly Cost',
annualCost: 'Annual Cost',
events: 'Included monthly events',
additionalEvents: 'Additional events',
environments: 'Environments',
maxRPS: 'Max API Requests (RPS) (Trigger events/Configuration/Global)',
channels: 'Channels supported: email, in-app, SMS, chat, push, and custom',
environments: 'Custom Environments',
maxRPS: 'Max API Requests (RPS)', // (Trigger events/Configuration/Global)
channels: 'Multiple delivery channels',
subscribers: 'Notification Subscribers',
guiWorkflow: 'GUI-based workflows',
codeWorkflow: 'Code-based workflows',
subscriberManagement: 'Subscriber management',
multiTenant: 'Multi-org/Multi-tenancy',
},
},
{
title: 'Novu Framework',
items: {
workflows: 'Maximum Workflows',
providers: 'Provider integrations',
feedRetention: 'Activity Feed retention',
digest: 'Notification Digests',
delay: 'Maximum Delayed Window',
digest: 'Maximum Digest Window',
stepControl: 'Workflow Step Controls',
translations: 'Translations',
blockEmailEditor: 'Block-based email editor',
branding: 'Remove Novu branding',
},
},
{
title: 'Inbox',
items: {
inboxComponent: 'Inbox component',
preferencesComponent: 'User preferences component',
bellComponent: 'Bell component',
notificationsComponent: 'Notifications component',
inboxContentComponent: 'Content component',
branding: 'Remove Novu branding',
},
},
{
title: 'Administration and Security',
title: 'Administration & Security',
items: {
teamMembers: 'Maximum team members',
rbac: 'Role-Based Access Control (RBAC)',
Expand Down
Loading