feat(web): refresh marketing site — accurate timeline, live changelog, cross-boundary positioning
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:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 />
|
||||
|
||||
Reference in New Issue
Block a user