Move cloud campaign badge into pricing contract

This commit is contained in:
rcourtman 2026-03-26 22:59:16 +00:00
parent 2dac3bedef
commit 7fd033210c
5 changed files with 13 additions and 6 deletions

View file

@ -504,10 +504,10 @@ while `frontend-modern/src/pages/CloudPricing.tsx`,
and the self-hosted billing settings surfaces must consume those shared owners
instead of redefining retail plan facts or counted-unit policy locally.
That shared ownership also includes display-ready price semantics. Monthly
headline price, founding-rate override, compare-at strike-through copy, and
annual summary text must come from the shared plan-definition owners rather
than page-local string parsing or hardcoded retail amounts inside hosted
pricing/signup screens.
headline price, founding-rate override, compare-at strike-through copy,
campaign badge copy, and annual summary text must come from the shared
plan-definition owners rather than page-local string parsing or hardcoded
retail amounts inside hosted pricing/signup screens.
That same counted-unit boundary also owns the disclosure rule for retail copy:
default billing and pricing surfaces should use concise monitored-system copy,
while the full counted-unit definition appears only behind explicit disclosure

View file

@ -32,10 +32,10 @@ function CloudTierCard(props: { tier: CloudPlanDefinition }) {
: 'relative'
}
>
<Show when={t.highlighted}>
<Show when={price.campaignBadge}>
<div class="absolute right-4 top-4">
<span class="inline-flex items-center rounded-full bg-amber-500 px-2.5 py-1 text-[11px] font-semibold text-white shadow-sm">
Founding rate
{price.campaignBadge}
</span>
</div>
</Show>

View file

@ -24,6 +24,7 @@ describe('CloudPricing', () => {
'href',
'/cloud/signup?tier=starter',
);
expect(screen.getByText('Founding rate')).toBeInTheDocument();
expect(screen.getByText('$19')).toBeInTheDocument();
expect(screen.getByText('$29/month')).toBeInTheDocument();
expect(screen.getByRole('link', { name: 'Choose Power' })).toHaveAttribute(

View file

@ -12,6 +12,7 @@ describe('cloudPlans', () => {
cadence: '/month',
annualSummary: 'or $249/year (save 29%)',
compareAtMonthlyPrice: '$29',
campaignBadge: 'Founding rate',
});
});
@ -21,6 +22,7 @@ describe('cloudPlans', () => {
cadence: '/month',
annualSummary: 'or $449/year (save 24%)',
compareAtMonthlyPrice: undefined,
campaignBadge: undefined,
});
});
});

View file

@ -9,6 +9,7 @@ export interface CloudPlanDefinition {
monitoredSystems: number;
support: 'Community' | 'Priority';
foundingMonthlyPrice?: string;
campaignBadge?: string;
highlighted?: boolean;
}
@ -17,6 +18,7 @@ export interface CloudPlanPricePresentation {
cadence: '/month';
annualSummary: string;
compareAtMonthlyPrice?: string;
campaignBadge?: string;
}
export const DEFAULT_CLOUD_TIER: CloudTierKey = 'starter';
@ -31,6 +33,7 @@ export const CLOUD_PLAN_DEFINITIONS: readonly CloudPlanDefinition[] = [
monitoredSystems: 10,
support: 'Community',
foundingMonthlyPrice: '$19',
campaignBadge: 'Founding rate',
highlighted: true,
},
{
@ -93,5 +96,6 @@ export function getCloudPlanPricePresentation(
cadence: '/month',
annualSummary: plan.annualSummary,
compareAtMonthlyPrice: plan.foundingMonthlyPrice ? plan.monthlyPrice : undefined,
campaignBadge: plan.campaignBadge,
};
}