fix(web): rewrite pricing to match shipped product (honest beta tier)
Some checks failed
CI / Lint (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled

The 6-tier grid was selling features that don't exist yet:
- Pro \$12/mo: dashboard, peer registry, message history (not built)
- Plus \$24/mo: Tailscale mesh (already default), MCP bridge (free),
  audit log (not built)
- Team \$99/mo: \"self-hosted broker\" AND \"25 peers\" AND
  \"unlimited peers\" — three contradictions in one tier
- Business \$499/mo: multi-region, retention, Slack/Linear (roadmap)
- Enterprise: claimed \"SOC 2 pack\" without certification

Replaced with a single Public-Beta card:
- Free, no card required
- Two columns: Shipping today (verified against source) + Roadmap
  v0.2–v0.3 (clearly labeled)
- Promise: \"Beta users keep the free plan for life\"

Non-additive rewrite of a shipped section. Authorized by user
explicitly; required because the prior pricing created refund +
legal risk.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-04-05 23:32:48 +01:00
parent 231618c595
commit ccff802163

View File

@@ -1,64 +1,25 @@
"use client";
import { useState } from "react";
import Link from "next/link"; import Link from "next/link";
import { Reveal, SectionIcon } from "./_reveal"; import { Reveal, SectionIcon } from "./_reveal";
const TIERS = { const SHIPPING = [
individual: [ "CLI + MCP server (Claude Code integration)",
{ "Hosted broker on claudemesh.com",
name: "Solo", "End-to-end encrypted direct messages (crypto_box)",
desc: "Run the broker on your laptop. Pair your Claude Code sessions across repos.", "Priority routing (now / next / low)",
price: "Free", "Mesh invites + membership",
cta: "Start free", "Windows, macOS, Linux support",
href: "/auth/register", ];
},
{ const ROADMAP = [
name: "Pro", "Mesh dashboard (browser UI)",
desc: "Mesh dashboard, peer registry, message history, priority routing.", "Message history + retention controls",
price: "$12", "Audit log",
note: "per month", "Slack / WhatsApp / Telegram gateways",
cta: "Start free trial", "Self-host broker + SSO",
href: "/auth/register", "Cross-broker federation",
}, ];
{
name: "Plus",
desc: "Cross-machine mesh via Tailscale / WireGuard, MCP bridge, audit log.",
price: "$24",
note: "per month",
cta: "Start free trial",
href: "/auth/register",
},
],
team: [
{
name: "Team",
desc: "Self-hosted broker. SSO, shared presence, team audit log, 25 peers.",
price: "$99",
note: "per month · unlimited peers",
cta: "Start free",
href: "/auth/register",
},
{
name: "Business",
desc: "Multi-region brokers, retention controls, Slack/Linear bridges.",
price: "$499",
note: "per month",
cta: "Start free",
href: "/auth/register",
},
{
name: "Enterprise",
desc: "Air-gapped deploy, custom SAML, dedicated support, SOC 2 pack.",
price: "Contact",
cta: "Contact sales",
href: "/contact",
},
],
};
export const Pricing = () => { export const Pricing = () => {
const [tab, setTab] = useState<"individual" | "team">("individual");
const tiers = TIERS[tab];
return ( return (
<section className="border-b border-[var(--cm-border)] bg-[var(--cm-bg)] px-6 py-24 md:px-12 md:py-32"> <section className="border-b border-[var(--cm-border)] bg-[var(--cm-bg)] px-6 py-24 md:px-12 md:py-32">
<div className="mx-auto max-w-[var(--cm-max-w)]"> <div className="mx-auto max-w-[var(--cm-max-w)]">
@@ -73,72 +34,104 @@ export const Pricing = () => {
Get started with claudemesh Get started with claudemesh
</h2> </h2>
</Reveal> </Reveal>
<Reveal delay={2} className="mt-10 flex justify-center"> <Reveal delay={2}>
<div className="inline-flex rounded-[var(--cm-radius-xs)] border border-[var(--cm-border)] bg-[var(--cm-bg-elevated)] p-1"> <p
{(["individual", "team"] as const).map((k) => ( className="mx-auto mt-4 max-w-[520px] text-center text-[15px] leading-[1.6] text-[var(--cm-fg-secondary)]"
<button style={{ fontFamily: "var(--cm-font-sans)" }}
key={k} >
onClick={() => setTab(k)} Free during public beta. The CLI is MIT-licensed. The hosted
className={ broker stays free while the roadmap ships. No billing today.
"rounded-[calc(var(--cm-radius-xs)-2px)] px-4 py-2 text-[13px] font-medium transition-colors " + </p>
(tab === k </Reveal>
? "bg-[var(--cm-fg)] text-[var(--cm-bg)]"
: "text-[var(--cm-fg-secondary)] hover:text-[var(--cm-fg)]") <Reveal delay={3}>
} <div className="mx-auto mt-16 max-w-[720px] rounded-[var(--cm-radius-md)] border border-[var(--cm-border)] bg-[var(--cm-bg-elevated)] p-8 md:p-10">
<div className="mb-6 flex items-baseline justify-between gap-4">
<h3
className="text-[28px] font-medium leading-tight text-[var(--cm-fg)]"
style={{ fontFamily: "var(--cm-font-serif)" }}
>
Public beta
</h3>
<div className="text-right">
<div
className="text-[32px] font-medium text-[var(--cm-fg)]"
style={{ fontFamily: "var(--cm-font-serif)" }}
>
Free
</div>
<div
className="text-xs text-[var(--cm-fg-tertiary)]"
style={{ fontFamily: "var(--cm-font-mono)" }}
>
no card required
</div>
</div>
</div>
<div className="grid gap-8 md:grid-cols-2">
<div>
<div
className="mb-3 text-[10px] uppercase tracking-wider text-[var(--cm-fg-tertiary)]"
style={{ fontFamily: "var(--cm-font-mono)" }}
>
Shipping today
</div>
<ul className="space-y-2">
{SHIPPING.map((item) => (
<li
key={item}
className="flex items-start gap-2 text-[13px] leading-[1.6] text-[var(--cm-fg-secondary)]"
style={{ fontFamily: "var(--cm-font-sans)" }}
>
<span className="mt-[6px] block h-[6px] w-[6px] shrink-0 rounded-full bg-[var(--cm-clay)]" />
<span>{item}</span>
</li>
))}
</ul>
</div>
<div>
<div
className="mb-3 text-[10px] uppercase tracking-wider text-[var(--cm-fg-tertiary)]"
style={{ fontFamily: "var(--cm-font-mono)" }}
>
Roadmap · v0.2v0.3
</div>
<ul className="space-y-2">
{ROADMAP.map((item) => (
<li
key={item}
className="flex items-start gap-2 text-[13px] leading-[1.6] text-[var(--cm-fg-tertiary)]"
style={{ fontFamily: "var(--cm-font-sans)" }}
>
<span className="mt-[6px] block h-[6px] w-[6px] shrink-0 rounded-full border border-[var(--cm-fg-tertiary)]" />
<span>{item}</span>
</li>
))}
</ul>
</div>
</div>
<div className="mt-8 flex flex-col items-start gap-3 border-t border-[var(--cm-border)] pt-6 sm:flex-row sm:items-center sm:justify-between">
<p
className="text-[12px] leading-[1.5] text-[var(--cm-fg-tertiary)]"
style={{ fontFamily: "var(--cm-font-sans)" }} style={{ fontFamily: "var(--cm-font-sans)" }}
> >
{k === "individual" ? "Individual" : "Team & Enterprise"} Paid tiers launch when the dashboard ships. Beta users keep
</button> the free plan for life.
))} </p>
</div> <Link
</Reveal> href="/auth/register"
<Reveal delay={3}> className="inline-flex shrink-0 items-center gap-2 rounded-[var(--cm-radius-xs)] bg-[var(--cm-fg)] px-5 py-2.5 text-sm font-medium text-[var(--cm-bg)] transition-colors hover:bg-[var(--cm-gray-150)]"
<div className="mt-16 grid gap-6 md:grid-cols-3"> style={{ fontFamily: "var(--cm-font-sans)" }}
{tiers.map((tier) => (
<article
key={tier.name}
className="flex flex-col rounded-[var(--cm-radius-md)] border border-[var(--cm-border)] bg-[var(--cm-bg-elevated)] p-8 transition-colors hover:border-[var(--cm-clay)]"
> >
<div className="mb-5"> Start free
<SectionIcon glyph="leaf" /> <span className="transition-transform duration-300 group-hover:translate-x-0.5">
</div>
<h3 </span>
className="mb-2 text-[28px] font-medium leading-tight text-[var(--cm-fg)]" </Link>
style={{ fontFamily: "var(--cm-font-serif)" }} </div>
>
{tier.name}
</h3>
<p
className="mb-6 text-[14px] leading-[1.6] text-[var(--cm-fg-secondary)]"
style={{ fontFamily: "var(--cm-font-serif)" }}
>
{tier.desc}
</p>
<div className="mb-6 mt-auto">
<div
className="text-[32px] font-medium text-[var(--cm-fg)]"
style={{ fontFamily: "var(--cm-font-serif)" }}
>
{tier.price}
</div>
{tier.note && (
<div
className="text-xs text-[var(--cm-fg-tertiary)]"
style={{ fontFamily: "var(--cm-font-mono)" }}
>
{tier.note}
</div>
)}
</div>
<Link
href={tier.href}
className="inline-flex items-center justify-center gap-2 rounded-[var(--cm-radius-xs)] border border-[var(--cm-fg-tertiary)] px-5 py-2.5 text-sm font-medium text-[var(--cm-fg)] transition-colors hover:border-[var(--cm-fg)] hover:bg-[var(--cm-bg)]"
style={{ fontFamily: "var(--cm-font-sans)" }}
>
{tier.cta}
</Link>
</article>
))}
</div> </div>
</Reveal> </Reveal>
</div> </div>