Files
codewhale/web/app/[locale]/page.tsx
T
Hunter B bb4d1e5744 docs(web,readme): taste pass — fix stale refs, tighten design rhythm
Polish fixes (12):
- INSTALL.md: drop duplicate code block; doc CODEWHALE_VERSION canonical
  env var; fix example mirror URLs /DeepSeek-TUI/ → /CodeWhale/; remove
  stale "Once npm publication resumes" conditional
- footer.tsx: fix Gitee mirror URL deepseek-tui → CodeWhale
- globals.css: update seal CSS shadows from old cream rgba(244,241,232)
  to paper white rgba(255,255,255)
- web/README.md: update palette description cream #FAF6EE → white #FFFFFF
- nav.tsx: fix zh-only date strip (第…期) and API label (在线) — now
  "Edition …" / "API · Online" in en mode
- page.tsx: hardcoded v0.8.56 → dynamic facts.version
- README.md: merge duplicate Contributing sections
- README.ja-JP/vi: parenthesize untranslated Chinese thank-you blurbs

Design rhythm (9):
- ThinkingTrace section: py-16→py-20, bg-paper-deep, hairlines for reveal
- Judgment stack: py-16→py-12; middle cell bg-paper-deep for ABA rhythm
- Maintainer loop: py-16→py-14; step numbers grow 01→04
- How it works: py-16→py-12
- Join in closer: py-16→py-20 (dark section breathes)
- Ticker: LIVE label shrunk to annotation weight
2026-06-13 13:55:51 -07:00

606 lines
30 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Link from "next/link";
import { fetchFeed, fetchRepoStats } from "@/lib/github";
import { getDispatch, getEnv } from "@/lib/kv";
import { getFacts } from "@/lib/facts";
import { Ticker } from "@/components/ticker";
import { StatGrid } from "@/components/stat-grid";
import { Seal } from "@/components/seal";
import { ThinkingTrace } from "@/components/thinking-trace";
import { MermaidDiagram } from "@/components/mermaid-diagram";
import type { CuratedDispatch, FeedItem, RepoStats } from "@/lib/types";
export const revalidate = 1800;
const FALLBACK_STATS: RepoStats = {
stars: 0,
forks: 0,
openIssues: 0,
openPulls: 0,
contributors: 141,
fetchedAt: new Date().toISOString(),
};
const RELEASE_CONTRIBUTORS = [
"@cy2311",
"@LING71671",
"@axobase001",
"@dzyuan",
"@mvanhorn",
"@malsony",
"@gaord",
"@yuanchenglu",
"@idling11",
"@h3c-hexin",
"@AdityaVG13",
"@Sskift",
"@cyq1017",
"@HUQIANTAO",
"@New2Niu",
"@AiurArtanis",
"@Lee-take",
"@nightt5879",
"@AresNing",
"@AccMoment",
"@reidliu41",
"@aboimpinto",
"@zhuangbiaowei",
"@donglovejava",
"@hongqitai",
"@zlh124",
"@encyc",
"@Implementist",
"@lihuan215",
"@LeoAlex0",
"@jimmyzhuu",
"@rockyzhang",
"@mo-vic",
"@hufanexplore",
"@hoclaptrinh33",
"@BryonGo",
];
const RELEASE_HELPERS = [
"@buko",
"@yyyCode",
"@gaslebinh-glitch",
"@Dr3259",
"@lpeng1711694086-lang",
"@VerrPower",
"@yan-zay",
"@jretz",
"@Neo-millunnium",
"@caeserchen",
"@T-Phuong-Nguyen",
"@zhyuzhyu",
"@0gl20shk0sbt36",
"@hatakes",
"@goodvecn-dev",
"@bevis-wong",
"@PurplePulse",
"@nbiish",
];
const FALLBACK_DISPATCH_EN: CuratedDispatch = {
generatedAt: new Date().toISOString(),
headline: "Quiet release week — install paths and contributor guides up to date.",
summary:
"This dispatch is regenerated by DeepSeek V4-Flash on a six-hour cron. Until the cron fills in fresh repo activity, the static links below are the best starting points.",
highlights: [
{ title: "Install", href: "/install", tag: "shipped", blurb: "npm, Cargo, Homebrew, or a direct download." },
{ title: "Open issues", href: "https://github.com/Hmbown/CodeWhale/issues", tag: "opened", blurb: "Start with anything labelled good first issue." },
{ title: "Roadmap", href: "/roadmap", tag: "discussion", blurb: "What is confirmed, what is being weighed, what is ruled out." },
],
movers: [],
};
const FALLBACK_DISPATCH_ZH: CuratedDispatch = {
generatedAt: new Date().toISOString(),
headline: "本周发布平稳——安装路径和贡献指南已同步。",
summary:
"本「今日要闻」由 DeepSeek V4-Flash 每六小时重新生成。在 cron 写入真实仓库动态之前,下面的固定链接是最实用的入口。",
highlights: [
{ title: "安装", href: "/zh/install", tag: "shipped", blurb: "npm、Cargo、Homebrew,或直接下载。" },
{ title: "开放议题", href: "https://github.com/Hmbown/CodeWhale/issues", tag: "opened", blurb: "从 good first issue 标签开始。" },
{ title: "路线图", href: "/zh/roadmap", tag: "discussion", blurb: "已确认、审议中、以及已排除的功能。" },
],
movers: [],
};
export default async function HomePage({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
const isZh = locale === "zh";
const env = await getEnv();
const facts = await getFacts();
let stats: RepoStats = FALLBACK_STATS;
let feed: FeedItem[] = [];
let dispatch: CuratedDispatch = isZh ? FALLBACK_DISPATCH_ZH : FALLBACK_DISPATCH_EN;
try {
[stats, feed] = await Promise.all([
fetchRepoStats(env.GITHUB_TOKEN),
fetchFeed(env.GITHUB_TOKEN, 12),
]);
} catch (e) {
console.error("github fetch failed", e);
}
try {
const cached = await getDispatch();
if (cached) dispatch = cached;
} catch {
/* keep fallback */
}
const highlights = isZh && dispatch.highlightsZh ? dispatch.highlightsZh : dispatch.highlights;
return (
<>
<Ticker items={feed} />
{/* HERO */}
<section className="relative">
<div className="mx-auto max-w-[1400px] px-4 sm:px-6 pt-10 sm:pt-14 pb-12 grid lg:grid-cols-12 gap-10">
<div className="lg:col-span-7">
<div className="mb-6">
<span className="pill pill-hot">{isZh ? "开源 · 多模型 · 本地优先" : "Open source · multi-model · local-first"}</span>
</div>
<h1 className="font-display tracking-crisp">
{isZh
? "面向最佳可用模型的终端智能体。"
: "An agentic terminal for the best available models."}
</h1>
<p className="mt-6 text-lg text-ink-soft leading-relaxed max-w-2xl">
<span className="font-cjk text-indigo font-semibold">CodeWhale</span>
{isZh
? " 是社区共建的终端智能体,本地运行,支持你真正在用的模型——GLM、DeepSeek、Kimi、MiniMax、OpenRouter 等等。完整的工具面、审批闸门、快照回滚、子智能体与可恢复会话,都在你的终端里。"
: " is a community-built terminal agent that runs locally and works with the models you actually use — GLM, DeepSeek, Kimi, MiniMax, OpenRouter, and more. A full tool surface, approval gates, snapshots you can roll back, sub-agents, and sessions you can resume."}
</p>
{/* COMMUNITY CALLOUT */}
<div className="mt-6 px-4 py-3 bg-indigo-pale border-l-4 border-indigo text-sm leading-relaxed max-w-2xl">
{isZh ? (
<>
<span className="font-display text-indigo font-semibold mr-1"></span>
PR
</>
) : (
<>
<span className="font-display text-indigo font-semibold mr-1">Built in the open</span>
Community-shaped to bring the best agent harness to the most people. Issues and pull requests are welcome at any experience level.
</>
)}
</div>
<div className="mt-6 flex flex-wrap items-stretch sm:items-center gap-3">
<Link
href={isZh ? "/zh/install" : "/install"}
className="flex-1 sm:flex-none text-center px-5 py-3 bg-ink text-paper font-mono text-sm uppercase tracking-wider hover:bg-indigo transition-colors"
>
{isZh ? "立即安装 →" : "Install →"}
</Link>
<Link
href="https://github.com/Hmbown/CodeWhale"
className="flex-1 sm:flex-none text-center px-5 py-3 hairline-t hairline-b hairline-l hairline-r font-mono text-sm uppercase tracking-wider hover:bg-paper-deep transition-colors"
>
GitHub
</Link>
<Link
href={isZh ? "/zh/docs" : "/docs"}
className="px-5 py-3 font-mono text-sm uppercase tracking-wider text-ink-mute hover:text-indigo transition-colors"
>
{isZh ? "阅读文档" : "Docs"}
</Link>
</div>
<div className="mt-6 flex items-center gap-4 text-xs font-mono text-ink-mute flex-wrap">
<span>{isZh ? "独立维护者 Hmbown" : "Maintained by Hmbown"}</span>
<span className="hidden sm:inline">·</span>
<span>{facts.version ?? "v0.8.x"}</span>
<span className="hidden sm:inline">·</span>
<span>{facts.providers.length} providers</span>
</div>
</div>
<div className="lg:col-span-5">
<div className="hairline-t hairline-b hairline-l hairline-r bg-paper p-5 relative">
<div className="absolute -top-3 left-4 bg-paper px-2 eyebrow">
{isZh ? "一行安装" : "one-line install"}
</div>
<pre className="code-block mt-2">
{isZh ? (
<>
<span className="comment"># npm Rust </span>{"\n"}
<span className="prompt">$</span> npm install -g codewhale{"\n"}
<span className="prompt">$</span> codewhale{"\n"}
<br />
<span className="comment"># Cargo / Homebrew / </span>{"\n"}
<span className="comment"># <span className="key">/install</span></span>
</>
) : (
<>
<span className="comment"># npm no Rust toolchain required</span>{"\n"}
<span className="prompt">$</span> npm install -g codewhale{"\n"}
<span className="prompt">$</span> codewhale{"\n"}
<br />
<span className="comment"># Cargo / Homebrew / direct download:</span>{"\n"}
<span className="comment"># <span className="key">/install</span></span>
</>
)}
</pre>
<div className="mt-3 flex items-center justify-between text-[0.7rem] font-mono text-ink-mute">
<span>{isZh ? "需要 Node 或 Rust 1.88+" : "needs Node or Rust 1.88+"}</span>
<Link href={isZh ? "/zh/install" : "/install"} className="text-indigo hover:underline">{isZh ? "其他方式 →" : "other ways →"}</Link>
</div>
</div>
</div>
</div>
</section>
<StatGrid stats={stats} />
{/* SEE HOW IT DECIDES — real reasoning traces prove the constitution operates */}
<section className="bg-paper-deep hairline-t hairline-b">
<div className="mx-auto max-w-[1400px] px-6 py-20">
<div className="flex items-baseline gap-4 mb-3 hairline-b pb-4">
<Seal char="判" />
<h2 className="font-display">
{isZh ? "看它如何决策" : "See how it decides"}
</h2>
</div>
<p className={`mb-8 text-ink-soft max-w-2xl ${isZh ? "leading-[1.9] tracking-wide" : "text-sm leading-relaxed"}`}>
{isZh
? "别的 Agent 声称自己「对齐」「可信」。CodeWhale 能证明——因为宪法会在模型的推理中现身:它决策时会援引「第 II 条」「第 V 条」。下面是真实会话中的推理摘录,以及它们所促成的决定。"
: "Every agent claims to be aligned and trustworthy. CodeWhale can prove it — the Constitution shows up in the model's reasoning, citing \"Article II\" and \"Article V\" as it decides. These are real traces from an actual session, paired with the decision each produced."}
</p>
<ThinkingTrace locale={locale} />
<div className="mt-6 text-[0.72rem] font-mono uppercase tracking-wider text-ink-mute">
{isZh
? "这些是真实推理的忠实摘录,非杜撰。宪法不是墙上的口号,而是模型决策时真正遵循的顺序。"
: "Faithful excerpts from real reasoning — not invented. The constitution isn't a poster on the wall; it's the order the model actually follows when it decides."}
</div>
</div>
</section>
{/* WHAT IT IS — the core ideas behind the harness */}
<section className="mx-auto max-w-[1400px] px-6 py-12">
<div className="flex items-baseline gap-4 mb-2 hairline-b pb-4">
<Seal char="是" />
<h2 className="font-display">
{isZh ? "判断栈" : "The judgment stack"}
</h2>
</div>
<p className={`mb-8 text-ink-soft max-w-2xl ${isZh ? "leading-[1.9] tracking-wide" : "text-sm leading-relaxed"}`}>
{isZh
? "模型会生成文本;Agent 会留下后果。CodeWhale 把后果需要的结构放在模型外面:自我、权威、证据、工具,各在其位。"
: "A model generates text; an agent leaves consequences. CodeWhale puts the structure for those consequences around the model: self, authority, evidence, and tools, each in its place."}
</p>
<div className="grid md:grid-cols-3 gap-0 col-rule hairline-t hairline-b">
{isZh ? (
<>
<div className="p-6">
<div className="eyebrow mb-3">01 · </div>
<h3 className="font-display text-xl mb-3"></h3>
<p className="text-sm text-ink-soft leading-[1.9]">
Agent
</p>
</div>
<div className="p-6 bg-paper-deep">
<div className="eyebrow mb-3">02 · </div>
<h3 className="font-display text-xl mb-3"></h3>
<p className="text-sm text-ink-soft leading-[1.9]">
Constitution law
</p>
</div>
<div className="p-6">
<div className="eyebrow mb-3">03 · </div>
<h3 className="font-display text-xl mb-3"></h3>
<p className="text-sm text-ink-soft leading-[1.9]">
ShellGitWebMCP Agent runtime
</p>
</div>
</>
) : (
<>
<div className="p-6">
<div className="eyebrow mb-3">01 · self-model</div>
<h3 className="font-display text-xl mb-3">Responsibility needs an address</h3>
<p className="text-sm text-ink-soft leading-relaxed">
The agent is not a model card or leaderboard score. It is an instance in this terminal, this workspace, this session. Give it an address before you ask it to act.
</p>
</div>
<div className="p-6 bg-paper-deep">
<div className="eyebrow mb-3">02 · nested constitution</div>
<h3 className="font-display text-xl mb-3">Conflict has law</h3>
<p className="text-sm text-ink-soft leading-relaxed">
Global Constitution, current user request, runtime statutes, repo-local law, live evidence, memory, personality, and old handoffs each have a rank. When they conflict, the agent has an order to follow.
</p>
</div>
<div className="p-6">
<div className="eyebrow mb-3">03 · local execution</div>
<h3 className="font-display text-xl mb-3">Evidence stays local</h3>
<p className="text-sm text-ink-soft leading-relaxed">
Files, shell, git, web, MCP, sub-agents, rollback, and diagnostics are runtime surfaces. The model does not claim verification as a mood; it has to leave evidence.
</p>
</div>
</>
)}
</div>
<div className="mt-8 hairline-t pt-6 flex flex-wrap items-baseline gap-x-6 gap-y-3">
<div className="eyebrow shrink-0">{isZh ? "内建提供商" : "Built-in providers"}</div>
<div className="flex flex-wrap gap-2">
{facts.providers.map((p) => (
<span key={p.id} className="font-mono text-xs px-2 py-1 hairline-t hairline-b hairline-l hairline-r text-ink-soft">
{p.label}
</span>
))}
</div>
</div>
</section>
{/* MAINTAINER LOOP */}
<section className="bg-paper-deep hairline-t hairline-b">
<div className="mx-auto max-w-[1400px] px-6 py-14">
<div className="grid lg:grid-cols-12 gap-10 items-start">
<div className="lg:col-span-5">
<div className="flex items-baseline gap-4 mb-4">
<Seal char="百" />
<div className="eyebrow">{isZh ? "维护者循环" : "maintainer loop"}</div>
</div>
<h2 className="font-display">
{isZh ? "长任务要能被继承" : "Long work has to be inheritable"}
</h2>
<p className={`mt-5 text-ink-soft ${isZh ? "leading-[1.9] tracking-wide" : "leading-relaxed"}`}>
{isZh
? "难点不是让模型一次做更多事,而是让用户意图、权威顺序、证据和贡献者上下文足够清楚,让下一个维护者可以接住。"
: "The hard part is not making the model do more at once. It is keeping intent, authority, evidence, and contributor context clear enough for the next maintainer to inherit."}
</p>
<p className={`mt-4 text-sm text-ink-mute ${isZh ? "leading-[1.9] tracking-wide" : "leading-relaxed"}`}>
{isZh
? "好的 Agent 工作不是一团活动记录,而是一条可以复核的线:请求、调查、补丁、验证、署名。"
: "Good agent work is not a pile of activity. It is a reviewable line: request, investigation, patch, verification, credit."}
</p>
<p className={`mt-4 text-sm text-ink-soft ${isZh ? "leading-[1.9] tracking-wide" : "leading-relaxed"}`}>
{isZh
? "框架承担了繁重工作:宪政提示、结构化信任、反馈循环、回滚和跨会话存活的交接。模型可以把注意力放在任务本身。"
: "The harness carries the heavy parts: constitutional prompts, structured trust, feedback loops, rollback, and handoffs that survive the session. The model can keep its attention on the task itself."}
</p>
<div className="mt-6 flex flex-wrap gap-3">
<Link href={isZh ? "/zh/docs#constitution" : "/docs#constitution"} className="px-4 py-2 bg-ink text-paper font-mono text-sm uppercase tracking-wider hover:bg-indigo transition-colors">
{isZh ? "阅读宪法 →" : "Read the docs →"}
</Link>
<Link href={isZh ? "/zh/contribute" : "/contribute"} className="px-4 py-2 font-mono text-sm uppercase tracking-wider text-ink-mute hover:text-indigo transition-colors">
{isZh ? "贡献指南 →" : "Contribute →"}
</Link>
</div>
</div>
<div className="lg:col-span-7 hairline-t hairline-b hairline-l hairline-r bg-paper">
<div className="bg-ink text-paper px-4 py-3 flex items-center justify-between gap-4">
<div className="font-mono text-sm uppercase tracking-widest">CodeWhale / review loop</div>
<div className="font-cjk text-sm text-paper-deep/80">{isZh ? "维护者工作流" : "maintainer workflow"}</div>
</div>
<div className="grid sm:grid-cols-2 gap-0 col-rule">
{(isZh
? [
{ n: "01", t: "意图", d: "当前用户请求定义目标、约束和成功标准。" },
{ n: "02", t: "调查", d: "Agent 读取代码、调用工具、必要时分派子 Agent,并保留证据。" },
{ n: "03", t: "补丁", d: "输出保持小、可复现、可测试,并尊重现有分支和贡献者上下文。" },
{ n: "04", t: "审查", d: "维护者看到改变、验证结果、风险和应被感谢的人。" },
]
: [
{ n: "01", t: "Intent", d: "The current user request defines the goal, constraints, and success bar." },
{ n: "02", t: "Investigation", d: "The agent reads code, uses tools, delegates when useful, and keeps the evidence visible." },
{ n: "03", t: "Patch", d: "The output stays small, reproducible, testable, and respectful of branch and contributor context." },
{ n: "04", t: "Review", d: "The maintainer sees what changed, what was verified, what risk remains, and who deserves credit." },
]
).map((item) => (
<div key={item.n} className="p-5">
<div className={`font-mono uppercase tracking-widest mb-2 ${item.n === "01" ? "text-[0.6rem] text-indigo/60" : item.n === "04" ? "text-[0.82rem] text-indigo font-semibold" : "text-[0.7rem] text-indigo"}`}>{item.n}</div>
<h3 className="font-display text-lg mb-2">{item.t}</h3>
<p className={`text-sm text-ink-soft ${isZh ? "leading-[1.9] tracking-wide" : "leading-relaxed"}`}>
{item.d}
</p>
</div>
))}
</div>
</div>
</div>
</div>
</section>
{/* HOW IT WORKS */}
<section className="mx-auto max-w-[1400px] px-6 py-12">
<div className="flex items-baseline gap-4 mb-8 hairline-b pb-4">
<Seal char="作" />
<h2 className="font-display">
{isZh ? "运作方式" : "How it works"}
</h2>
</div>
<div className="hairline-t hairline-b hairline-l hairline-r bg-paper p-4 sm:p-8">
<MermaidDiagram
label={isZh ? "CodeWhale 运作方式示意图" : "CodeWhale architecture diagram"}
chart={
isZh
? `flowchart TD
A["用户输入<br/>(TUI · ratatui)"] -->|Op channel| B["Engine<br/>turn loop + tools"]
B -->|HTTPS / SSE| C["DeepSeek API<br/>V4 family"]
C -->|stream events| B
B -->|tool call| T["read_file · edit_file · grep<br/>apply_patch · exec_shell<br/>mcp_&lt;server&gt;_&lt;tool&gt;"]
T -->|approval Y/N| P["审批对话框<br/>approval dialog"]
P --> B
T -->|exec| S["沙箱<br/>seatbelt · landlock · win32"]
classDef accent fill:#e9eefe,stroke:#0e0e10,stroke-width:1px;
classDef api fill:#0e0e10,stroke:#0e0e10,color:#ffffff;
class C api;
class T,P,S accent;`
: `flowchart TD
A["You type<br/>(TUI · ratatui)"] -->|Op channel| B["Engine<br/>turn loop + tools"]
B -->|HTTPS / SSE| C["DeepSeek API<br/>V4 family"]
C -->|stream events| B
B -->|tool call| T["read_file · edit_file · grep<br/>apply_patch · exec_shell<br/>mcp_&lt;server&gt;_&lt;tool&gt;"]
T -->|approval Y/N| P["Approval<br/>dialog"]
P --> B
T -->|exec| S["Sandbox<br/>seatbelt · landlock · win32"]
classDef accent fill:#e9eefe,stroke:#0e0e10,stroke-width:1px;
classDef api fill:#0e0e10,stroke:#0e0e10,color:#ffffff;
class C api;
class T,P,S accent;`
}
/>
</div>
</section>
{/* TODAY'S DISPATCH — slim editorial column */}
<section className="bg-paper-deep hairline-t hairline-b">
<div className="mx-auto max-w-[1400px] px-6 py-14">
<div className="flex items-end justify-between mb-6 hairline-b pb-4 flex-wrap gap-3">
<div>
<div className="eyebrow mb-2">{isZh ? "今日要闻" : "Today's Dispatch"}</div>
<div className="font-mono text-sm tabular text-ink-mute">
{new Date(dispatch.generatedAt).toISOString().slice(0, 10)}
</div>
</div>
<div className="font-mono text-xs text-ink-mute">DeepSeek V4-Flash · 6h cron</div>
</div>
<article className="grid lg:grid-cols-12 gap-x-10 gap-y-6 max-w-[1100px]">
<h3 className="lg:col-span-12 font-display text-2xl sm:text-3xl leading-tight">
{isZh && dispatch.headlineZh ? dispatch.headlineZh : dispatch.headline}
</h3>
<p className={`lg:col-span-7 text-ink-soft ${isZh ? "leading-[1.9] tracking-wide" : "leading-relaxed"}`}>
{isZh && dispatch.summaryZh ? dispatch.summaryZh : dispatch.summary}
</p>
<ul className="lg:col-span-5 space-y-3">
{highlights.slice(0, 3).map((h, i) => (
<li key={i} className="flex items-baseline gap-3">
<span className="font-mono text-[0.66rem] text-indigo uppercase tracking-widest w-16 shrink-0">
{h.tag}
</span>
<div>
<Link href={h.href} className="body-link font-display text-base leading-snug">
{h.title}
</Link>
<p className={`text-sm text-ink-soft mt-0.5 ${isZh ? "leading-[1.8]" : ""}`}>{h.blurb}</p>
</div>
</li>
))}
</ul>
</article>
<div className="mt-8 hairline-t pt-4">
<Link href={isZh ? "/zh/feed" : "/feed"} className="font-mono text-xs uppercase tracking-wider text-indigo hover:underline">
{isZh ? "全部活动 →" : "All activity →"}
</Link>
</div>
</div>
</section>
{/* RELEASE CREDITS */}
<section className="mx-auto max-w-[1400px] px-6 py-14">
<div className="flex items-baseline gap-4 mb-5 hairline-b pb-4">
<Seal char="谢" />
<div>
<div className="eyebrow mb-2">{isZh ? `v${facts.version} 致谢` : `v${facts.version} credits`}</div>
<h2 className="font-display text-3xl">
{isZh ? "每个补丁和报告都算数" : "Every patch and report counts"}
</h2>
</div>
</div>
<div className="grid lg:grid-cols-12 gap-10">
<div className="lg:col-span-5">
<p className={`text-ink-soft ${isZh ? "leading-[1.9] tracking-wide" : "leading-relaxed"}`}>
{isZh
? "这一版合并和吸收了来自社区的大量工作。完整条目在 CHANGELOG 中;这里保留最新发布的公开致谢入口。"
: "This release merged and harvested a large community tranche. The full notes live in the changelog; this keeps the latest public credit surface easy to find."}
</p>
<Link href="https://github.com/Hmbown/CodeWhale/blob/main/CHANGELOG.md#0856---2026-06-09" className="inline-block mt-4 font-mono text-xs uppercase tracking-wider text-indigo hover:underline">
{isZh ? "查看完整 changelog →" : "Full changelog →"}
</Link>
</div>
<div className="lg:col-span-7 grid gap-6">
<div>
<div className="eyebrow mb-3">{isZh ? "已合并 / 已吸收贡献" : "Merged and harvested contributions"}</div>
<div className="flex flex-wrap gap-2">
{RELEASE_CONTRIBUTORS.map((handle) => (
<Link
key={handle}
href={`https://github.com/${handle.slice(1)}`}
className="font-mono text-xs px-2 py-1 hairline-t hairline-b hairline-l hairline-r text-ink-soft hover:text-indigo hover:bg-paper-deep"
>
{handle}
</Link>
))}
</div>
</div>
<div>
<div className="eyebrow mb-3">{isZh ? "报告、复现和验证" : "Reports, repros, and verification"}</div>
<div className="flex flex-wrap gap-2">
{RELEASE_HELPERS.map((handle) => (
<Link
key={handle}
href={`https://github.com/${handle.slice(1)}`}
className="font-mono text-xs px-2 py-1 hairline-t hairline-b hairline-l hairline-r text-ink-soft hover:text-indigo hover:bg-paper-deep"
>
{handle}
</Link>
))}
</div>
</div>
</div>
</div>
</section>
{/* JOIN IN */}
<section className="bg-ink text-paper">
<div className="mx-auto max-w-[1400px] px-6 py-20 grid lg:grid-cols-12 gap-10 items-center">
<div className="lg:col-span-8">
<div className="eyebrow text-paper-deep/70 mb-3">{isZh ? "加入" : "Join in"}</div>
<h2 className="font-display text-paper text-4xl leading-tight">
{isZh ? "小项目。你的每个补丁都重要。" : "A small project. Your patch matters."}
</h2>
<p className={`mt-5 text-paper-deep/80 max-w-2xl ${isZh ? "leading-[1.9]" : "leading-relaxed"}`}>
{isZh
? "无 CLA,无赞助商优先通道。维护者亲自阅读每一条内容,议题公开分类,版本从 main 分支发布。"
: "No CLA. No sponsor lockouts. The maintainer reads everything personally, issues are triaged in the open, and releases cut from main."}
</p>
<div className="mt-6 flex flex-wrap items-center gap-3">
<Link
href="https://github.com/Hmbown/CodeWhale"
className="px-4 py-2 hairline-t hairline-b hairline-l hairline-r border-white/20 text-paper font-mono text-sm hover:bg-white/10 transition-colors"
>
{isZh ? "Star on GitHub" : "Star on GitHub"}
</Link>
<Link
href={isZh ? "/zh/contribute" : "/contribute"}
className="px-4 py-2 font-mono text-sm text-paper-deep/80 hover:text-paper transition-colors"
>
{isZh ? "参与贡献 →" : "Contribute →"}
</Link>
</div>
</div>
<div className="lg:col-span-4 font-mono text-sm text-paper-deep/80 space-y-2">
<div className="flex justify-between hairline-b border-white/15 pb-2">
<span className="uppercase tracking-widest text-[0.66rem] text-paper-deep/60">{isZh ? "版本" : "version"}</span>
<span className="tabular text-paper">{facts.version ?? "v0.8.x"}</span>
</div>
<div className="flex justify-between hairline-b border-white/15 pb-2">
<span className="uppercase tracking-widest text-[0.66rem] text-paper-deep/60">{isZh ? "提供商" : "providers"}</span>
<span className="tabular text-paper">{facts.providers.length}</span>
</div>
<div className="flex justify-between hairline-b border-white/15 pb-2">
<span className="uppercase tracking-widest text-[0.66rem] text-paper-deep/60">{isZh ? "许可证" : "license"}</span>
<span className="text-paper">{facts.license ?? "MIT"}</span>
</div>
</div>
</div>
</section>
</>
);
}