fix(web): simplify community and mobile docs surfaces

Replace the pre-redesign community ticker, stats, empty dispatch, and duplicate closer with the documentation portal's quieter section grammar. Keep issue and pull-request entry points prominent and preserve the complete current-release contributor ledger.

Collapse the repeated docs index to one mobile return link, add an honest app preview footer link, and apply strict CJK heading line breaking so punctuation does not orphan at narrow reading widths.
This commit is contained in:
Hunter B
2026-07-15 17:33:15 -07:00
parent 2bab145722
commit c268cc3756
5 changed files with 236 additions and 231 deletions
+136 -221
View File
@@ -1,24 +1,7 @@
import Link from "next/link";
import { fetchFeed, fetchRepoStats } from "@/lib/github";
import { getDispatch, getEnv } from "@/lib/kv";
import { getFacts } from "@/lib/facts";
import { buildPageMetadata } from "@/lib/page-meta";
import { Seal } from "@/components/seal";
import { Ticker } from "@/components/ticker";
import { StatGrid } from "@/components/stat-grid";
import { RELEASE_CONTRIBUTORS, RELEASE_HELPERS } from "@/lib/release-credits";
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(),
};
export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
@@ -28,53 +11,81 @@ export async function generateMetadata({ params }: { params: Promise<{ locale: s
locale,
title: isZh ? "社区 · Codewhale" : "Community · Codewhale",
description: isZh
? "Codewhale 的社区一角:实时仓库动态、每周摘要、路线图、贡献指南与发布致谢,集中在一处。"
: "The community side of Codewhale in one place: live repo activity, the weekly digest, the roadmap, how to contribute, and release credits.",
? "了解 Codewhale 的国际开源社区,提交 issue、发送 pull request、改进翻译并查看版本贡献者。"
: "Meet Codewhale's international open-source community, file issues, send pull requests, improve translations, and see release contributors.",
});
}
export default async function CommunityPage({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
const isZh = locale === "zh";
const p = (path: string) => (isZh ? `/zh${path}` : path);
const env = await getEnv();
const p = (path: string) => `/${locale}${path}`;
const facts = await getFacts();
let stats: RepoStats = FALLBACK_STATS;
let feed: FeedItem[] = [];
let dispatch: CuratedDispatch | null = null;
try {
[stats, feed] = await Promise.all([
fetchRepoStats(env.GITHUB_TOKEN),
fetchFeed(env.GITHUB_TOKEN, 12),
]);
} catch (e) {
console.error("github fetch failed", e);
}
try {
dispatch = await getDispatch();
} catch {
/* dispatch stays null; the section falls back to a link */
}
const highlights =
dispatch && isZh && dispatch.highlightsZh ? dispatch.highlightsZh : dispatch?.highlights ?? [];
const hubs = isZh
const contributionPaths = isZh
? [
{ t: "提交问题", d: "报告 bug、兼容性问题或不清楚的行为。请附上系统信息、复现步骤和相关日志。", cta: "提交 issue →", href: "https://github.com/Hmbown/CodeWhale/issues/new/choose", tag: "反馈" },
{ t: "发送改进", d: "修复运行时、测试或文档中的一个具体问题,并提交范围清晰、便于审查的 pull request。", cta: "阅读贡献指南 →", href: p("/contribute"), tag: "代码与文档" },
{ t: "改进翻译", d: "帮助 Codewhale 在更多语言和地区中自然、准确地工作。翻译指南列出了完整语言包与待补项目。", cta: "查看本地化指南 ↗", href: "https://github.com/Hmbown/CodeWhale/blob/main/docs/LOCALIZATION.md", tag: "语言" },
{ t: "跟进项目动态", d: "查看最近的 issues、pull requests、版本路线和经过维护者审核的社区摘要。", cta: "查看动态 →", href: p("/feed"), tag: "动态" },
{
title: "报告问题",
description: "报告 bug、兼容性问题或不清楚的行为,并附上系统信息、复现步骤和可以安全分享的日志。",
cta: "提交 issue →",
href: "https://github.com/Hmbown/CodeWhale/issues/new/choose",
},
{
title: "改进代码或测试",
description: "选择一个范围清晰的问题,提交尽可能小的有效补丁,并添加能够证明行为变化的回归测试。",
cta: "查看开放 issues →",
href: "https://github.com/Hmbown/CodeWhale/issues",
},
{
title: "改进文档或翻译",
description: "修正不准确的说明、补充实际示例,或帮助完成新的语言包,让文档在不同地区都自然准确。",
cta: "查看本地化指南 ↗",
href: "https://github.com/Hmbown/CodeWhale/blob/main/docs/LOCALIZATION.md",
},
{
title: "复现并审查现有工作",
description: "在你的平台和提供商上验证 issue 或 pull request,然后分享你运行的命令、结果和剩余问题。",
cta: "查看 pull requests →",
href: "https://github.com/Hmbown/CodeWhale/pulls",
},
]
: [
{ t: "Report a problem", d: "File a bug, compatibility problem, or unclear behavior. Include your system details, reproduction steps, and relevant logs.", cta: "File an issue →", href: "https://github.com/Hmbown/CodeWhale/issues/new/choose", tag: "feedback" },
{ t: "Send an improvement", d: "Fix one concrete problem in the runtime, tests, or documentation and open a focused pull request that is easy to review.", cta: "Read the contribution guide →", href: p("/contribute"), tag: "code and docs" },
{ t: "Improve a translation", d: "Help Codewhale work naturally and accurately across more languages and regions. The localization guide lists complete packs and open gaps.", cta: "Open the localization guide ↗", href: "https://github.com/Hmbown/CodeWhale/blob/main/docs/LOCALIZATION.md", tag: "language" },
{ t: "Follow project activity", d: "Browse recent issues and pull requests, the public roadmap, and maintainer-reviewed community summaries.", cta: "Open the activity feed →", href: p("/feed"), tag: "activity" },
{
title: "Report a problem",
description: "File a bug, compatibility problem, or unclear behavior with system details, reproduction steps, and any logs you can share safely.",
cta: "File an issue →",
href: "https://github.com/Hmbown/CodeWhale/issues/new/choose",
},
{
title: "Improve code or tests",
description: "Choose one well-bounded problem, make the smallest useful patch, and add a regression test that proves the changed behavior.",
cta: "Browse open issues →",
href: "https://github.com/Hmbown/CodeWhale/issues",
},
{
title: "Improve documentation or translations",
description: "Correct inaccurate guidance, add a practical example, or help complete a language pack so the project reads naturally in more regions.",
cta: "Open the localization guide ↗",
href: "https://github.com/Hmbown/CodeWhale/blob/main/docs/LOCALIZATION.md",
},
{
title: "Reproduce and review existing work",
description: "Verify an issue or pull request with your platform and provider, then share the commands you ran, the result, and any remaining problem.",
cta: "Browse pull requests →",
href: "https://github.com/Hmbown/CodeWhale/pulls",
},
];
const activityLinks = isZh
? [
{ title: "仓库动态", description: "最近的 issues 与 pull requests。", href: p("/feed") },
{ title: "社区摘要", description: "经过维护者审核的每周项目记录。", href: p("/digest") },
{ title: "公开路线图", description: "已发布、正在进行、考虑中和明确不做的工作。", href: p("/roadmap") },
]
: [
{ title: "Repository activity", description: "Recent issues and pull requests.", href: p("/feed") },
{ title: "Community digest", description: "The maintainer-reviewed weekly project record.", href: p("/digest") },
{ title: "Public roadmap", description: "Shipped, underway, considered, and ruled-out work.", href: p("/roadmap") },
];
return (
@@ -86,8 +97,8 @@ export default async function CommunityPage({ params }: { params: Promise<{ loca
<h1>{isZh ? "与世界各地的贡献者一起构建 Codewhale。" : "Build Codewhale with contributors around the world."}</h1>
<p>
{isZh
? "Codewhale 的代码、文档、测试和翻译由不同国家、语言和技术背景的贡献者共同改进。第一次参与不需要从大功能开始:一份清楚的 bug 报告、一处文档修正或一个带测试的小补丁都很有价值。"
: "Codewhale's runtime, documentation, tests, and translations improve through contributors across countries, languages, and technical backgrounds. A first contribution does not need to be a large feature: a clear bug report, a documentation correction, or a small tested patch is useful project work."}
? "Codewhale 的运行时、文档、测试和翻译由不同国家、语言、平台和技术背景的贡献者共同改进。第一次参与不需要从大功能开始清楚的 bug 报告、准确的文档修正或带测试的小补丁都是重要的项目工作。"
: "Codewhale's runtime, documentation, tests, and translations improve through contributors across countries, languages, platforms, and technical backgrounds. A first contribution does not need to be a large feature; a clear bug report, an accurate documentation correction, or a small tested patch is valuable project work."}
</p>
<div className="portal-actions">
<Link href="https://github.com/Hmbown/CodeWhale/issues/new/choose" className="portal-button portal-button-primary">
@@ -96,189 +107,93 @@ export default async function CommunityPage({ params }: { params: Promise<{ loca
<Link href="https://github.com/Hmbown/CodeWhale/pulls" className="portal-button portal-button-secondary">
{isZh ? "查看 pull requests" : "Browse pull requests"}
</Link>
<Link href="https://github.com/Hmbown/CodeWhale/blob/main/docs/LOCALIZATION.md" className="portal-button portal-button-secondary">
{isZh ? "改进翻译" : "Improve a translation"}
<Link href={p("/contribute")} className="portal-button portal-button-secondary">
{isZh ? "阅读贡献指南" : "Read the contribution guide"}
</Link>
</div>
</div>
</section>
{/* live repo activity — the same ticker as the homepage, composed here */}
<Ticker items={feed} />
{/* Direct contribution paths */}
<section className="mx-auto max-w-[1400px] px-6 py-12">
<div className="mb-6 hairline-b pb-4">
<div className="eyebrow mb-2">{isZh ? "现在就可以参与" : "Ways to contribute now"}</div>
<h2 className="font-display">{isZh ? "选择一个具体的切入点。" : "Choose one practical place to start."}</h2>
</div>
<div className="grid md:grid-cols-2 gap-0 col-rule hairline-t hairline-b">
{hubs.map((h) => (
<Link key={h.t} href={h.href} className="block p-6 hover:bg-paper-deep transition-colors">
<div className="flex items-baseline justify-between gap-3 mb-2">
<h3 className="font-display text-xl">{h.t}</h3>
<span className="font-mono text-[0.62rem] uppercase tracking-widest text-indigo shrink-0">{h.tag}</span>
</div>
<p className={`text-sm text-ink-soft mb-4 ${isZh ? "leading-[1.9] tracking-wide" : "leading-relaxed"}`}>
{h.d}
</p>
<span className="font-mono text-[0.7rem] uppercase tracking-widest text-indigo">{h.cta}</span>
</Link>
))}
</div>
</section>
{/* the numbers — same StatGrid as the homepage */}
<StatGrid stats={stats} />
{/* TODAY'S DISPATCH — composed from the same cron-curated source */}
<section className="bg-paper-deep hairline-t hairline-b">
<div className="mx-auto max-w-[1400px] px-6 py-14">
<div className="flex items-baseline gap-4 mb-8 hairline-b pb-4">
<Seal char="讯" />
<h2 className="font-display">{isZh ? "今日要闻" : "Today's dispatch"}</h2>
</div>
{dispatch ? (
<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>
) : (
<p className={`text-ink-soft max-w-2xl ${isZh ? "leading-[1.9] tracking-wide" : "leading-relaxed"}`}>
{isZh ? (
<>
{" "}
<Link href={p("/digest")} className="body-link"></Link>
</>
) : (
<>
While a current dispatch is unavailable, the{" "}
<Link href={p("/digest")} className="body-link">community digest</Link>{" "}
keeps the weekly archive of repository activity.
</>
)}
</p>
)}
</div>
</section>
{/* RELEASE CREDITS — the people behind the current release */}
<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"}`}>
<section className="portal-section">
<div className="portal-container portal-section-grid">
<div className="portal-section-copy">
<span>{isZh ? "参与方式" : "Ways to contribute"}</span>
<h2>{isZh ? "从一个具体、可验证的改进开始。" : "Start with one concrete, verifiable improvement."}</h2>
<p>
{isZh
? "这一版本包含了社区提交的代码、测试、问题复现和审查建议。完整记录保存在 CHANGELOG 和贡献者名单中;即使补丁需要由维护者整理后合入,原作者的贡献也会保留。"
: "This release includes code, tests, reproductions, and review guidance from the community. The changelog and contributor list keep the full record, including credit when a maintainer adapts a patch before it lands."}
? "问题报告、代码、测试、文档、翻译和审查都会推进项目。请选择最适合你当前经验和时间的一种方式。"
: "Issue reports, code, tests, documentation, translations, and review all move the project forward. Choose the path that fits your experience and available time."}
</p>
<div className="flex flex-wrap gap-x-5 gap-y-2 mt-4">
<Link href="https://github.com/Hmbown/CodeWhale/blob/main/docs/CONTRIBUTORS.md" className="font-mono text-xs uppercase tracking-wider text-indigo hover:underline">
{isZh ? "完整贡献者名单 →" : "Full contributor list →"}
</div>
<div className="contribute-path-grid">
{contributionPaths.map((path) => (
<article key={path.title}>
<h3>{path.title}</h3>
<p>{path.description}</p>
<Link href={path.href}>{path.cta}</Link>
</article>
))}
</div>
</div>
</section>
<section className="portal-section portal-section-muted">
<div className="portal-container portal-section-grid">
<div className="portal-section-copy">
<span>{isZh ? "公开项目记录" : "Public project record"}</span>
<h2>{isZh ? "从提案到发布,项目工作保持公开。" : "Follow the repository work from proposal to release."}</h2>
<p>
{isZh
? "动态页面汇总最近的仓库活动,社区摘要保留每周存档,路线图区分已发布的能力与仍在讨论的方向。"
: "The activity feed collects recent repository work, the community digest keeps the weekly archive of repository activity, and the roadmap separates shipped capabilities from work that is still being discussed."}
</p>
</div>
<div className="portal-topic-list">
{activityLinks.map((item) => (
<Link key={item.href} href={item.href}>
<strong>{item.title}</strong>
<span>{item.description}</span>
<span aria-hidden="true"></span>
</Link>
<Link href="https://github.com/Hmbown/CodeWhale/blob/main/CHANGELOG.md" className="font-mono text-xs uppercase tracking-wider text-indigo hover:underline">
CHANGELOG
</Link>
<Link href={p("/contribute")} className="font-mono text-xs uppercase tracking-wider text-indigo hover:underline">
{isZh ? "参与贡献 →" : "Contribute →"}
))}
</div>
</div>
</section>
<section className="portal-section community-credit-section">
<div className="portal-container portal-section-grid">
<div className="portal-section-copy">
<span>{isZh ? `v${facts.version} 版本致谢` : `v${facts.version} release credit`}</span>
<h2>{isZh ? "贡献者署名是版本记录的一部分。" : "Contributor credit is part of the release record."}</h2>
<p>
{isZh
? "这一版本包含社区提交的代码、测试、复现和验证。即使维护者需要调整补丁后再合入,原始贡献者的署名也会保留在提交、更新日志和贡献者名单中。"
: "This release includes code, tests, reproductions, and verification from the community. When a maintainer needs to adapt a patch before it lands, the original contributor remains credited in the commit, changelog, and contributor record."}
</p>
<div className="community-record-links">
<Link href="https://github.com/Hmbown/CodeWhale/blob/main/docs/CONTRIBUTORS.md">
{isZh ? "完整贡献者名单 ↗" : "Full contributor record ↗"}
</Link>
<Link href="https://github.com/Hmbown/CodeWhale/blob/main/CHANGELOG.md">CHANGELOG </Link>
</div>
</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">
<div className="community-credit-groups">
<section>
<h3>{isZh ? "已合并吸收贡献" : "Merged or adapted contributions"}</h3>
<div className="community-credit-list">
{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>
<Link key={handle} href={`https://github.com/${handle.slice(1)}`}>{handle}</Link>
))}
</div>
</div>
<div>
<div className="eyebrow mb-3">{isZh ? "报告、复现验证" : "Reports, repros, and verification"}</div>
<div className="flex flex-wrap gap-2">
</section>
<section>
<h3>{isZh ? "报告、复现验证" : "Reports, reproductions, and verification"}</h3>
<div className="community-credit-list">
{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>
<Link key={handle} href={`https://github.com/${handle.slice(1)}`}>{handle}</Link>
))}
</div>
</div>
</div>
</div>
</section>
{/* JOIN IN — one clear ask, matching the homepage closer */}
<section className="bg-ink text-paper">
<div className="mx-auto max-w-[1400px] px-6 py-16 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-3xl sm:text-4xl leading-tight">
{isZh ? "告诉项目什么有效,什么还需要改进。" : "Tell the project what works and what still needs attention."}
</h2>
<p className={`mt-5 text-paper-deep/80 max-w-2xl ${isZh ? "leading-[1.9]" : "leading-relaxed"}`}>
{isZh
? "如果你遇到 bug、需要一个尚未支持的模型,或发现文档不清楚,请提交 issue。已经有明确改进方案时,也欢迎直接发送带测试的 pull request。"
: "If you hit a bug, need a model that is not supported yet, or find unclear documentation, file an issue. If you already have a focused improvement, a tested pull request is welcome too."}
</p>
<div className="mt-6 flex flex-wrap items-center gap-3">
<Link href="https://github.com/Hmbown/CodeWhale/issues/new" className="px-4 py-2 bg-indigo text-paper font-mono text-sm hover:bg-indigo-deep transition-colors">
{isZh ? "开个 issue →" : "Open an issue →"}
</Link>
<Link href={p("/contribute")} 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 ? "参与贡献 →" : "Contribute →"}
</Link>
<Link href="https://github.com/Hmbown/CodeWhale/discussions" className="px-4 py-2 font-mono text-sm text-paper-deep/80 hover:text-paper transition-colors">
{isZh ? "讨论区 →" : "Discussions →"}
</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>
</section>
</div>
</div>
</section>
+85 -9
View File
@@ -96,6 +96,17 @@ h1 { font-size: clamp(2.25rem, 5vw, 4.75rem); line-height: 0.98; word-break: kee
h2 { font-size: clamp(1.5rem, 2.8vw, 2.6rem); line-height: 1.08; word-break: keep-all; overflow-wrap: anywhere; }
h3 { font-size: 1.18rem; line-height: 1.25; }
/* `overflow-wrap: anywhere` keeps long English headings safe, but can strand
Chinese punctuation on a line of its own. Strict CJK line-breaking keeps
punctuation attached while still allowing breaks between Han characters. */
html[lang="zh"] h1,
html[lang="zh"] h2,
html[lang="zh"] h3 {
line-break: strict;
word-break: normal;
overflow-wrap: break-word;
}
@media (max-width: 640px) {
h1 .font-cjk {
display: inline-block;
@@ -1090,6 +1101,18 @@ a.body-link:hover { background-size: 100% 6px; color: var(--ink); }
font-weight: 600;
}
.docs-sidebar-heading a {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
}
.docs-sidebar-heading a > span:last-child {
color: var(--ink-mute);
font-size: 0.72rem;
}
.docs-sidebar-group {
padding-block: 0.9rem;
border-bottom: 1px solid var(--hairline);
@@ -1295,18 +1318,10 @@ a.body-link:hover { background-size: 100% 6px; color: var(--ink); }
"sidebar";
}
.docs-sidebar nav {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
column-gap: 2rem;
}
.docs-sidebar nav { display: none; }
}
@media (max-width: 640px) {
.docs-sidebar nav {
grid-template-columns: 1fr;
}
.docs-topic-row {
grid-template-columns: minmax(0, 1fr) auto;
gap: 0.6rem 1rem;
@@ -1323,6 +1338,67 @@ a.body-link:hover { background-size: 100% 6px; color: var(--ink); }
}
}
/* ---------- community release record ---------- */
.community-credit-section {
border-bottom: 0;
}
.community-record-links {
display: flex;
flex-wrap: wrap;
gap: 0.65rem 1.25rem;
margin-top: 1.25rem;
}
.community-record-links a {
color: var(--indigo-deep);
font-size: 0.75rem;
font-weight: 600;
}
.community-record-links a:hover {
text-decoration: underline;
text-underline-offset: 0.22rem;
}
.community-credit-groups {
display: grid;
gap: 2rem;
}
.community-credit-groups section {
padding-top: 1rem;
border-top: 1px solid var(--hairline);
}
.community-credit-groups h3 {
margin-bottom: 0.9rem;
color: var(--ink-mute);
font-size: 0.7rem;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.community-credit-list {
display: flex;
flex-wrap: wrap;
gap: 0.45rem;
}
.community-credit-list a {
padding: 0.3rem 0.45rem;
border: 1px solid var(--hairline);
color: var(--ink-soft);
font-family: var(--font-mono), "JetBrains Mono", monospace;
font-size: 0.68rem;
}
.community-credit-list a:hover {
border-color: var(--indigo);
color: var(--indigo-deep);
}
/* ------------------------------------------------------------------ */
/* Dark mode — scoped to the /docs routes */
/* */
+6 -1
View File
@@ -27,7 +27,12 @@ export function DocsSidebar({ locale }: { locale: string }) {
return (
<aside className="docs-sidebar min-w-0">
<div className="lg:sticky lg:top-24">
<div className="docs-sidebar-heading">{isZh ? "文档目录" : "Documentation"}</div>
<div className="docs-sidebar-heading">
<Link href={`/${locale}/docs`}>
<span>{isZh ? "文档目录" : "Documentation"}</span>
<span aria-hidden="true"></span>
</Link>
</div>
<nav aria-label={isZh ? "文档目录" : "Documentation index"}>
{[...byCategory.entries()].map(([category, topics]) => (
<div key={category} className="docs-sidebar-group">
+2
View File
@@ -11,12 +11,14 @@ export function Footer({ locale = "en" }: { locale?: Locale }) {
{ label: "安装", href: "/zh/install" },
{ label: "模型", href: "/zh/models" },
{ label: "运行时", href: "/zh/runtime" },
{ label: "应用预览", href: "https://app.codewhale.net" },
]
: [
{ label: "Docs", href: "/en/docs" },
{ label: "Install", href: "/en/install" },
{ label: "Models", href: "/en/models" },
{ label: "Runtime", href: "/en/runtime" },
{ label: "App preview", href: "https://app.codewhale.net" },
];
const project = isZh
+7
View File
@@ -26,11 +26,15 @@ describe("public website copy contracts", () => {
it("does not rule out the managed app or make it a requirement for local use", () => {
const roadmap = pageSource("roadmap/page.tsx");
const footer = readFileSync(new URL("../components/footer.tsx", import.meta.url), "utf8");
expect(roadmap).toContain("Managed app preview and optional accounts");
expect(roadmap).toContain("Required account for the local runtime");
expect(roadmap).not.toContain("Hosted SaaS dashboard");
expect(roadmap).not.toContain("Required login / accounts");
expect(footer).toContain("App preview");
expect(footer).toContain("https://app.codewhale.net");
expect(footer).not.toMatch(/Create account|Sign up/);
});
it("describes ACP and the VS Code extension at their implemented capability level", () => {
@@ -87,6 +91,9 @@ describe("public website copy contracts", () => {
expect(community).toContain("Hmbown/CodeWhale/pulls");
expect(community).toContain("keeps the weekly archive of repository activity");
expect(community).not.toContain("latest one sits near the top");
expect(community).not.toContain("<Ticker");
expect(community).not.toContain("<StatGrid");
expect(community).not.toContain("Today's dispatch");
});
it("keeps current-release website credits in exact changelog parity", () => {