docs(web): track FAQ route and ignore generated artifacts

This commit is contained in:
Hunter Bown
2026-05-24 03:37:08 -05:00
parent 3e89ccf98e
commit cf08a1e14b
3 changed files with 721 additions and 0 deletions
+2
View File
@@ -61,11 +61,13 @@ count_deps.py
project_overhaul_prompt.md
.codex/
.context/
.wrangler/
# Local runtime state
.deepseek/
**/session_*.json
*.db
npm/*/bin/downloads/
# Companion app (tracked separately)
apps/
+1
View File
@@ -0,0 +1 @@
bin/downloads/
+718
View File
@@ -0,0 +1,718 @@
import Link from "next/link";
import { Seal } from "@/components/seal";
export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
const isZh = locale === "zh";
return {
title: isZh ? "常见问题 · CodeWhale" : "FAQ · CodeWhale",
description: isZh
? "CodeWhale 常见问题:安装、配置、提供商、模型、模式、安全与隐私。答案来自实际代码、文档和 GitHub 议题。"
: "CodeWhale frequently asked questions: install, config, providers, models, modes, security, and privacy. Answers sourced from real code, docs, and GitHub issues.",
};
}
interface FaqItem {
q: string;
a: React.ReactNode;
sources?: string[];
}
const faqEn: FaqItem[] = [
{
q: "What is CodeWhale?",
a: (
<>
CodeWhale is a terminal-native coding agent for open-source and open-weight models. It runs from the <code className="inline">codewhale</code> command, streams reasoning blocks, edits local workspaces with approval gates, and can auto-route each turn to the right model and thinking level. DeepSeek V4 is the first-class model path; OpenRouter is ready. Hugging Face, self-hosted, and other open-model surfaces are on the roadmap.
</>
),
sources: ["README.md", "docs/ARCHITECTURE.md"],
},
{
q: "How do I install CodeWhale?",
a: (
<>
<p className="mb-2">Four paths, same result:</p>
<pre className="code-block mb-2">
{`# npm (recommended — no Rust toolchain needed)
npm install -g codewhale
# Cargo (needs Rust 1.88+)
cargo install codewhale-cli --locked
# Homebrew (macOS)
brew tap Hmbown/deepseek-tui && brew install deepseek-tui
# Direct download
# https://github.com/Hmbown/CodeWhale/releases`}
</pre>
<p>
Run <code className="inline">codewhale</code> to start. First run creates <code className="inline">~/.deepseek/</code> automatically.
See the <Link href="/install" className="body-link">full install guide</Link> for China mirrors, Docker, and troubleshooting.
</p>
</>
),
sources: ["README.md", "#1860", "#1914"],
},
{
q: "What's the difference between codewhale and codewhale-tui?",
a: (
<>
<code className="inline">codewhale</code> is the dispatcher CLI it manages config, auth, updates, and launches the TUI.
<code className="inline">codewhale-tui</code> is the terminal UI binary that runs the agent loop.
When you type <code className="inline">codewhale</code>, the dispatcher spawns <code className="inline">codewhale-tui</code> for you.
Both are installed together; you rarely need to think about the split.
</>
),
sources: ["README.md"],
},
{
q: "Is CodeWhale the same as DeepSeek TUI? What about the rename?",
a: (
<>
Yes. CodeWhale is the new name for what was previously called DeepSeek TUI.
The canonical command is now <code className="inline">codewhale</code>. Legacy <code className="inline">deepseek</code> and <code className="inline">deepseek-tui</code> commands remain as compatibility shims they still work.
Config lives at <code className="inline">~/.deepseek/</code>. <code className="inline">DEEPSEEK_*</code> env vars continue to work.
DeepSeek is not deprecated. The rename reflects CodeWhale's broader mission as the agentic terminal for open models across providers, not a narrowing away from DeepSeek.
</>
),
sources: ["docs/REBRAND.md", "README.md"],
},
{
q: "How do I set my API key?",
a: (
<>
<pre className="code-block mb-2">
{`# Method 1: Environment variable
export DEEPSEEK_API_KEY=sk-...
# Method 2: Saved config (recommended — survives shell restarts)
codewhale auth set --provider deepseek --api-key sk-...
# Method 3: config.toml
# Add to ~/.deepseek/config.toml:
api_key = "sk-..."
# Check what's active:
codewhale auth status # shows config, keyring, and env-var state
codewhale doctor # full connectivity check`}
</pre>
<p>
Saved config keys take precedence over environment variables.
Use <code className="inline">codewhale auth clear --provider deepseek</code> to remove a saved key.
</p>
</>
),
sources: ["#907", "#1545", "docs/CONFIGURATION.md"],
},
{
q: "Which providers does CodeWhale support?",
a: (
<>
<p className="mb-2">CodeWhale ships with these built-in providers:</p>
<ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft mb-3">
<li><strong>DeepSeek</strong> — first-class, native API. Reasoning streaming, cache metrics, thinking effort control.</li>
<li><strong>OpenRouter</strong> — unified API for DeepSeek models and more.</li>
<li><strong>OpenAI</strong>, <strong>NVIDIA NIM</strong>, <strong>Novita</strong>, <strong>Fireworks</strong>, <strong>sglang</strong>, <strong>vLLM</strong>, <strong>Ollama</strong></li>
</ul>
<p>
Set the corresponding env var (e.g. <code className="inline">OPENROUTER_API_KEY</code>) and your provider in <code className="inline">~/.deepseek/config.toml</code>.
Hugging Face, ZenMux, and self-hosted OpenAI-compatible endpoints are on the roadmap.
</p>
</>
),
sources: ["docs/CONFIGURATION.md", "#1978", "#1710"],
},
{
q: "How do I use OpenRouter with CodeWhale?",
a: (
<>
<pre className="code-block mb-2">
{`# 1. Set your OpenRouter key
export OPENROUTER_API_KEY=sk-or-v1-...
# 2. In ~/.deepseek/config.toml:
[providers.openrouter]
api_key = "sk-or-v1-..."
# 3. Run with an OpenRouter model:
codewhale --model openrouter/deepseek/deepseek-v4-pro
# Or set it as default in config.toml:
default_text_model = "openrouter/deepseek/deepseek-v4-pro"`}
</pre>
<p>
OpenRouter uses the same reasoning/cache parser as the native DeepSeek provider.
Model IDs follow the <code className="inline">provider/model-id</code> pattern (e.g. <code className="inline">openrouter/deepseek/deepseek-v4-flash</code>).
</p>
</>
),
sources: ["docs/CONFIGURATION.md", "#1978"],
},
{
q: "Can I use self-hosted or local models (vLLM, Ollama, llama.cpp)?",
a: (
<>
Yes. Use the <code className="inline">vllm</code>, <code className="inline">sglang</code>, or <code className="inline">ollama</code> providers with your local endpoint.
For OpenAI-compatible endpoints (llama.cpp server, text-generation-webui, Aphrodite, etc.), you can use the <code className="inline">openai</code> provider with a custom <code className="inline">base_url</code>.
CodeWhale also respects <code className="inline">DEEPSEEK_ALLOW_INSECURE_HTTP=true</code> for local HTTP endpoints.
Full Hugging Face TGI/vLLM integration is on the roadmap.
</>
),
sources: ["#574", "#1303", "docs/CONFIGURATION.md"],
},
{
q: "What are Plan, Agent, and YOLO modes?",
a: (
<>
<ul className="list-disc pl-5 space-y-2 text-sm text-ink-soft">
<li><strong>Plan</strong> — Read-only investigation. Can grep, read files, list directories, fetch URLs. Cannot write or execute shell.</li>
<li><strong>Agent</strong> — Default mode. Multi-step tool calling. Shell and side-effect tools require approval based on your approval_mode setting.</li>
<li><strong>YOLO</strong> — Auto-approves all operations and enables trust mode. Workspace boundaries lift. Use carefully.</li>
</ul>
<p className="mt-2">
Press <kbd className="font-mono text-xs px-1.5 py-0.5 hairline-t hairline-b hairline-l hairline-r">Tab</kbd> to cycle modes.
Approval mode (suggest / auto / never) is orthogonal — you can be in Agent mode with auto-approval, for example.
</p>
</>
),
sources: ["docs/MODES.md"],
},
{
q: "What is model auto-routing? What is Fin?",
a: (
<>
<p className="mb-2">
Use <code className="inline">codewhale --model auto</code> or <code className="inline">/model auto</code> to let CodeWhale decide how much model power each turn needs.
</p>
<p className="mb-2">
<strong>Fin</strong> is the fast non-thinking path (<code className="inline">deepseek-v4-flash</code> with thinking off) used for routing decisions, summaries, RLM children, context maintenance, and other coordination work. Before the real turn is sent, Fin makes a small routing call to pick the concrete model and thinking level.
</p>
<p>
Short/simple turns can stay on Flash with thinking off. Coding, debugging, release work, architecture, or security review can move up to Pro and/or higher thinking. Fin is local to CodeWhale — the upstream API never receives <code className="inline">model: "auto"</code>.
</p>
</>
),
sources: ["README.md", "#1207"],
},
{
q: "What is Goal mode? Is it available?",
a: (
<>
Goal mode is a future workflow/tab direction for long-running, multi-step objectives — not the current <code className="inline">/goal</code> command.
The current <code className="inline">/goal</code> is a simple goal-setter. The full Goal mode (autonomous multi-turn task execution with checkpoint/resume) is planned but not yet implemented.
Track progress in <a href="https://github.com/Hmbown/CodeWhale/issues/891" className="body-link">#891</a>.
</>
),
sources: ["#891"],
},
{
q: "Is my code safe? What sandboxing does CodeWhale use?",
a: (
<>
CodeWhale runs entirely on your machine. No telemetry, no cloud processing of your code.
Sandbox backends: <strong>seatbelt</strong> (macOS), <strong>landlock</strong> (Linux), restricted tokens (Windows).
Workspace boundaries default to <code className="inline">--workspace</code>. <code className="inline">/trust</code> lifts them.
Approval mode is configurable per session. All credential/approval/elevation events are written to <code className="inline">~/.deepseek/audit.log</code>.
</>
),
sources: ["SECURITY.md", "docs/ARCHITECTURE.md"],
},
{
q: "How do MCP servers work?",
a: (
<>
CodeWhale is a bidirectional MCP client and server. Define servers in <code className="inline">~/.deepseek/mcp.json</code>.
Tools appear as <code className="inline">mcp_&lt;server&gt;_&lt;tool&gt;</code>. You can also expose CodeWhale as an MCP server with <code className="inline">codewhale mcp</code>.
See the <Link href="/docs#mcp" className="body-link">docs page</Link> for configuration examples.
</>
),
sources: ["docs/MCP.md"],
},
{
q: "How do I contribute?",
a: (
<>
No CLA required. Fork, branch with conventional commits (<code className="inline">feat:</code>, <code className="inline">fix:</code>, etc.), run the local checks, open a PR.
The maintainer reads everything personally. Start with issues labeled <code className="inline">good first issue</code>.
See the <Link href="/contribute" className="body-link">contribute page</Link> and <a href="https://github.com/Hmbown/CodeWhale/blob/main/CONTRIBUTING.md" className="body-link">CONTRIBUTING.md</a>.
</>
),
sources: ["CONTRIBUTING.md"],
},
{
q: "I'm in China — how do I install? Downloads are slow.",
a: (
<>
Use mirror registries:
<pre className="code-block my-2">
{`# npm mirror
npm config set registry https://registry.npmmirror.com
npm install -g codewhale
# Cargo mirror (Tsinghua TUNA)
# Add to ~/.cargo/config.toml:
[source.crates-io]
replace-with = "tuna"
[source.tuna]
registry = "sparse+https://mirrors.tuna.tsinghua.edu.cn/crates.io-index/"`}
</pre>
<p>
Prebuilt binaries are also available from <a href="https://github.com/Hmbown/CodeWhale/releases" className="body-link">GitHub Releases</a>.
The Gitee mirror and CNB mirror may also be available.
</p>
</>
),
sources: ["README.md", "#1914", "docs/CNB_MIRROR.md"],
},
{
q: "My API key was rejected or I get auth errors on first run.",
a: (
<>
<p className="mb-2">Run <code className="inline">codewhale doctor</code> — it checks API key, network, sandbox, and MCP servers. Full report is written to <code className="inline">~/.deepseek/doctor.log</code>.</p>
<p className="mb-2">Common causes:</p>
<ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft">
<li>Stale <code className="inline">DEEPSEEK_API_KEY</code> in shell startup file — open a fresh shell or use <code className="inline">codewhale auth set</code></li>
<li>Key from wrong provider — make sure the key matches the provider you're using</li>
<li>Network connectivity — check <code className="inline">curl https://api.deepseek.com/v1/models</code></li>
</ul>
</>
),
sources: ["#907", "#1545"],
},
{
q: "What is Model Lab? When will Hugging Face integration be available?",
a: (
<>
Model Lab is the planned open-model infrastructure layer: Hugging Face Hub API for model discovery, model cards, datasets, safetensors adapters, inference providers, and Jobs.
It is NOT fully implemented. Track progress in <a href="https://github.com/Hmbown/CodeWhale/issues/1977" className="body-link">#1977</a>.
Currently, you can use Hugging Face models through the OpenRouter provider or self-hosted endpoints.
</>
),
sources: ["#1977", "docs/MODEL_LAB.md"],
},
{
q: "Why is token consumption so high? / Why is cache hit rate low?",
a: (
<>
CodeWhale sends substantial context (system prompt, project instructions, tool definitions) with each turn.
DeepSeek's prefix cache is used aggressively — the system prompt is layered to maximize cache hits.
If you see high token usage, check: are you using <code className="inline">deepseek-v4-pro</code> for simple queries better suited to Flash?
Model auto-routing (Fin) can help pick the right model per turn.
Cache hit rate depends on prompt stability — modifying the system prompt or switching models resets the cache.
</>
),
sources: ["#1177", "#1818", "#743"],
},
{
q: "How do I update CodeWhale?",
a: (
<>
<pre className="code-block mb-2">
{`# Release-binary updater (works for npm/release-binary installs)
codewhale update
# npm
npm install -g codewhale@latest
# Cargo
cargo install codewhale-cli --locked --force
# Homebrew
brew update && brew upgrade deepseek-tui`}
</pre>
<p>
If you installed via npm, <code className="inline">codewhale update</code> downloads the latest release binaries.
If a mirror is lagging, download directly from <a href="https://github.com/Hmbown/CodeWhale/releases" className="body-link">GitHub Releases</a>.
</p>
</>
),
sources: ["README.md", "#1869", "#1914"],
},
];
const faqZh: FaqItem[] = [
{
q: "CodeWhale 是什么?",
a: (
<>
CodeWhale 是一个面向开源模型的终端原生编程智能体。通过 <code className="inline">codewhale</code> 命令启动,流式输出推理块,在有审批门槛的情况下编辑本地工作区,并可为每个回合自动选择最合适的模型和推理深度。DeepSeek V4 是一级模型路径;OpenRouter 已就绪。Hugging Face、自托管等开放模型接口已在路线图中。
</>
),
sources: ["README.md", "docs/ARCHITECTURE.md"],
},
{
q: "如何安装 CodeWhale",
a: (
<>
<p className="mb-2">四种方式,殊途同归:</p>
<pre className="code-block mb-2">
{`# npm Rust
npm install -g codewhale
# Cargo Rust 1.88+
cargo install codewhale-cli --locked
# HomebrewmacOS
brew tap Hmbown/deepseek-tui && brew install deepseek-tui
#
# https://github.com/Hmbown/CodeWhale/releases`}
</pre>
<p>
<code className="inline">codewhale</code> <code className="inline">~/.deepseek/</code>
<Link href="/zh/install" className="body-link"></Link> Docker
</p>
</>
),
sources: ["README.md", "#1860", "#1914"],
},
{
q: "codewhale 和 codewhale-tui 有什么区别?",
a: (
<>
<code className="inline">codewhale</code> CLI TUI
<code className="inline">codewhale-tui</code> UI
<code className="inline">codewhale</code> <code className="inline">codewhale-tui</code>
</>
),
sources: ["README.md"],
},
{
q: "CodeWhale 和 DeepSeek TUI 是什么关系?改名是怎么回事?",
a: (
<>
CodeWhale DeepSeek TUI <code className="inline">codewhale</code> <code className="inline">deepseek</code> <code className="inline">deepseek-tui</code>
<code className="inline">~/.deepseek/</code><code className="inline">DEEPSEEK_*</code>
DeepSeek CodeWhale 广使 DeepSeek
</>
),
sources: ["docs/REBRAND.md", "README.md"],
},
{
q: "如何设置 API 密钥?",
a: (
<>
<pre className="code-block mb-2">
{`# 方法 1:环境变量
export DEEPSEEK_API_KEY=sk-...
# 方法 2:保存在配置中(推荐 — 重启 Shell 后仍然有效)
codewhale auth set --provider deepseek --api-key sk-...
# 方法 3config.toml
# 在 ~/.deepseek/config.toml 中添加:
api_key = "sk-..."
# 查看当前状态:
codewhale auth status # 显示配置、密钥环和环境变量状态
codewhale doctor # 完整连接检查`}
</pre>
<p>
使 <code className="inline">codewhale auth clear --provider deepseek</code>
</p>
</>
),
sources: ["#907", "#1545", "docs/CONFIGURATION.md"],
},
{
q: "CodeWhale 支持哪些提供商?",
a: (
<>
<p className="mb-2">CodeWhale </p>
<ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft mb-3">
<li><strong>DeepSeek</strong> API</li>
<li><strong>OpenRouter</strong> API访 DeepSeek </li>
<li><strong>OpenAI</strong><strong>NVIDIA NIM</strong><strong>Novita</strong><strong>Fireworks</strong><strong>sglang</strong><strong>vLLM</strong><strong>Ollama</strong></li>
</ul>
<p>
<code className="inline">OPENROUTER_API_KEY</code> <code className="inline">~/.deepseek/config.toml</code>
Hugging FaceZenMux OpenAI 线
</p>
</>
),
sources: ["docs/CONFIGURATION.md", "#1978", "#1710"],
},
{
q: "如何使用 OpenRouter",
a: (
<>
<pre className="code-block mb-2">
{`# 1. 设置 OpenRouter 密钥
export OPENROUTER_API_KEY=sk-or-v1-...
# 2. 在 ~/.deepseek/config.toml 中:
[providers.openrouter]
api_key = "sk-or-v1-..."
# 3. 使用 OpenRouter 模型运行:
codewhale --model openrouter/deepseek/deepseek-v4-pro
# 或在 config.toml 中设为默认:
default_text_model = "openrouter/deepseek/deepseek-v4-pro"`}
</pre>
<p>
OpenRouter 使 DeepSeek /
ID <code className="inline">provider/model-id</code> <code className="inline">openrouter/deepseek/deepseek-v4-flash</code>
</p>
</>
),
sources: ["docs/CONFIGURATION.md", "#1978"],
},
{
q: "可以使用自托管或本地模型吗(vLLM、Ollama、llama.cpp)?",
a: (
<>
使 <code className="inline">vllm</code><code className="inline">sglang</code> <code className="inline">ollama</code>
OpenAI llama.cpp servertext-generation-webui 使 <code className="inline">openai</code> <code className="inline">base_url</code>
CodeWhale <code className="inline">DEEPSEEK_ALLOW_INSECURE_HTTP=true</code> HTTP
Hugging Face TGI/vLLM 线
</>
),
sources: ["#574", "#1303", "docs/CONFIGURATION.md"],
},
{
q: "Plan、Agent、YOLO 三种模式有什么区别?",
a: (
<>
<ul className="list-disc pl-5 space-y-2 text-sm text-ink-soft">
<li><strong>Plan</strong> grep URL Shell</li>
<li><strong>Agent</strong> Shell approval_mode </li>
<li><strong>YOLO</strong> 使</li>
</ul>
<p className="mt-2">
<kbd className="font-mono text-xs px-1.5 py-0.5 hairline-t hairline-b hairline-l hairline-r">Tab</kbd>
/ / Agent 使
</p>
</>
),
sources: ["docs/MODES.md"],
},
{
q: "什么是模型自动路由?Fin 是什么?",
a: (
<>
<p className="mb-2">
使 <code className="inline">codewhale --model auto</code> <code className="inline">/model auto</code> CodeWhale
</p>
<p className="mb-2">
<strong>Fin</strong> <code className="inline">deepseek-v4-flash</code>RLM Fin
</p>
<p>
Flash + Pro /Fin CodeWhale API <code className="inline">model: "auto"</code>
</p>
</>
),
sources: ["README.md", "#1207"],
},
{
q: "什么是 Goal 模式?现在可用吗?",
a: (
<>
Goal / <code className="inline">/goal</code>
<code className="inline">/goal</code> Goal /
<a href="https://github.com/Hmbown/CodeWhale/issues/891" className="body-link">#891</a>
</>
),
sources: ["#891"],
},
{
q: "我的代码安全吗?CodeWhale 使用什么沙箱机制?",
a: (
<>
CodeWhale
<strong>seatbelt</strong>macOS<strong>landlock</strong>LinuxWindows
<code className="inline">--workspace</code><code className="inline">/trust</code>
// <code className="inline">~/.deepseek/audit.log</code>
</>
),
sources: ["SECURITY.md", "docs/ARCHITECTURE.md"],
},
{
q: "MCP 服务器如何工作?",
a: (
<>
CodeWhale MCP <code className="inline">~/.deepseek/mcp.json</code>
<code className="inline">mcp_&lt;server&gt;_&lt;tool&gt;</code> <code className="inline">codewhale mcp</code> CodeWhale MCP
<Link href="/zh/docs#mcp" className="body-link"></Link>
</>
),
sources: ["docs/MCP.md"],
},
{
q: "如何参与贡献?",
a: (
<>
CLAFork<code className="inline">feat:</code><code className="inline">fix:</code> PR
<code className="inline">good first issue</code>
<Link href="/zh/contribute" className="body-link"></Link> <a href="https://github.com/Hmbown/CodeWhale/blob/main/CONTRIBUTING.md" className="body-link">CONTRIBUTING.md</a>
</>
),
sources: ["CONTRIBUTING.md"],
},
{
q: "我在国内,安装很慢怎么办?",
a: (
<>
使
<pre className="code-block my-2">
{`# npm 镜像
npm config set registry https://registry.npmmirror.com
npm install -g codewhale
# Cargo 镜像(清华 TUNA
# 在 ~/.cargo/config.toml 中添加:
[source.crates-io]
replace-with = "tuna"
[source.tuna]
registry = "sparse+https://mirrors.tuna.tsinghua.edu.cn/crates.io-index/"`}
</pre>
<p>
<a href="https://github.com/Hmbown/CodeWhale/releases" className="body-link">GitHub Releases</a>
Gitee CNB
</p>
</>
),
sources: ["README.md", "#1914", "docs/CNB_MIRROR.md"],
},
{
q: "首次运行时提示 API 密钥被拒绝或认证错误?",
a: (
<>
<p className="mb-2"> <code className="inline">codewhale doctor</code> API MCP <code className="inline">~/.deepseek/doctor.log</code></p>
<p className="mb-2"></p>
<ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft">
<li>Shell <code className="inline">DEEPSEEK_API_KEY</code> Shell 使 <code className="inline">codewhale auth set</code></li>
<li>使</li>
<li> <code className="inline">curl https://api.deepseek.com/v1/models</code></li>
</ul>
</>
),
sources: ["#907", "#1545"],
},
{
q: "Model Lab 是什么?Hugging Face 集成什么时候可用?",
a: (
<>
Model Lab Hugging Face Hub API safetensors Jobs
<a href="https://github.com/Hmbown/CodeWhale/issues/1977" className="body-link">#1977</a>
OpenRouter 使 Hugging Face
</>
),
sources: ["#1977", "docs/MODEL_LAB.md"],
},
{
q: "为什么 token 消耗这么大?/ 缓存命中率为什么低?",
a: (
<>
CodeWhale
DeepSeek 使
token 使使 <code className="inline">deepseek-v4-pro</code> Flash
Fin
</>
),
sources: ["#1177", "#1818", "#743"],
},
{
q: "如何更新 CodeWhale",
a: (
<>
<pre className="code-block mb-2">
{`# 发布二进制更新器(适用于 npm/二进制安装)
codewhale update
# npm
npm install -g codewhale@latest
# Cargo
cargo install codewhale-cli --locked --force
# Homebrew
brew update && brew upgrade deepseek-tui`}
</pre>
<p>
npm <code className="inline">codewhale update</code>
<a href="https://github.com/Hmbown/CodeWhale/releases" className="body-link">GitHub Releases</a>
</p>
</>
),
sources: ["README.md", "#1869", "#1914"],
},
];
export default async function FaqPage({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
const isZh = locale === "zh";
const items = isZh ? faqZh : faqEn;
return (
<>
<section className="mx-auto max-w-[1400px] px-6 pt-12 pb-8">
<div className="flex items-baseline gap-4 mb-3">
<Seal char="问" />
<div className="eyebrow">{isZh ? "常见问题" : "FAQ"}</div>
</div>
<h1 className="font-display tracking-crisp">
{isZh ? (
<> <span className="font-cjk text-indigo text-5xl ml-2">FAQ</span></>
) : (
<>FAQ <span className="font-cjk text-indigo text-5xl ml-2"></span></>
)}
</h1>
<p className="mt-5 max-w-3xl text-ink-soft text-lg leading-[1.9] tracking-wide">
{isZh
? "答案来自实际代码、文档、发布说明和 GitHub 议题。每个回答下方标注了信息来源。如有未覆盖的问题,请在 GitHub 上提交 Issue。"
: "Answers sourced from real code, docs, release notes, and GitHub issues. Sources are cited below each answer. If your question isn't covered, open an issue on GitHub."}
</p>
</section>
<section className="mx-auto max-w-[1400px] px-6 pb-20">
<div className="space-y-0 hairline-t hairline-b">
{items.map((item, i) => (
<details key={i} className="group hairline-b last:border-b-0">
<summary className="px-0 py-5 cursor-pointer flex items-start gap-4 hover:text-indigo transition-colors">
<span className="font-mono text-indigo tabular text-sm pt-0.5 shrink-0">
{String(i + 1).padStart(2, "0")}
</span>
<span className="font-display text-lg leading-snug flex-1">{item.q}</span>
<span className="font-mono text-ink-mute text-sm group-open:rotate-45 transition-transform shrink-0">+</span>
</summary>
<div className="pb-5 pl-10 pr-4">
<div className={`text-ink-soft leading-relaxed ${isZh ? "leading-[1.9] tracking-wide" : ""}`}>
{item.a}
</div>
{item.sources && item.sources.length > 0 && (
<div className="mt-3 flex items-center gap-2 flex-wrap">
<span className="font-mono text-[0.66rem] text-ink-mute uppercase tracking-wider">
{isZh ? "来源" : "Sources"}:
</span>
{item.sources.map((s) => (
<span key={s} className="font-mono text-[0.7rem] text-indigo">{s}</span>
))}
</div>
)}
</div>
</details>
))}
</div>
<div className="mt-12 text-center">
<p className="text-ink-soft text-sm mb-4">
{isZh
? "没找到你的问题?"
: "Didn't find your question?"}
</p>
<a
href="https://github.com/Hmbown/CodeWhale/issues/new/choose"
className="inline-flex items-center gap-2 px-5 py-3 bg-ink text-paper font-mono text-sm uppercase tracking-wider hover:bg-indigo transition-colors"
>
{isZh ? "提交 Issue →" : "Open an issue →"}
</a>
</div>
</section>
</>
);
}