Skip to content
Merged
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
474 changes: 253 additions & 221 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"@headlessui/tailwindcss": "^0.2.2",
"@hookform/resolvers": "^3.3.4",
"@inkeep/cxkit-react": "^0.5.116",
"@next/bundle-analyzer": "^16.1.6",
"@next/bundle-analyzer": "16.3.3",
"@octokit/core": "^6.1.2",
"@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-toast": "^1.2.19",
Expand Down Expand Up @@ -95,7 +95,7 @@
"mdast-util-mdx": "^3.0.0",
"mdast-util-to-markdown": "^2.1.2",
"mermaid": "^11.15.0",
"next": "^16.1.6",
"next": "16.3.3",
"next-mdx-remote": "^6.0.0",
"next-sitemap": "^4.2.3",
"next-themes": "^0.4.6",
Expand Down Expand Up @@ -130,7 +130,7 @@
"@eslint/compat": "^1.2.0",
"@eslint/js": "^9.0.0",
"@neon/sdk": "^2.0.0",
"@next/eslint-plugin-next": "^16.2.1",
"@next/eslint-plugin-next": "16.3.3",
"@playwright/test": "1.61.1",
"@scalar/openapi-parser": "^0.28.2",
"@shikijs/transformers": "^1.3.0",
Expand Down
1 change: 0 additions & 1 deletion public/pricing.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,3 @@ See [Cost optimization](https://neon.com/docs/introduction/cost-optimization.md)
- Get credits for building Open Source on Neon: https://neon.com/programs/open-source.md
- Apply for the Agent Plan (for AI agent platforms): https://neon.com/docs/introduction/agent-plan.md
- More plan details: https://neon.com/docs/introduction/plans.md

17 changes: 10 additions & 7 deletions src/components/pages/pricing/hero/plans/data/plans.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import BACKEND_PRICING from 'constants/backend-pricing';
import LINKS from 'constants/links';

const { objectStorage, functions } = BACKEND_PRICING;

export default [
{
planId: 'free',
Expand Down Expand Up @@ -37,14 +40,14 @@ export default [
features: [
{ title: 'Managed Better Auth', info: 'Up to 60k MAUs' },
{
title: 'Object Storage',
title: `${objectStorage.freeAllowanceGb} GB of Object Storage`,
tag: { label: 'Beta', theme: 'orange-muted' },
info: 'No charges applied during beta, with usage limits',
info: '<p>Measured across your account, not per project</p>',
},
{
title: 'Functions',
tag: { label: 'Beta', theme: 'orange-muted' },
info: 'No charges applied during beta, with usage limits',
info: `<p>${functions.free.activeCapacityHours} active capacity-hours per month</p><p>${functions.free.waitingCapacityHours} waiting capacity-hours per month</p><p>${functions.free.invocations} invocations per month</p>`,
},
],
},
Expand Down Expand Up @@ -91,12 +94,12 @@ export default [
{
title: 'Object Storage',
tag: { label: 'Beta', theme: 'orange-muted' },
info: 'No charges applied during beta, with usage limits',
info: `<p>$${objectStorage.storageRatePerGbMonth} per GB-month</p><p>No charges applied during beta</p>`,
},
{
title: 'Functions',
tag: { label: 'Beta', theme: 'orange-muted' },
info: 'No charges applied during beta, with usage limits',
info: `<p>$${functions.launch.activeCapacityHourRate} per active capacity-hour</p><p>$${functions.launch.waitingCapacityHourRate} per waiting capacity-hour</p><p>$${functions.launch.invocationRatePerMillion} per million invocations</p><p>No charges applied during beta</p>`,
},
{
title: 'AI Gateway',
Expand Down Expand Up @@ -148,12 +151,12 @@ export default [
{
title: 'Object Storage',
tag: { label: 'Beta', theme: 'orange-muted' },
info: 'No charges applied during beta, with usage limits',
info: `<p>$${objectStorage.storageRatePerGbMonth} per GB-month</p><p>No charges applied during beta</p>`,
},
{
title: 'Functions',
tag: { label: 'Beta', theme: 'orange-muted' },
info: 'No charges applied during beta, with usage limits',
info: `<p>$${functions.scale.activeCapacityHourRate} per active capacity-hour</p><p>$${functions.scale.waitingCapacityHourRate} per waiting capacity-hour</p><p>$${functions.scale.invocationRatePerMillion} per million invocations</p><p>No charges applied during beta</p>`,
},
{
title: 'AI Gateway',
Expand Down
70 changes: 63 additions & 7 deletions src/components/pages/pricing/plans/data/plans.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import BACKEND_PRICING from 'constants/backend-pricing';

const { objectStorage, functions } = BACKEND_PRICING;

export default {
headings: {
feature: '',
Expand Down Expand Up @@ -163,20 +167,72 @@ export default {
feature: {
title: 'Object Storage',
tag: { label: 'Beta', theme: 'orange-muted' },
subtitle: 'Stored volume',
},
free: 'No charges applied during beta, with usage limits',
launch: 'No charges applied during beta, with usage limits',
scale: 'No charges applied during beta, with usage limits',
free: `${objectStorage.freeAllowanceGb} GB included`,
launch: `$${objectStorage.storageRatePerGbMonth} per GB-month<span>No charges during beta</span>`,
scale: `$${objectStorage.storageRatePerGbMonth} per GB-month<span>No charges during beta</span>`,
},
{
rows: '2',
fluid: true,
feature: {
title: 'Functions',
tag: { label: 'Beta', theme: 'orange-muted' },
subtitle: 'Compute and invocations',
},
free: {
sections: [
{
title: 'Compute',
details: [
`${functions.free.activeCapacityHours} active capacity-hours`,
`${functions.free.waitingCapacityHours} waiting capacity-hours`,
],
},
{
title: 'Invocations',
details: [`${functions.free.invocations} invocations`],
},
],
},
launch: {
sections: [
{
title: 'Compute',
details: [
`$${functions.launch.activeCapacityHourRate} per active capacity-hour`,
`$${functions.launch.waitingCapacityHourRate} per waiting capacity-hour`,
],
},
{
title: 'Invocations',
details: [`$${functions.launch.invocationRatePerMillion} per 1M invocations`],
},
{
title: 'Charges',
details: ['No charges during beta'],
},
],
},
scale: {
sections: [
{
title: 'Compute',
details: [
`$${functions.scale.activeCapacityHourRate} per active capacity-hour`,
`$${functions.scale.waitingCapacityHourRate} per waiting capacity-hour`,
],
},
{
title: 'Invocations',
details: [`$${functions.scale.invocationRatePerMillion} per 1M invocations`],
},
{
title: 'Charges',
details: ['No charges during beta'],
},
],
},
free: 'No charges applied during beta, with usage limits',
launch: 'No charges applied during beta, with usage limits',
scale: 'No charges applied during beta, with usage limits',
},
{
rows: '2',
Expand Down
34 changes: 31 additions & 3 deletions src/components/pages/pricing/plans/table/table.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,30 @@ const rowClass = {
3: 'h-[92px] xl:h-[108px]',
};

const PricingSections = ({ sections }) => (
<div className="flex flex-col gap-y-7 leading-snug font-normal tracking-extra-tight">
{sections.map(({ title, details }) => (
<div className="flex flex-col gap-y-1" key={title}>
<span className="text-base text-gray-new-80">{title}</span>
{details.map((detail) => (
<span className="text-sm text-gray-new-50" key={detail}>
{detail}
</span>
))}
</div>
))}
</div>
);

PricingSections.propTypes = {
sections: PropTypes.arrayOf(
PropTypes.shape({
title: PropTypes.string.isRequired,
details: PropTypes.arrayOf(PropTypes.string).isRequired,
})
).isRequired,
};

const TableHeading = ({ className, label, price, isLabelsColumn, isFeaturedPlan }) => {
// placeholder for the labels column
if (isLabelsColumn) {
Expand Down Expand Up @@ -86,7 +110,7 @@ const Table = () => {

return (
<li
className={cn('relative pt-6 xl:pt-4', {
className={cn('relative flex flex-col pt-6 xl:pt-4', {
'z-30 flex-1 bg-black-pure lt:min-w-[200px] lg:sticky lg:top-0 lg:left-0 lg:shadow-[8px_18px_20px_0px_rgba(5,5,5,.8)] md:min-w-[180px]':
isLabelsColumn,
'basis-[296px] xl:basis-[252px] lg:shrink-0 lg:basis-[240px]': !isLabelsColumn,
Expand Down Expand Up @@ -114,6 +138,7 @@ const Table = () => {
isGroupTitle
? 'h-[86px] justify-end border-t pb-[18px] lg:h-[66px]'
: ['py-[14px] lg:py-2.5', rowClass[item.rows]],
item.fluid && 'grow',
i === 1 && 'lg:pl-5',
index === 0 && 'border-t-0',
'before:opacity-0',
Expand Down Expand Up @@ -179,8 +204,10 @@ const Table = () => {
<span className="pricing-cross-icon flex size-[14px] bg-gray-new-30" />
);
} else if (typeof item[key] === 'object') {
const { title, info, moreLink } = item[key];
cell = (
const { title, info, moreLink, sections } = item[key];
cell = sections ? (
<PricingSections sections={sections} />
) : (
<div className="leading-snug font-normal tracking-extra-tight">
{title}
{info && (
Expand Down Expand Up @@ -226,6 +253,7 @@ const Table = () => {
rowsWithGroupTitles.includes(index)
? 'h-[86px] lg:h-[66px]'
: ['py-[14px] lg:py-2.5', rowClass[item.rows]],
item.fluid && 'grow',
item[key] !== undefined && !rowsWithGroupTitles.includes(index),
i === arr.length - 1 &&
'before:absolute before:-inset-y-px before:-right-4 before:z-0 before:w-4 before:rounded-tr-lg before:rounded-br-lg before:bg-gray-new-8 before:opacity-0 before:transition-opacity lg:before:hidden'
Expand Down
25 changes: 25 additions & 0 deletions src/constants/backend-pricing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const BACKEND_PRICING = {
objectStorage: {
freeAllowanceGb: '5',
storageRatePerGbMonth: '0.023',
},
functions: {
free: {
activeCapacityHours: '10',
waitingCapacityHours: '400',
invocations: '1M',
},
launch: {
activeCapacityHourRate: '0.10',
waitingCapacityHourRate: '0.025',
invocationRatePerMillion: '0.60',
},
scale: {
activeCapacityHourRate: '0.12',
waitingCapacityHourRate: '0.03',
invocationRatePerMillion: '0.60',
},
},
};

export default BACKEND_PRICING;
Loading
Loading