diff --git a/packages/landing/src/lib/platform.ts b/packages/landing/src/lib/platform.ts
new file mode 100644
index 0000000..6eade95
--- /dev/null
+++ b/packages/landing/src/lib/platform.ts
@@ -0,0 +1,15 @@
+/**
+ * Coarse client-side OS detection, shared by the hero's platform-aware download
+ * button and the download page's platform cards. Detection only tunes emphasis
+ * (which label the hero button carries, which card gets badged) — absent or wrong
+ * detection never blocks a download.
+ */
+export type Platform = "mac" | "windows" | "linux";
+
+export function detectPlatform(): Platform | null {
+ const ua = navigator.userAgent;
+ if (/Windows/i.test(ua)) return "windows";
+ if (/Macintosh|Mac OS X/i.test(ua)) return "mac";
+ if (/Linux|X11/.test(ua) && !/Android/i.test(ua)) return "linux";
+ return null;
+}
diff --git a/packages/landing/src/lib/strings-en.ts b/packages/landing/src/lib/strings-en.ts
index a30fadd..53de34d 100644
--- a/packages/landing/src/lib/strings-en.ts
+++ b/packages/landing/src/lib/strings-en.ts
@@ -54,9 +54,14 @@ export const en: Strings = {
titleWords: ["Desktop", "Server"],
titleSuffix: "",
subtitle: "Create Self-Evolving Agents in One Click",
- ctaPrimary: "Get started",
+ /** Primary CTA: base label, and the platform-aware variant once the OS is detected. */
+ downloadCta: "Download the desktop app",
+ downloadCtaFor: (platform: string) => `Download for ${platform}`,
+ ctaQuickstart: "Get started",
ctaGithub: "GitHub",
- installHint: "One-line install (bundled Node runtime — unpack and run)",
+ /** Line under the CTAs: all installers on /download, CLI / self-hosted below the fold. */
+ downloadAll: "All platforms (macOS / Windows / Linux)",
+ cliAlt: "CLI and self-hosted install ↓",
stats: [
{ value: "1000+", label: "supported models" },
{ value: "1×CPU", label: "minimum footprint" },
@@ -80,7 +85,7 @@ export const en: Strings = {
},
offlineRelease: "Download offline packages from GitHub Releases",
desktopNote:
- "Prefer a standalone app? The desktop app packages the Web interface and the server into a terminal-free installer (macOS / Windows / Linux), sharing the same local data as a CLI install.",
+ "Already on the desktop app? A CLI install shares the same local data with it, and the two can be used side by side.",
desktopPage: "Go to the desktop download page",
},
@@ -485,7 +490,8 @@ export const en: Strings = {
title: "Complex AI development, made ever simpler",
subtitle:
"Through continuous evolution, PenguinHarness gives you a more efficient, more reliable, lower-hallucination and lower-cost Agent productivity engine.",
- install: "Install now",
+ download: "Download the desktop app",
+ quickstart: "Get started",
docs: "Read the docs",
},
diff --git a/packages/landing/src/lib/strings.ts b/packages/landing/src/lib/strings.ts
index 07fc4ce..786adb9 100644
--- a/packages/landing/src/lib/strings.ts
+++ b/packages/landing/src/lib/strings.ts
@@ -59,9 +59,14 @@ export const zh = {
titleWords: ["桌面", "服务器"],
titleSuffix: "上",
subtitle: "一键创建自进化 Agent",
- ctaPrimary: "快速开始",
+ /** Primary CTA: base label, and the platform-aware variant once the OS is detected. */
+ downloadCta: "下载桌面版",
+ downloadCtaFor: (platform: string) => `下载桌面版(${platform})`,
+ ctaQuickstart: "快速开始",
ctaGithub: "GitHub",
- installHint: "一行命令安装(内嵌 Node 运行时,解压即用)",
+ /** Line under the CTAs: all installers on /download, CLI / self-hosted below the fold. */
+ downloadAll: "全部平台下载(macOS / Windows / Linux)",
+ cliAlt: "命令行与自托管安装 ↓",
stats: [
{ value: "1000+", label: "支持模型数量" },
{ value: "1×CPU", label: "最低运行配置" },
@@ -70,7 +75,7 @@ export const zh = {
],
},
- /** Install-method switcher (hero + quick start): OS tabs, online/offline methods. */
+ /** Install-method switcher (quick start step 1): OS tabs, online/offline methods. */
install: {
linux: "Linux",
macos: "macOS",
@@ -85,8 +90,7 @@ export const zh = {
windows: "解压后也可直接双击 install.cmd 完成安装。",
},
offlineRelease: "前往 GitHub Releases 下载离线安装包",
- desktopNote:
- "更喜欢独立应用?桌面端把 Web 界面与服务端打包成免终端的安装程序(macOS / Windows / Linux),与 CLI 安装共用同一份本地数据。",
+ desktopNote: "已经装了桌面版?CLI 安装与桌面版共用同一份本地数据,两者可以随时并用。",
desktopPage: "前往桌面端下载页",
},
@@ -475,7 +479,8 @@ export const zh = {
title: "让复杂的 AI 开发越来越简单",
subtitle:
"通过不断进化,PenguinHarness 为你提供更高效、更可靠、更低幻觉、更低成本的 Agent 生产力引擎。",
- install: "立即安装",
+ download: "下载桌面版",
+ quickstart: "快速开始",
docs: "阅读文档",
},
diff --git a/packages/landing/src/pages/download.tsx b/packages/landing/src/pages/download.tsx
index 1ec67cd..f5a7da9 100644
--- a/packages/landing/src/pages/download.tsx
+++ b/packages/landing/src/pages/download.tsx
@@ -23,22 +23,14 @@ import {
OSS_ORIGIN,
RELEASES_URL,
} from "../lib/links";
+import { detectPlatform } from "../lib/platform";
+import type { Platform } from "../lib/platform";
import { Section } from "../components/section";
import { CodeCard } from "../components/code-card";
import { ChevronDownIcon, DownloadIcon, ExternalLinkIcon } from "../components/icons";
-type Platform = "mac" | "windows" | "linux";
const PLATFORMS: Platform[] = ["mac", "windows", "linux"];
-/** Coarse OS detection, used only to badge one card; absent or wrong detection changes nothing else. */
-function detectPlatform(): Platform | null {
- const ua = navigator.userAgent;
- if (/Windows/i.test(ua)) return "windows";
- if (/Macintosh|Mac OS X/i.test(ua)) return "mac";
- if (/Linux|X11/.test(ua) && !/Android/i.test(ua)) return "linux";
- return null;
-}
-
interface Mirror {
tag: string;
base: string;
diff --git a/packages/landing/src/sections/cta.tsx b/packages/landing/src/sections/cta.tsx
index f8ec440..2c86b5f 100644
--- a/packages/landing/src/sections/cta.tsx
+++ b/packages/landing/src/sections/cta.tsx
@@ -1,11 +1,13 @@
-/** Closing call-to-action: the productivity-engine pitch + install / docs buttons. */
+/** Closing call-to-action: the productivity-engine pitch + download / quick start / docs buttons. */
import { Link } from "react-router";
import { S } from "../lib/strings";
import { DOCS_URL } from "../lib/links";
import { Section } from "../components/section";
-import { ArrowRightIcon } from "../components/icons";
+import { DownloadIcon } from "../components/icons";
export function Cta() {
+ const secondary =
+ "inline-flex h-11 items-center rounded-lg border border-gray-200 bg-white px-5 text-sm font-medium text-gray-900 transition-colors hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100 dark:hover:bg-gray-800";
return (
{S.hero.installHint}
-
- {os === "windows" ? ">" : "$"}
-
- {cmd}
-
-
{S.install.desktopNote}{" "}