Remove duplicate hosted commercial copy

This commit is contained in:
rcourtman
2026-03-23 17:41:41 +00:00
parent 72a2a0d119
commit 2bfd76903d
6 changed files with 34 additions and 72 deletions
@@ -327,6 +327,11 @@ deployment internals.
Those same hosted surfaces should also prefer neutral plan-selection and
sign-in language such as `Choose Starter` or `sign-in link` rather than
marketing-heavy CTA copy or infrastructure-specific transport jargon.
They should also avoid duplicating shared commercial facts across multiple
adjacent blocks on the same screen. Common Cloud inclusions belong in one
shared area rather than being restated inside every plan card, and hosted
signup should not repeat the selected plan facts across the page header, form
card, and plan summary at the same time.
That contract applies to both plan summary labels and upgrade/paywall copy:
current v6 self-hosted pricing may not drift back to the older `$49/yr Relay`,
`$99/yr Pro`, or monitored-system-count marketing drift that contradicts the
+11 -45
View File
@@ -15,29 +15,6 @@ const INCLUDED_IN_ALL = [
'Dedicated workspace URL',
];
// ---------------------------------------------------------------------------
// Components
// ---------------------------------------------------------------------------
function FoundingBanner() {
return (
<div class="rounded-lg border border-amber-300 bg-amber-50 px-5 py-4 dark:border-amber-700 dark:bg-amber-950/40">
<div class="flex items-start gap-3">
<span class="text-xl leading-tight">🎉</span>
<div>
<p class="text-sm font-semibold text-amber-900 dark:text-amber-200">
Starter founding rate
</p>
<p class="mt-0.5 text-sm text-amber-800 dark:text-amber-300">
Starter is available at <strong>$19/month</strong> for the first 100 signups. The rate
remains in place while the subscription stays active.
</p>
</div>
</div>
</div>
);
}
function CloudTierCard(props: { tier: CloudPlanDefinition }) {
const t = props.tier;
@@ -53,7 +30,7 @@ function CloudTierCard(props: { tier: CloudPlanDefinition }) {
<Show when={t.highlighted}>
<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
Founding rate
</span>
</div>
</Show>
@@ -74,25 +51,16 @@ function CloudTierCard(props: { tier: CloudPlanDefinition }) {
</Show>
<div class="mt-1 text-sm text-muted">{t.subline}</div>
<ul class="mt-4 space-y-2 text-sm text-base-content">
<li class="flex gap-2">
<span class="shrink-0 text-emerald-600 dark:text-emerald-400 font-bold">
{t.monitoredSystems} monitored systems
</span>
</li>
<li class="flex gap-2">
<span class="text-blue-700 dark:text-blue-300 shrink-0"></span>
<span>{t.support} support</span>
</li>
<li class="flex gap-2">
<span class="text-blue-700 dark:text-blue-300 shrink-0"></span>
<span>All Pro features</span>
</li>
<li class="flex gap-2">
<span class="text-blue-700 dark:text-blue-300 shrink-0"></span>
<span>Managed hosting + daily backups</span>
</li>
</ul>
<dl class="mt-4 space-y-3 text-sm text-base-content">
<div class="flex items-center justify-between gap-3">
<dt class="text-muted">Monitored systems</dt>
<dd class="font-semibold">{t.monitoredSystems}</dd>
</div>
<div class="flex items-center justify-between gap-3">
<dt class="text-muted">Support</dt>
<dd class="font-semibold">{t.support}</dd>
</div>
</dl>
<div class="mt-6">
<A
@@ -122,8 +90,6 @@ export default function CloudPricing() {
description="Managed Pulse hosting with Pro features included."
/>
<FoundingBanner />
{/* Tier cards */}
<div class="grid grid-cols-1 gap-4 md:grid-cols-3">
<For each={CLOUD_PLAN_DEFINITIONS}>{(tier) => <CloudTierCard tier={tier} />}</For>
+9 -16
View File
@@ -117,10 +117,10 @@ export default function HostedSignup() {
if (result.ok) {
setMagicLinkMessage(
result.data.message ||
"If that email is registered, you'll receive a magic link shortly.",
"If that email is registered, you'll receive a sign-in link shortly.",
);
} else {
setMagicLinkMessage(result.error.message || 'Failed to request magic link.');
setMagicLinkMessage(result.error.message || 'Failed to request sign-in link.');
}
} finally {
setRequestingMagicLink(false);
@@ -131,17 +131,12 @@ export default function HostedSignup() {
<div class="space-y-6">
<PageHeader
title={`Pulse Cloud ${selectedPlan().name}`}
description={`${selectedPlan().name} Cloud includes ${selectedPlan().monitoredSystems} monitored systems and ${selectedPlan().support.toLowerCase()} support.`}
description="Create your managed Pulse Cloud workspace."
/>
<div class="grid grid-cols-1 gap-4 lg:grid-cols-2">
<Card padding="lg" class="space-y-4">
<h2 class="text-lg font-semibold text-base-content">
Create {selectedPlan().name} Hosted Workspace
</h2>
<p class="text-sm text-muted">
You&apos;re creating a {selectedPlan().name} Cloud workspace.
</p>
<h2 class="text-lg font-semibold text-base-content">Workspace</h2>
<form class="space-y-3" onSubmit={submitSignup}>
<label class="block text-sm font-medium text-base-content" for="hosted-email">
@@ -177,7 +172,7 @@ export default function HostedSignup() {
class="w-full inline-flex items-center justify-center rounded-md bg-blue-600 px-4 py-2 text-sm font-semibold text-white transition-colors hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-60"
disabled={!canSubmit()}
>
<Show when={status() === 'submitting'} fallback="Create Hosted Workspace">
<Show when={status() === 'submitting'} fallback="Create Workspace">
Creating...
</Show>
</button>
@@ -212,9 +207,7 @@ export default function HostedSignup() {
</Card>
<Card padding="lg" class="space-y-4">
<h2 class="text-lg font-semibold text-base-content">
Plan Summary
</h2>
<h2 class="text-lg font-semibold text-base-content">Plan</h2>
<div class="rounded-md border border-border bg-surface-alt p-4">
<div class="flex items-baseline justify-between gap-3">
<div>
@@ -234,10 +227,10 @@ export default function HostedSignup() {
</div>
</dl>
</div>
<h3 class="text-sm font-semibold text-base-content">After Signup</h3>
<h3 class="text-sm font-semibold text-base-content">Next</h3>
<ol class="list-decimal space-y-2 pl-5 text-sm text-base-content">
<li>Your workspace is created for the {selectedPlan().name} Cloud plan.</li>
<li>You receive a sign-in link by email.</li>
<li>Continue through checkout if prompted.</li>
<li>Finish sign-in from the email link.</li>
<li>Open your workspace and start connecting systems.</li>
</ol>
@@ -32,7 +32,8 @@ describe('CloudPricing', () => {
'href',
'/cloud/signup?tier=max',
);
expect(screen.getByText('Starter founding rate')).toBeInTheDocument();
expect(screen.queryByText('Starter founding rate')).not.toBeInTheDocument();
expect(screen.getAllByText('All Pro features')).toHaveLength(1);
expect(screen.getByText('Setup')).toBeInTheDocument();
expect(
screen.queryByText(/provisioned in under 60 seconds/i),
@@ -40,7 +40,7 @@ describe('HostedSignup', () => {
status: 200,
data: {
success: true,
message: "If that email is registered, you'll receive a magic link shortly.",
message: "If that email is registered, you'll receive a sign-in link shortly.",
},
});
window.history.replaceState({}, '', '/cloud/signup?tier=power');
@@ -58,12 +58,11 @@ describe('HostedSignup', () => {
</Router>
));
expect(await screen.findByText('Create Power Hosted Workspace')).toBeInTheDocument();
expect(screen.getByText(/power cloud includes 30 monitored systems/i)).toBeInTheDocument();
expect(screen.getByText("You're creating a Power Cloud workspace.")).toBeInTheDocument();
expect(screen.getByText('Plan Summary')).toBeInTheDocument();
expect(screen.getByText('After Signup')).toBeInTheDocument();
expect(screen.getByText('You receive a sign-in link by email.')).toBeInTheDocument();
expect(await screen.findByText('Workspace')).toBeInTheDocument();
expect(screen.getByText('Create your managed Pulse Cloud workspace.')).toBeInTheDocument();
expect(screen.getByText('Plan')).toBeInTheDocument();
expect(screen.getByText('Next')).toBeInTheDocument();
expect(screen.getByText('Continue through checkout if prompted.')).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Email Sign-In Link' })).toBeInTheDocument();
fireEvent.input(screen.getByLabelText('Work Email'), {
@@ -72,7 +71,7 @@ describe('HostedSignup', () => {
fireEvent.input(screen.getByLabelText('Organization Name'), {
target: { value: 'Pulse Labs' },
});
fireEvent.submit(screen.getByRole('button', { name: 'Create Hosted Workspace' }).closest('form')!);
fireEvent.submit(screen.getByRole('button', { name: 'Create Workspace' }).closest('form')!);
await waitFor(() => {
expect(signupMock).toHaveBeenCalledWith({
-2
View File
@@ -9,7 +9,6 @@ export interface CloudPlanDefinition {
monitoredSystems: number;
support: 'Community' | 'Priority';
foundingPrice?: string;
foundingLabel?: string;
highlighted?: boolean;
}
@@ -25,7 +24,6 @@ export const CLOUD_PLAN_DEFINITIONS: readonly CloudPlanDefinition[] = [
monitoredSystems: 10,
support: 'Community',
foundingPrice: '$19/month',
foundingLabel: '$19/mo - Founding Member rate (first 100 signups)',
highlighted: true,
},
{