feat(web): refresh marketing site — accurate timeline, live changelog, cross-boundary positioning
Some checks failed
CI / Typecheck (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled

The site had drifted ~6 months behind the product. Three problems
addressed in one push:

1. Timeline ("Shipped, not promised") topped out at v0.6–0.8 and
   claimed "66 npm releases" — both stale. Adds a v0.9 → 1.34 tier
   covering daemon, multi-mesh, multi-session correctness train,
   refuse-to-kick on control-plane, env-var fallback. Updates count
   to "120+ npm releases through v1.34.15." Rewrites the "next"
   block from the now-shipped "Daemon redesign · per-topic
   encryption" to the actually-pending "HKDF cross-machine identity
   · session capabilities · A2A interop · self-host packaging ·
   federation."

2. Hero subhead leaned into the original "Claude Code peer mesh"
   framing, which is undercut by Anthropic Agent Teams (Feb 2026,
   single-machine native mailbox). Now reframes claudemesh as the
   encrypted backbone where Claude Code sessions, autonomous
   agents, and humans coordinate "across machines, across users,
   across organizations" — the four words that distinguish the
   product from anything Anthropic structurally can ship from
   inside Claude Code.

3. /changelog had three entries from April 2026 (v0.1.2 → v0.1.4)
   and was 70+ versions out of date. Replaced with a curated
   16-entry timeline from v0.1.0 → v1.34.15, hand-picked to tell
   the story (load-bearing ships, not every patch). Adds links
   back to docs/roadmap.md, .artifacts/specs/, and GitHub Releases.

New module: apps/web/src/modules/marketing/home/changelog-data.ts
holds the curated entries as a single source of truth. Imported by
both the /changelog page and a new home-page component
LatestReleases (compact 5-entry strip, slotted between Timeline
and Pricing) so they never disagree.

Misc fixes pulled in:
- timeline.tsx had glyph="layers" which isn't in SectionIcon's
  valid set; switched to "grid" (changelog-data.ts uses same).
- changelog data extracted to a non-route module so Next.js's
  route-export validator stops complaining about exporting
  CHANGELOG_ENTRIES from app/.../changelog/page.tsx.

Pre-existing typecheck noise in packages/ui/web/sidebar.tsx
(csstype version mismatch) + billing modules unrelated to this
change. My files all typecheck clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-05-04 22:55:30 +01:00
parent 7f61a711f1
commit 64d9f9f6f9
6 changed files with 487 additions and 51 deletions

View File

@@ -1,55 +1,161 @@
import Link from "next/link";
import {
CHANGELOG_ENTRIES,
CHANGELOG_TYPE_COLOR,
CHANGELOG_TYPE_LABELS,
} from "~/modules/marketing/home/changelog-data";
export const metadata = {
title: "Changelog — claudemesh",
description: "Release history for claudemesh-cli.",
description:
"Release history for claudemesh-cli — every shipped version, with the why behind it.",
};
const ENTRIES = [
{ version: "0.1.4", date: "2026-04-06", type: "feat", summary: "Stateful welcome screen, PROTOCOL.md, THREAT_MODEL.md, Windows CI matrix" },
{ version: "0.1.3", date: "2026-04-05", type: "feat", summary: "claudemesh --version, status, doctor commands" },
{ version: "0.1.2", date: "2026-04-05", type: "feat", summary: "claudemesh launch command, transparency banner, decrypt fix, Windows support" },
];
const TYPE_LABELS: Record<string, string> = { feat: "Feature", fix: "Fix", docs: "Docs" };
const TYPE_COLORS: Record<string, string> = { feat: "bg-[var(--cm-clay)]", fix: "bg-[var(--cm-cactus)]", docs: "bg-[var(--cm-oat)]" };
export default function ChangelogPage() {
return (
<section className="mx-auto max-w-3xl px-6 py-24 md:py-32">
<h1
className="text-[clamp(2rem,4.5vw,3rem)] font-medium leading-[1.1] text-[var(--cm-fg)]"
style={{ fontFamily: "var(--cm-font-serif)" }}
>
Changelog
</h1>
<p
className="mt-4 text-[15px] text-[var(--cm-fg-secondary)]"
style={{ fontFamily: "var(--cm-font-sans)" }}
>
Every shipped version of claudemesh-cli.
</p>
<div className="mt-12 space-y-8">
{ENTRIES.map((entry) => (
<article key={entry.version} className="border-b border-[var(--cm-border)] pb-6">
<div className="flex items-center gap-3">
<span
className={`rounded-[4px] px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider text-[var(--cm-bg)] ${TYPE_COLORS[entry.type] || "bg-[var(--cm-fg-tertiary)]"}`}
style={{ fontFamily: "var(--cm-font-mono)" }}
>
{TYPE_LABELS[entry.type] || entry.type}
</span>
<span className="text-[18px] font-medium text-[var(--cm-fg)]" style={{ fontFamily: "var(--cm-font-serif)" }}>
v{entry.version}
</span>
<time dateTime={entry.date} className="text-[11px] text-[var(--cm-fg-tertiary)]" style={{ fontFamily: "var(--cm-font-mono)" }}>
{new Date(entry.date).toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric" })}
</time>
</div>
<p className="mt-2 text-[14px] leading-[1.6] text-[var(--cm-fg-secondary)]" style={{ fontFamily: "var(--cm-font-sans)" }}>
{entry.summary}
</p>
</article>
))}
<div className="mb-12">
<p
className="text-[11px] uppercase tracking-[0.2em] text-[var(--cm-fg-tertiary)]"
style={{ fontFamily: "var(--cm-font-mono)" }}
>
claudemesh-cli · release log
</p>
<h1
className="mt-3 text-[clamp(2rem,4.5vw,3rem)] font-medium leading-[1.1] text-[var(--cm-fg)]"
style={{ fontFamily: "var(--cm-font-serif)" }}
>
Changelog
</h1>
<p
className="mt-4 max-w-xl text-[15px] leading-[1.65] text-[var(--cm-fg-secondary)]"
style={{ fontFamily: "var(--cm-font-sans)" }}
>
Hand-picked, load-bearing ships from{" "}
<span className="text-[var(--cm-fg)]">v0.1.0</span> through{" "}
<span className="text-[var(--cm-clay)]">v1.34.15</span>. For the
byte-level diff, the canonical{" "}
<Link
href="https://github.com/alezmad/claudemesh/blob/main/apps/cli/CHANGELOG.md"
className="underline decoration-[var(--cm-fg-tertiary)] underline-offset-4 transition-colors hover:text-[var(--cm-fg)] hover:decoration-[var(--cm-clay)]"
>
CHANGELOG.md
</Link>{" "}
lives in the repo.
</p>
</div>
{/* Vertical timeline rail */}
<div className="relative">
<div
className="absolute left-[7px] top-2 hidden h-full w-px md:block"
style={{
background:
"linear-gradient(to bottom, var(--cm-clay) 0%, var(--cm-fig) 30%, var(--cm-cactus) 60%, transparent 100%)",
}}
/>
<div className="space-y-10">
{CHANGELOG_ENTRIES.map((entry, idx) => (
<article
key={entry.version + entry.date}
className="relative md:pl-10"
>
{/* Dot on rail */}
<div
className="absolute left-0 top-[10px] hidden h-[15px] w-[15px] rounded-full border-2 md:block"
style={{
borderColor: CHANGELOG_TYPE_COLOR[entry.type],
backgroundColor: "var(--cm-bg)",
}}
>
<div
className="absolute inset-[3px] rounded-full"
style={{
backgroundColor: CHANGELOG_TYPE_COLOR[entry.type],
opacity: idx === 0 ? 1 : 0.5,
}}
/>
</div>
<header className="mb-3 flex flex-wrap items-baseline gap-x-3 gap-y-1">
<span
className="rounded-[3px] px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider"
style={{
fontFamily: "var(--cm-font-mono)",
backgroundColor: CHANGELOG_TYPE_COLOR[entry.type],
color: "var(--cm-gray-900)",
}}
>
{CHANGELOG_TYPE_LABELS[entry.type]}
</span>
<span
className="text-[18px] font-medium text-[var(--cm-fg)]"
style={{ fontFamily: "var(--cm-font-serif)" }}
>
v{entry.version}
</span>
<time
dateTime={entry.date}
className="text-[11px] text-[var(--cm-fg-tertiary)]"
style={{ fontFamily: "var(--cm-font-mono)" }}
>
{new Date(entry.date).toLocaleDateString("en-US", {
year: "numeric",
month: "short",
day: "numeric",
})}
</time>
</header>
<h2
className="text-[15px] font-medium text-[var(--cm-fg)]"
style={{ fontFamily: "var(--cm-font-sans)" }}
>
{entry.title}
</h2>
<p
className="mt-2 text-[14px] leading-[1.7] text-[var(--cm-fg-secondary)]"
style={{ fontFamily: "var(--cm-font-sans)" }}
>
{entry.summary}
</p>
</article>
))}
</div>
</div>
<footer className="mt-20 border-t border-[var(--cm-border)] pt-8">
<p
className="text-[13px] text-[var(--cm-fg-tertiary)]"
style={{ fontFamily: "var(--cm-font-sans)" }}
>
Tracked at{" "}
<Link
href="https://github.com/alezmad/claudemesh/blob/main/docs/roadmap.md"
className="underline decoration-[var(--cm-fg-tertiary)] underline-offset-4 transition-colors hover:text-[var(--cm-fg)] hover:decoration-[var(--cm-clay)]"
>
docs/roadmap.md
</Link>
. Specs at{" "}
<Link
href="https://github.com/alezmad/claudemesh/tree/main/.artifacts/specs"
className="underline decoration-[var(--cm-fg-tertiary)] underline-offset-4 transition-colors hover:text-[var(--cm-fg)] hover:decoration-[var(--cm-clay)]"
>
.artifacts/specs/
</Link>
. Tagged binaries on{" "}
<Link
href="https://github.com/alezmad/claudemesh/releases"
className="underline decoration-[var(--cm-fg-tertiary)] underline-offset-4 transition-colors hover:text-[var(--cm-fg)] hover:decoration-[var(--cm-clay)]"
>
GitHub Releases
</Link>
.
</p>
</footer>
</section>
);
}

View File

@@ -3,6 +3,7 @@ import { Features } from "~/modules/marketing/home/features";
import { WhereMeshFits } from "~/modules/marketing/home/where-mesh-fits";
import { WhatIsClaudemesh } from "~/modules/marketing/home/what-is-claudemesh";
import { Timeline } from "~/modules/marketing/home/timeline";
import { LatestReleases } from "~/modules/marketing/home/latest-releases";
import { Pricing } from "~/modules/marketing/home/pricing";
import { FAQ } from "~/modules/marketing/home/faq";
import { CallToAction } from "~/modules/marketing/home/cta";
@@ -22,6 +23,7 @@ const HomePage = () => {
<WhereMeshFits />
<WhatIsClaudemesh />
<Timeline />
<LatestReleases count={5} />
<Pricing />
<FAQ />
<CallToAction />