diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5980745..81c19e6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,6 +12,24 @@ concurrency:
cancel-in-progress: true
jobs:
+ website:
+ name: Website build and download checks
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: pnpm/action-setup@v4
+ with:
+ version: 10.30.3
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 22
+ cache: pnpm
+ - run: pnpm install --filter @goagent/website... --frozen-lockfile --ignore-scripts
+ - run: pnpm website:build
+ - run: pnpm check:website
+ - run: pnpm --dir website exec astro check
+ - run: node --test website/tests/*.test.mjs
+
build:
name: Typecheck and build (${{ matrix.os }})
runs-on: ${{ matrix.os }}
diff --git a/.github/workflows/deploy-website.yml b/.github/workflows/deploy-website.yml
index 1fecf68..11e65e5 100644
--- a/.github/workflows/deploy-website.yml
+++ b/.github/workflows/deploy-website.yml
@@ -7,6 +7,7 @@ on:
paths:
- "website/**"
- "scripts/check_website.mjs"
+ - "pnpm-lock.yaml"
- ".github/workflows/deploy-website.yml"
workflow_dispatch:
@@ -50,11 +51,20 @@ jobs:
- name: Check website contract
run: pnpm check:website
+ - name: Check website types and download behavior
+ run: |
+ pnpm --dir website exec astro check
+ node --test website/tests/*.test.mjs
+
- name: Report missing Cloudflare secrets
if: ${{ env.CLOUDFLARE_API_TOKEN == '' || env.CLOUDFLARE_ACCOUNT_ID == '' }}
run: |
echo "::warning title=Cloudflare deploy skipped::Set repository secrets CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID to enable automatic Pages deploys."
+ - name: Verify Cloudflare authentication
+ if: ${{ env.CLOUDFLARE_API_TOKEN != '' && env.CLOUDFLARE_ACCOUNT_ID != '' }}
+ run: pnpm dlx wrangler@4.118.0 whoami
+
- name: Deploy to Cloudflare Pages
if: ${{ env.CLOUDFLARE_API_TOKEN != '' && env.CLOUDFLARE_ACCOUNT_ID != '' }}
run: pnpm dlx wrangler@4.118.0 pages deploy website/dist --project-name=goagent --branch=${{ github.ref_name }} --commit-hash=${{ github.sha }}
diff --git a/design-qa.md b/design-qa.md
index 9944b1a..cb15497 100644
--- a/design-qa.md
+++ b/design-qa.md
@@ -1,32 +1,59 @@
-# Download Center Design QA
+# Official Website Design QA
-## Scope
+final result: passed
-- Official homepage download entry
-- Simplified Chinese download center
-- Traditional Chinese, English, Japanese, Korean, Thai, and Vietnamese download pages
-- Live stable catalog integration
+Date: 2026-10-02. Scope: local implementation and browser verification, not production deployment.
-## Visual Review
+## Reference and comparison
-- [x] The page uses the existing GoAgent site header, footer, typography, and color system.
-- [x] Windows and macOS choices are separated into clear platform panels.
-- [x] NVIDIA, RTX 50, TensorRT, OpenCL, CPU, and no-engine choices are visible without technical setup copy.
-- [x] Apple silicon and Intel Mac choices are clearly distinguished.
-- [x] TensorRT is presented as two required download parts.
-- [x] The small Windows update is visually secondary to full downloads.
-- [x] Download sizes and the current stable tag are loaded from the live catalog.
-- [x] Empty, loading, and retry states remain understandable without exposing infrastructure details.
+- Selected direction: option 1, warm ivory paper, forest-green actions, Go-room photography, editorial serif headings.
+- [Selected reference](website/qa/2026-10-official-site/selected-reference.png)
+- [Rendered homepage, 1003 CSS px](website/qa/2026-10-official-site/home-final-1003.png)
+- [Rendered homepage, 390 CSS px](website/qa/2026-10-official-site/home-final-390.png)
+- [Rendered downloads, 1003 CSS px](website/qa/2026-10-official-site/download-final-1003.png)
+- Reference and rendered page were inspected together at matching width, then the hero was compared again in readable, matching 1003 x 625 crops.
+- Checked hierarchy, type scale, line breaks, color, imagery, spacing, section boundaries and real interactions. No unresolved P0/P1/P2 findings in this scope.
-## Interaction Review
+Intentional adaptations: use an actual recent application capture rather than the mockup's old UI; use library icons; show live release and size data; retain FAQ, privacy and community access; clarify that external AI service usage is not included. Page height adapts to readable copy rather than stretching a screenshot to match the reference. The full download page preserves advanced variants without crowding the homepage.
-- [x] All 10 generated download actions use HTTPS and the official download host.
-- [x] Catalog URLs are validated before being assigned to buttons.
-- [x] The catalog failure state offers retry and a direct download-page fallback.
-- [x] Navigation and footer download links stay inside the official website.
-- [x] Localized pages reuse one component, preventing layout and asset drift between languages.
-- [x] Interactive controls have visible labels and generated accessible names.
+## Findings fixed and retested
-## Result
+- Primary download URL with a trailing slash returned 404 in development. Accept both slash forms, retain the official download canonical.
+- Newly added image was absent in a stale dev server. Restarted and verified all image requests; no broken images in final capture.
+- Reduced header, workflow and download spacing after the first visual comparison.
+- Caption was low-contrast on photographic background. Added a small opaque-backed caption.
+- macOS/Linux tabs showed the Windows core-update link. Now shown only on Windows; mouse and keyboard retest passed.
+- Localhost is intentionally outside the production catalog CORS allowlist. A dev-only fixed-path proxy uses the real catalog; production output continues using the unchanged official endpoint.
+- Catalog loading now times out and retries a bounded number of times; failed loading provides retry and GitHub backup.
+- TensorRT buttons require distinct matching .001/.002 volumes. Invalid URLs, missing sizes or incomplete archives cannot become enabled downloads.
+- Guides and FAQ no longer instruct users to install another application just to use AI commentary.
-Passed local Astro build, website contract checks, desktop browser review, localized content review, and live catalog population checks.
+## Verification
+
+- 46 static routes built successfully.
+- Astro check: 0 errors, 0 warnings, 0 hints.
+- 13 automated tests passed: catalog URL safety, schema, flavor/architecture selection, multipart validation, retries, timeout, size formatting, seven-language keys, built routes, local links/assets and duplicate IDs.
+- Website contract check and git diff --check passed.
+- Seven languages: homepage and downloads checked at 390px; all homepages checked at 1440px. No horizontal overflow or missing images. Chinese and English additionally checked at 320px; reference comparison at 1003px.
+- Browser-tested homepage download, language navigation, mobile menu, Escape/focus restoration, OS tabs, ArrowLeft/ArrowRight/Home/End selection and Windows-only update visibility.
+- Final browser log inspection: no warnings or errors.
+- Live catalog: next-2026-09-26.2. All ten displayed binary/volume URLs returned HTTP 200 via HEAD, with Content-Length matching the catalog. No multi-gigabyte full downloads were performed.
+- Production-origin CORS response explicitly allows https://goagent.top.
+
+## Boundaries
+
+No release assets, update protocol, R2 objects, production site or DNS were changed. No PR or deployment was performed. Browser checks used the local macOS in-app browser; this is not a Windows, Safari or screen-reader certification.
+
+The application image reuses the real 2026-10-01 local acceptance capture. A fresh isolated Java process was started, but the native automation surface could not attach to its window; it was stopped without changing existing user configuration. No application UI was synthesized into the image.
+
+## Reproduce
+
+```sh
+pnpm install --filter @goagent/website... --frozen-lockfile --ignore-scripts
+pnpm website:build
+pnpm --dir website exec astro check
+node --test website/tests/*.test.mjs
+pnpm check:website
+git diff --check
+pnpm --dir website dev --host 127.0.0.1 --port 4173
+```
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4fc0483..8db1882 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -87,6 +87,9 @@ importers:
astro:
specifier: ^5.16.4
version: 5.18.1(@types/node@24.12.0)(jiti@2.6.1)(rollup@4.60.1)(tsx@4.23.5)(typescript@5.9.3)(yaml@2.8.4)
+ bootstrap-icons:
+ specifier: 1.13.1
+ version: 1.13.1
typescript:
specifier: ^5.9.3
version: 5.9.3
@@ -1546,6 +1549,9 @@ packages:
resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
+ bootstrap-icons@1.13.1:
+ resolution: {integrity: sha512-ijombt4v6bv5CLeXvRWKy7CuM3TRTuPEuGaGKvTV5cz65rQSY8RQ2JcHt6b90cBBAC7s8fsf2EkQDldzCoXUjw==}
+
boxen@8.0.1:
resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==}
engines: {node: '>=18'}
@@ -5411,6 +5417,8 @@ snapshots:
boolean@3.2.0: {}
+ bootstrap-icons@1.13.1: {}
+
boxen@8.0.1:
dependencies:
ansi-align: 3.0.1
diff --git a/scripts/check_website.mjs b/scripts/check_website.mjs
index ea43871..75e3a8e 100644
--- a/scripts/check_website.mjs
+++ b/scripts/check_website.mjs
@@ -25,6 +25,7 @@ function walk(dir) {
if (!existsSync(dir)) return []
const entries = []
for (const name of readdirSync(dir)) {
+ if (['node_modules', '.astro', 'dist', '.git'].includes(name)) continue
const path = join(dir, name)
const stat = statSync(path)
if (stat.isDirectory()) entries.push(...walk(path))
@@ -57,6 +58,8 @@ requireFile('website/public/ai.txt')
requireFile('website/public/_worker.js')
const index = read('website/src/pages/index.astro')
+const home = read('website/src/components/HomePage.astro')
+const homeCopy = read('website/src/data/home-copy.mjs')
const downloadPage = read('website/src/pages/download.astro')
const docsPage = read('website/src/pages/docs.astro')
const faqPage = read('website/src/pages/faq.astro')
@@ -64,6 +67,7 @@ const changelogPage = read('website/src/pages/changelog.astro')
const localizedHome = read('website/src/pages/[locale].astro')
const localizedPages = read('website/src/pages/[locale]/[page].astro')
const downloadChooser = read('website/src/components/DownloadChooser.astro')
+const downloadImplementation = downloadChooser + read('website/src/lib/download-catalog.mjs') + read('website/src/lib/download-ui.mjs')
const layout = read('website/src/layouts/BaseLayout.astro')
const privacy = read('website/src/pages/privacy.astro')
const deployment = read('website/DEPLOYMENT.md')
@@ -76,21 +80,19 @@ const ai = read('website/public/ai.txt')
const edgeWorker = read('website/public/_worker.js')
const chooserCopy = ['不会选', '也没关系'].join('')
-if (!index.includes('LizzieYzy Next')) fail('homepage must contain LizzieYzy Next')
-if (!index.includes('想复盘围棋')) fail('homepage must use the simple Go review hero headline')
-if (!index.includes('首推')) fail('homepage must present LizzieYzy Next as the recommended product')
-if (!index.includes('实验围棋智能体')) fail('homepage must position GoAgent as an experimental Go agent')
-for (const keyword of ['KataGo 官方推荐', '免费开源', '解压即用', '快速复盘']) {
- if (!index.includes(keyword)) fail(`homepage must focus LizzieYzy Next on the new core value prop: ${keyword}`)
+if (!index.includes('')) fail('download page must render the unified download chooser')
if (!downloadPage.includes('canonical="https://goagent.top/download/"')) fail('download page must use the trailing-slash canonical URL')
for (const keyword of [
@@ -118,7 +120,7 @@ for (const keyword of [
'Intel 芯片',
'下载小更新',
]) {
- if (!downloadChooser.includes(keyword)) fail(`download chooser must contain: ${keyword}`)
+ if (!downloadImplementation.includes(keyword)) fail(`download chooser must contain: ${keyword}`)
}
const nvidiaRow = downloadChooser.indexOf("['nvidia', 'windows-portable', 'nvidia'")
const amdRow = downloadChooser.indexOf("['amd', 'amd-rocm-experimental', 'rocm-gfx120x', 'x64'")
@@ -172,18 +174,8 @@ for (const keyword of ['我应该先下载哪个?', '我该点哪个下载?'
for (const keyword of ['官网首页更简单', '多语言页面同步更新', '普通用户不用先理解项目区别']) {
if (!changelogPage.includes(keyword)) fail(`changelog page must use user-facing copy: ${keyword}`)
}
-for (const keyword of [
- 'homeCopy',
- 'Review Go games?',
- 'officialDownloadCopy',
- 'home-proof-strip',
- 'hero-actions',
- 'Officially recommended by KataGo',
- 'Free, open source, unzip-and-run',
- 'lizzieDownload',
- 'Tải LizzieYzy Next'
-]) {
- if (!localizedHome.includes(keyword)) fail(`localized homepage must use the simplified homepage system: ${keyword}`)
+for (const keyword of ['HomePage', 'localeSlugs', 'getStaticPaths']) {
+ if (!localizedHome.includes(keyword)) fail(`localized homepage must share the same components: ${keyword}`)
}
for (const forbidden of [
'lizzieBaidu',
diff --git a/website/DEPLOYMENT.md b/website/DEPLOYMENT.md
index b606dde..dd7f8ae 100644
--- a/website/DEPLOYMENT.md
+++ b/website/DEPLOYMENT.md
@@ -98,12 +98,13 @@ website/dist
## 6. GitHub Actions 自动部署
-仓库提供 `.github/workflows/deploy-website.yml`。当 `main` 分支里的 `website/**`、`scripts/check_website.mjs` 或部署 workflow 变化时,GitHub Actions 会:
+仓库提供 `.github/workflows/deploy-website.yml`。当 `main` 分支里的 `website/**`、`scripts/check_website.mjs`、`pnpm-lock.yaml` 或部署 workflow 变化时,GitHub Actions 会:
1. 安装网站依赖。
2. 构建 Astro 静态站。
3. 执行 `pnpm check:website`。
-4. 使用 Cloudflare Wrangler Direct Upload 部署到 Pages 项目 `goagent`。
+4. 执行 Astro 类型检查、七语构建页面检查和下载逻辑测试;PR 阶段也执行相同门禁。
+5. 使用 `wrangler whoami` 验证部署授权,再通过 Direct Upload 部署到 Pages 项目 `goagent`。
Cloudflare Pages 项目当前是 Direct Upload 项目,不依赖 Pages 控制台的 Git 绑定。自动部署需要 GitHub 仓库 secrets:
diff --git a/website/DESIGN.md b/website/DESIGN.md
new file mode 100644
index 0000000..c1c4241
--- /dev/null
+++ b/website/DESIGN.md
@@ -0,0 +1,21 @@
+# Official Website Design
+
+The selected direction is a calm Go room: warm paper, forest green, restrained gold and readable editorial headings. The homepage has one primary product and one primary action, followed by a three-step review journey and three common Windows builds. The full download page keeps every supported variant.
+
+## Assets
+
+- `public/images/review-room.webp`: generated photographic background, 2026-10-02. Brief: ivory left-hand negative space, soft greenery and a wooden Go table on the right, no text, no interface, no logo.
+- `public/images/review-download.webp`: generated restrained ink-landscape and Go-stone background, 2026-10-02. Brief: quiet ivory left side, decorative landscape on the right, no text or interface.
+- `public/images/lizzie-review.webp`: real LizzieYzy Next local-engine acceptance screenshot from 2026-10-01, converted to WebP without synthesized UI. No credentials or personal game names are shown.
+- `SiteIcon.astro`: Bootstrap Icons 1.13.1 (MIT), imported from the pinned dependency. Existing brand and download icons are retained.
+- The selected mockup and final screenshots are in `qa/2026-10-official-site/`; these QA files are not public website assets.
+
+## Maintenance
+
+Homepage copy is shared across seven locales in `src/data/home-copy.mjs`. Explanatory copy in `guide-copy.mjs` keeps AI setup and privacy statements consistent. Headings and body copy remain real HTML, not image text.
+
+`DownloadChooser.astro` is used by both the homepage and download routes. Live release selection stays in `download-catalog.mjs`; UI status, retry and keyboard navigation stay in `download-ui.mjs`. Do not replace the live catalog with hardcoded sample versions or sizes.
+
+The dev-only catalog proxy is fixed to one public endpoint. Production uses the existing direct endpoint and CORS policy. Tests live under `website/tests`, separate from desktop-application tests, and run after the website build.
+
+See the repository-root `design-qa.md` for verification evidence and scope limits. Deploy only through the existing Cloudflare Pages workflow after review; this redesign does not migrate hosting or alter release assets.
diff --git a/website/astro.config.mjs b/website/astro.config.mjs
index a788d19..0a604f0 100644
--- a/website/astro.config.mjs
+++ b/website/astro.config.mjs
@@ -3,5 +3,17 @@ import { defineConfig } from 'astro/config'
export default defineConfig({
site: 'https://goagent.top',
output: 'static',
- trailingSlash: 'never'
+ trailingSlash: 'ignore',
+ devToolbar: { enabled: false },
+ vite: {
+ server: {
+ proxy: {
+ '/__dev/stable/catalog.json': {
+ target: 'https://download.goagent.top',
+ changeOrigin: true,
+ rewrite: () => '/channels/stable/catalog.json'
+ }
+ }
+ }
+ }
})
diff --git a/website/package.json b/website/package.json
index 54121a8..fd8d57a 100644
--- a/website/package.json
+++ b/website/package.json
@@ -11,6 +11,7 @@
"dependencies": {
"@astrojs/check": "^0.9.4",
"astro": "^5.16.4",
+ "bootstrap-icons": "1.13.1",
"typescript": "^5.9.3"
}
}
diff --git a/website/public/images/lizzie-review.webp b/website/public/images/lizzie-review.webp
new file mode 100644
index 0000000..d3c432c
Binary files /dev/null and b/website/public/images/lizzie-review.webp differ
diff --git a/website/public/images/review-download.webp b/website/public/images/review-download.webp
new file mode 100644
index 0000000..89bad57
Binary files /dev/null and b/website/public/images/review-download.webp differ
diff --git a/website/public/images/review-room.webp b/website/public/images/review-room.webp
new file mode 100644
index 0000000..95855e3
Binary files /dev/null and b/website/public/images/review-room.webp differ
diff --git a/website/qa/2026-10-official-site/download-final-1003.png b/website/qa/2026-10-official-site/download-final-1003.png
new file mode 100644
index 0000000..482877a
Binary files /dev/null and b/website/qa/2026-10-official-site/download-final-1003.png differ
diff --git a/website/qa/2026-10-official-site/home-final-1003.png b/website/qa/2026-10-official-site/home-final-1003.png
new file mode 100644
index 0000000..ea8cfce
Binary files /dev/null and b/website/qa/2026-10-official-site/home-final-1003.png differ
diff --git a/website/qa/2026-10-official-site/home-final-390.png b/website/qa/2026-10-official-site/home-final-390.png
new file mode 100644
index 0000000..ef90be8
Binary files /dev/null and b/website/qa/2026-10-official-site/home-final-390.png differ
diff --git a/website/qa/2026-10-official-site/selected-reference.png b/website/qa/2026-10-official-site/selected-reference.png
new file mode 100644
index 0000000..b843eb6
Binary files /dev/null and b/website/qa/2026-10-official-site/selected-reference.png differ
diff --git a/website/src/components/DownloadChooser.astro b/website/src/components/DownloadChooser.astro
index e523c31..5c97e5c 100644
--- a/website/src/components/DownloadChooser.astro
+++ b/website/src/components/DownloadChooser.astro
@@ -1,12 +1,18 @@
---
+import SiteIcon from './SiteIcon.astro'
+import { homeCopy } from '../data/home-copy.mjs'
+import '../styles/download-refresh.css'
type SiteLang = 'zh-CN' | 'zh-Hant' | 'en' | 'ja' | 'ko' | 'th' | 'vi'
interface Props {
lang?: SiteLang
+ compact?: boolean
+ title?: string
+ lead?: string
}
-const { lang = 'zh-CN' } = Astro.props
-const catalogUrl = 'https://download.goagent.top/channels/stable/catalog.json'
+const { lang = 'zh-CN', compact = false, title, lead } = Astro.props
+const catalogUrl = import.meta.env.DEV ? '/__dev/stable/catalog.json' : 'https://download.goagent.top/channels/stable/catalog.json'
const releaseHistory = 'https://github.com/wimi321/lizzieyzy-next/releases'
const copyByLang = {
@@ -95,6 +101,8 @@ const copyByLang = {
} as const
const copy = copyByLang[lang] ?? copyByLang.en
+const home = homeCopy[lang]
+const Heading = compact ? 'h2' : 'h1'
const localeSlug = { 'zh-CN': '', 'zh-Hant': 'zh-hant', en: 'en', ja: 'ja', ko: 'ko', th: 'th', vi: 'vi' }[lang]
const helpUrl = localeSlug ? `/${localeSlug}/docs` : '/docs'
const rows = [
@@ -112,9 +120,10 @@ const macRows = [
---
)}
+
+
+
+
diff --git a/website/src/components/SiteIcon.astro b/website/src/components/SiteIcon.astro
new file mode 100644
index 0000000..f1c4215
--- /dev/null
+++ b/website/src/components/SiteIcon.astro
@@ -0,0 +1,17 @@
+---
+import download from 'bootstrap-icons/icons/download.svg?url'
+import folder from 'bootstrap-icons/icons/folder2-open.svg?url'
+import search from 'bootstrap-icons/icons/search.svg?url'
+import chart from 'bootstrap-icons/icons/bar-chart-line-fill.svg?url'
+import windows from 'bootstrap-icons/icons/windows.svg?url'
+import apple from 'bootstrap-icons/icons/apple.svg?url'
+import linux from 'bootstrap-icons/icons/ubuntu.svg?url'
+import globe from 'bootstrap-icons/icons/globe2.svg?url'
+import menu from 'bootstrap-icons/icons/list.svg?url'
+import chevron from 'bootstrap-icons/icons/chevron-down.svg?url'
+import arrow from 'bootstrap-icons/icons/arrow-right.svg?url'
+const icons = { download, folder, search, chart, windows, apple, linux, globe, menu, chevron, arrow }
+interface Props { name: keyof typeof icons; size?: number; class?: string }
+const { name, size = 22, class: className = '' } = Astro.props
+---
+
diff --git a/website/src/data/guide-copy.mjs b/website/src/data/guide-copy.mjs
new file mode 100644
index 0000000..993c592
--- /dev/null
+++ b/website/src/data/guide-copy.mjs
@@ -0,0 +1,37 @@
+export const guideCopy = {
+ 'zh-CN': {
+ ai: ['使用 AI 解说', '在 LizzieYzy Next 顶部点击“AI 解说”,连接自己的服务后使用。不需要另外安装 GoAgent;服务用量与费用以提供方为准。'],
+ separate: '不需要。LizzieYzy Next 已提供 AI 解说和 AI 陪练。GoAgent 是另一个实验项目,只在想尝鲜时选择。',
+ privacy: '官网不上传棋谱。本地引擎在电脑上分析;使用远程算力或 AI 解说时,必要的棋局内容会发送给你选择的服务。'
+ },
+ 'zh-Hant': {
+ ai: ['使用 AI 解說', '點擊 LizzieYzy Next 頂部的「AI 解說」,連接自己的服務即可使用,不必另裝 GoAgent。用量與費用以服務商為準。'],
+ separate: '不需要。LizzieYzy Next 已提供 AI 解說與 AI 陪練。GoAgent 是另一個可選的實驗專案。',
+ privacy: '官網不上傳棋譜。本機引擎在電腦上分析;使用遠端算力或 AI 解說時,必要棋局內容會傳送到你選擇的服務。'
+ },
+ en: {
+ ai: ['Use AI commentary', 'Choose AI Commentary at the top of LizzieYzy Next and connect your own service. No separate GoAgent installation is needed. Usage and fees depend on your provider.'],
+ separate: 'No. LizzieYzy Next already includes AI commentary and practice. GoAgent is a separate, optional experimental project.',
+ privacy: 'This website does not upload games. Local engines analyze on your computer. Remote engines and AI commentary send the necessary game context to the service you choose.'
+ },
+ ja: {
+ ai: ['AI 解説を使う', 'LizzieYzy Next 上部の AI 解説から、自分のサービスに接続します。GoAgent の追加インストールは不要です。利用枠と料金はサービス提供元に従います。'],
+ separate: '不要です。LizzieYzy Next に AI 解説と練習機能があります。GoAgent は別の実験的プロジェクトです。',
+ privacy: 'このサイトは棋譜を送信しません。ローカルエンジンは本機で分析します。遠隔エンジンや AI 解説では、必要な棋譜情報を選択したサービスに送信します。'
+ },
+ ko: {
+ ai: ['AI 해설 사용', 'LizzieYzy Next 상단의 AI 해설에서 본인의 서비스에 연결하세요. GoAgent를 따로 설치할 필요가 없습니다. 사용량과 요금은 서비스 제공업체 기준입니다.'],
+ separate: '아니요. LizzieYzy Next에 AI 해설과 연습 기능이 있습니다. GoAgent는 별도의 선택형 실험 프로젝트입니다.',
+ privacy: '이 사이트는 기보를 업로드하지 않습니다. 로컬 엔진은 컴퓨터에서 분석합니다. 원격 엔진이나 AI 해설을 쓰면 필요한 기보 정보가 선택한 서비스로 전송됩니다.'
+ },
+ th: {
+ ai: ['ใช้คำอธิบาย AI', 'กด AI Commentary ด้านบนของ LizzieYzy Next แล้วเชื่อมต่อบริการของคุณ ไม่ต้องติดตั้ง GoAgent เพิ่ม โควตาและค่าบริการเป็นไปตามผู้ให้บริการ'],
+ separate: 'ไม่จำเป็น LizzieYzy Next มีคำอธิบาย AI และคู่ซ้อมอยู่แล้ว GoAgent เป็นโครงการทดลองแยกต่างหากสำหรับผู้ที่สนใจ',
+ privacy: 'เว็บไซต์ไม่อัปโหลดคีฟู เอนจินภายในเครื่องวิเคราะห์บนคอมพิวเตอร์ของคุณ เมื่อใช้เอนจินระยะไกลหรือคำอธิบาย AI ข้อมูลเกมที่จำเป็นจะถูกส่งไปยังบริการที่คุณเลือก'
+ },
+ vi: {
+ ai: ['Dùng giải thích AI', 'Chọn AI Commentary ở đầu LizzieYzy Next và kết nối dịch vụ của bạn. Không cần cài thêm GoAgent. Hạn mức và phí theo nhà cung cấp dịch vụ.'],
+ separate: 'Không cần. LizzieYzy Next đã có giải thích AI và luyện tập. GoAgent là một dự án thử nghiệm riêng, không bắt buộc.',
+ privacy: 'Website không tải kỳ phổ lên. Engine cục bộ phân tích trên máy. Khi dùng engine từ xa hoặc giải thích AI, thông tin ván đấu cần thiết được gửi tới dịch vụ bạn chọn.'
+ }
+}
diff --git a/website/src/data/home-copy.mjs b/website/src/data/home-copy.mjs
new file mode 100644
index 0000000..553d806
--- /dev/null
+++ b/website/src/data/home-copy.mjs
@@ -0,0 +1,80 @@
+export const localeSlugs = { 'zh-CN': '', 'zh-Hant': 'zh-hant', en: 'en', ja: 'ja', ko: 'ko', th: 'th', vi: 'vi' }
+export const homeCopy = {
+ 'zh-CN': {
+ title: 'LizzieYzy Next · 看懂每一盘棋', description: '免费开源的围棋复盘软件。导入棋谱,查看 KataGo 分析、关键失误与变化,使用 AI 陪练和解说。支持 Windows、macOS 和 Linux。',
+ headline: ['下过的每一盘,', '都值得看懂。'], lead: '导入棋谱,找到关键失误。复盘、陪练、AI 解说,在一个软件里完成。',
+ download: '免费下载', tour: '看看如何复盘', free: '软件免费开源', quote: ['棋如人生,', '多一分看见,多一分从容。'],
+ screenshot: 'LizzieYzy Next 实际界面:棋盘、胜率曲线与候选变化', caption: '真实软件界面 · KataGo 分析',
+ stepsTitle: '从今天的一盘棋开始', stepsLead: '只需三步,找到值得复盘的关键手。',
+ steps: [['找到棋谱', '打开本地棋谱,或从野狐等平台下载后导入,支持 SGF 格式。'], ['自动分析', '用 KataGo 查看胜率和目差变化,按自己的节奏逐手分析。'], ['看懂关键手', '对照实战与推荐变化;也可以配置 AI 解说,帮助理解。']],
+ downloadTitle: '选对版本,开始复盘', downloadLead: '根据电脑配置选择。更多版本与安装说明,请前往下载页面。',
+ allDownloads: '全部版本与安装帮助', platformLabel: '选择电脑系统', linuxLead: 'Linux 版本在 GitHub 提供,包含 CPU、OpenCL 和 CUDA。', linuxAction: '查看 Linux 下载',
+ menu: '导航菜单', language: '选择语言', nav: '网站导航', tagline: '围棋,让更多人看见 AI 的可能。', experimental: 'GoAgent 实验项目', footerNote: '开源 · 自由 · 更好的围棋工具', community: '交流社区', aiNote: 'AI 解说需自行连接服务,服务用量与费用以提供方为准。'
+ },
+ 'zh-Hant': {
+ title: 'LizzieYzy Next · 看懂每一盤棋', description: '免費開源的圍棋復盤軟體。匯入棋譜,查看 KataGo 分析、關鍵失誤與變化,使用 AI 陪練和解說。',
+ headline: ['下過的每一盤,', '都值得看懂。'], lead: '匯入棋譜,找到關鍵失誤。復盤、陪練、AI 解說,在一個軟體裡完成。',
+ download: '免費下載', tour: '看看如何復盤', free: '軟體免費開源', quote: ['棋如人生,', '多一分看見,多一分從容。'],
+ screenshot: 'LizzieYzy Next 實際介面:棋盤、勝率曲線與候選變化', caption: '真實軟體介面 · KataGo 分析',
+ stepsTitle: '從今天的一盤棋開始', stepsLead: '只需三步,找到值得復盤的關鍵手。',
+ steps: [['找到棋譜', '開啟本機棋譜,或從野狐等平台下載後匯入,支援 SGF 格式。'], ['自動分析', '用 KataGo 查看勝率和目差變化,按自己的節奏逐手分析。'], ['看懂關鍵手', '對照實戰與推薦變化;也可以設定 AI 解說,幫助理解。']],
+ downloadTitle: '選對版本,開始復盤', downloadLead: '根據電腦配備選擇。更多版本與安裝說明,請前往下載頁面。',
+ allDownloads: '全部版本與安裝說明', platformLabel: '選擇電腦系統', linuxLead: 'Linux 版本在 GitHub 提供,包含 CPU、OpenCL 和 CUDA。', linuxAction: '查看 Linux 下載',
+ menu: '導覽選單', language: '選擇語言', nav: '網站導覽', tagline: '圍棋,讓更多人看見 AI 的可能。', experimental: 'GoAgent 實驗專案', footerNote: '開源 · 自由 · 更好的圍棋工具', community: '交流社群', aiNote: 'AI 解說需自行連接服務,用量與費用以服務提供者為準。'
+ },
+ en: {
+ title: 'LizzieYzy Next · Understand every game', description: 'Free, open-source Go review with KataGo analysis, key mistakes, AI practice and explanations. For Windows, macOS and Linux.',
+ headline: ['Every game played.', 'A little more understood.'], lead: 'Open a game, find the turning points. Review, practice and AI explanations in one place.',
+ download: 'Download free', tour: 'See how review works', free: 'Free, open-source software', quote: ['A clearer view of the board.', 'A more thoughtful next move.'],
+ screenshot: 'Real LizzieYzy Next interface with board, win-rate graph and variations', caption: 'Real application · KataGo analysis',
+ stepsTitle: 'Start with a game you played today', stepsLead: 'Three steps to the moves worth a second look.',
+ steps: [['Find your game', 'Open an SGF file, or import a game downloaded from Fox or another platform.'], ['Run analysis', 'Use KataGo to examine win rate and score changes, one move at your own pace.'], ['Understand key moves', 'Compare your moves with suggested variations. Connect an AI service for explanations.']],
+ downloadTitle: 'The right version. Your next review.', downloadLead: 'Choose for your computer. Find more versions and installation help on the download page.',
+ allDownloads: 'All versions & installation help', platformLabel: 'Choose your operating system', linuxLead: 'Linux builds are available on GitHub, including CPU, OpenCL and CUDA.', linuxAction: 'Get Linux builds',
+ menu: 'Navigation menu', language: 'Choose language', nav: 'Site navigation', tagline: 'A clearer view of Go, with AI.', experimental: 'GoAgent experiments', footerNote: 'Open source. Better tools for Go.', community: 'Community', aiNote: 'AI explanations require your own service connection. Provider usage limits and fees apply.'
+ },
+ ja: {
+ title: 'LizzieYzy Next · 一局ごとの理解を深める', description: '無料・オープンソースの囲碁復盤ソフト。KataGo 分析、AI 対局練習と解説を Windows・macOS・Linux で。',
+ headline: ['打った一局から、', '次の一手が見えてくる。'], lead: '棋譜を開いて、重要な一手を見つける。復盤も練習も AI 解説も、ひとつのソフトで。',
+ download: '無料ダウンロード', tour: '復盤の流れを見る', free: '無料・オープンソース', quote: ['盤面が見えれば、', '次の一手に余裕が生まれる。'],
+ screenshot: 'LizzieYzy Next の実画面:盤面・勝率グラフ・候補手', caption: '実際の画面 · KataGo 分析',
+ stepsTitle: '今日の一局から始めよう', stepsLead: '三つのステップで、振り返りたい一手へ。',
+ steps: [['棋譜を開く', '手元の SGF や、野狐などから取得した棋譜を読み込みます。'], ['自動分析', '勝率と目差の変化を KataGo で確認。自分のペースで一手ずつ。'], ['重要な一手を理解', '実戦と推奨変化を比較。AI サービスを接続すると解説も利用できます。']],
+ downloadTitle: '環境に合う版で、復盤を始める', downloadLead: 'パソコンに合わせて選択。その他の版や導入方法はダウンロードページへ。',
+ allDownloads: 'すべての版とインストール案内', platformLabel: 'OS を選択', linuxLead: 'Linux の CPU・OpenCL・CUDA 版は GitHub で提供しています。', linuxAction: 'Linux 版を見る',
+ menu: 'ナビゲーション', language: '言語を選択', nav: 'サイト案内', tagline: 'AI とともに、囲碁をもっと深く。', experimental: 'GoAgent 実験プロジェクト', footerNote: 'オープンソースで、囲碁をもっと身近に。', community: 'コミュニティ', aiNote: 'AI 解説にはサービス接続が必要です。利用条件と料金は提供元に従います。'
+ },
+ ko: {
+ title: 'LizzieYzy Next · 한 판마다 깊어지는 이해', description: '무료 오픈소스 바둑 복기 도구. KataGo 분석, AI 연습 대국과 해설을 Windows, macOS, Linux에서 사용하세요.',
+ headline: ['한 판의 경험을,', '다음 수의 배움으로.'], lead: '기보를 열고 중요한 실수를 찾아보세요. 복기, 연습, AI 해설을 한곳에서.',
+ download: '무료 다운로드', tour: '복기 과정 보기', free: '무료 오픈소스 소프트웨어', quote: ['더 잘 보이는 바둑판,', '더 여유로운 다음 한 수.'],
+ screenshot: 'LizzieYzy Next 실제 화면: 바둑판, 승률 그래프와 변화도', caption: '실제 프로그램 · KataGo 분석',
+ stepsTitle: '오늘 둔 한 판부터 시작하세요', stepsLead: '세 단계로 다시 볼 중요한 수를 찾습니다.',
+ steps: [['기보 찾기', 'SGF 파일을 열거나 야호 등에서 받은 기보를 불러옵니다.'], ['자동 분석', 'KataGo로 승률과 집 차이를 살피며 원하는 속도로 분석합니다.'], ['중요한 수 이해하기', '실전과 추천 변화도를 비교합니다. AI 서비스를 연결하면 해설도 이용할 수 있습니다.']],
+ downloadTitle: '맞는 버전으로 복기 시작', downloadLead: '컴퓨터에 맞게 선택하세요. 다른 버전과 설치 안내는 다운로드 페이지에서 확인하세요.',
+ allDownloads: '모든 버전 및 설치 안내', platformLabel: '운영체제 선택', linuxLead: 'Linux CPU, OpenCL, CUDA 버전은 GitHub에서 제공됩니다.', linuxAction: 'Linux 버전 보기',
+ menu: '탐색 메뉴', language: '언어 선택', nav: '사이트 탐색', tagline: 'AI와 함께 더 깊이 보는 바둑.', experimental: 'GoAgent 실험 프로젝트', footerNote: '오픈소스, 더 나은 바둑 도구.', community: '커뮤니티', aiNote: 'AI 해설은 서비스 연결이 필요하며 제공업체의 이용 한도와 요금이 적용됩니다.'
+ },
+ th: {
+ title: 'LizzieYzy Next · เข้าใจทุกเกมที่เล่น', description: 'ซอฟต์แวร์ทบทวนหมากล้อมฟรีและโอเพนซอร์ส พร้อม KataGo คู่ซ้อม AI และคำอธิบาย สำหรับ Windows, macOS และ Linux',
+ headline: ['ทุกเกมที่เล่น', 'มีสิ่งให้เข้าใจมากขึ้น'], lead: 'เปิดบันทึกเกม ค้นหาจุดเปลี่ยน ทบทวน ฝึกเล่น และใช้คำอธิบาย AI ในโปรแกรมเดียว',
+ download: 'ดาวน์โหลดฟรี', tour: 'ดูวิธีทบทวนเกม', free: 'ซอฟต์แวร์ฟรีและโอเพนซอร์ส', quote: ['มองกระดานชัดขึ้น', 'ตัดสินใจตาถัดไปอย่างมั่นใจ'],
+ screenshot: 'หน้าจอจริงของ LizzieYzy Next แสดงกระดาน กราฟโอกาสชนะ และแนวเดิน', caption: 'หน้าจอโปรแกรมจริง · วิเคราะห์ด้วย KataGo',
+ stepsTitle: 'เริ่มจากเกมที่เล่นวันนี้', stepsLead: 'สามขั้นตอนเพื่อค้นหาตาที่ควรกลับมาทบทวน',
+ steps: [['เลือกบันทึกเกม', 'เปิดไฟล์ SGF หรือนำเข้าเกมที่ดาวน์โหลดจาก Fox หรือแพลตฟอร์มอื่น'], ['วิเคราะห์อัตโนมัติ', 'ดูโอกาสชนะและผลต่างคะแนนด้วย KataGo วิเคราะห์ทีละตาตามจังหวะของคุณ'], ['เข้าใจตาสำคัญ', 'เทียบตาที่เล่นกับแนวเดินแนะนำ เชื่อมต่อบริการ AI เพื่ออ่านคำอธิบายเพิ่มเติม']],
+ downloadTitle: 'เลือกเวอร์ชัน แล้วเริ่มทบทวน', downloadLead: 'เลือกตามคอมพิวเตอร์ ดูเวอร์ชันอื่นและวิธีติดตั้งได้ที่หน้าดาวน์โหลด',
+ allDownloads: 'ทุกเวอร์ชันและวิธีติดตั้ง', platformLabel: 'เลือกระบบปฏิบัติการ', linuxLead: 'รุ่น Linux สำหรับ CPU, OpenCL และ CUDA มีให้ดาวน์โหลดบน GitHub', linuxAction: 'ดูรุ่น Linux',
+ menu: 'เมนูนำทาง', language: 'เลือกภาษา', nav: 'การนำทางเว็บไซต์', tagline: 'เข้าใจหมากล้อมมากขึ้นด้วย AI', experimental: 'โครงการทดลอง GoAgent', footerNote: 'โอเพนซอร์ส เพื่อเครื่องมือหมากล้อมที่ดีขึ้น', community: 'ชุมชน', aiNote: 'คำอธิบาย AI ต้องเชื่อมต่อบริการของคุณเอง โดยมีขีดจำกัดและค่าบริการตามผู้ให้บริการ'
+ },
+ vi: {
+ title: 'LizzieYzy Next · Hiểu rõ từng ván cờ', description: 'Phần mềm xem lại cờ vây miễn phí, mã nguồn mở với KataGo, luyện đấu và giải thích AI. Dành cho Windows, macOS và Linux.',
+ headline: ['Mỗi ván đã chơi,', 'một điều mới để hiểu.'], lead: 'Mở kỳ phổ, tìm nước sai quan trọng. Xem lại, luyện tập và giải thích AI trong cùng một phần mềm.',
+ download: 'Tải miễn phí', tour: 'Xem cách phân tích', free: 'Phần mềm miễn phí, mã nguồn mở', quote: ['Nhìn rõ bàn cờ hơn,', 'bình tĩnh hơn ở nước tiếp theo.'],
+ screenshot: 'Giao diện thật LizzieYzy Next với bàn cờ, đồ thị tỷ lệ thắng và biến thể', caption: 'Giao diện thật · Phân tích KataGo',
+ stepsTitle: 'Bắt đầu từ ván cờ hôm nay', stepsLead: 'Ba bước để tìm những nước đáng xem lại.',
+ steps: [['Tìm kỳ phổ', 'Mở tệp SGF hoặc nhập kỳ phổ đã tải từ Fox và các nền tảng khác.'], ['Phân tích tự động', 'Dùng KataGo xem tỷ lệ thắng và chênh lệch điểm, theo nhịp độ của bạn.'], ['Hiểu nước quan trọng', 'So sánh nước thực chiến với biến thể đề xuất. Kết nối dịch vụ AI để xem giải thích.']],
+ downloadTitle: 'Chọn đúng phiên bản, bắt đầu xem lại', downloadLead: 'Chọn theo máy tính. Các phiên bản khác và hướng dẫn cài đặt có trên trang tải xuống.',
+ allDownloads: 'Mọi phiên bản và hướng dẫn cài đặt', platformLabel: 'Chọn hệ điều hành', linuxLead: 'Các bản Linux CPU, OpenCL và CUDA được cung cấp trên GitHub.', linuxAction: 'Xem bản Linux',
+ menu: 'Menu điều hướng', language: 'Chọn ngôn ngữ', nav: 'Điều hướng trang', tagline: 'Hiểu cờ vây rõ hơn cùng AI.', experimental: 'Dự án thử nghiệm GoAgent', footerNote: 'Mã nguồn mở. Công cụ cờ vây tốt hơn.', community: 'Cộng đồng', aiNote: 'Giải thích AI cần kết nối dịch vụ riêng. Giới hạn sử dụng và phí do nhà cung cấp quy định.'
+ }
+}
diff --git a/website/src/layouts/BaseLayout.astro b/website/src/layouts/BaseLayout.astro
index 64b67c6..9516394 100644
--- a/website/src/layouts/BaseLayout.astro
+++ b/website/src/layouts/BaseLayout.astro
@@ -1,5 +1,8 @@
---
import '../styles/global.css'
+import '../styles/review-site.css'
+import SiteIcon from '../components/SiteIcon.astro'
+import { homeCopy } from '../data/home-copy.mjs'
interface Props {
title?: string
@@ -29,9 +32,7 @@ const {
jsonLd
} = Astro.props
-const goAgentUrl = 'https://github.com/wimi321/GoAgent'
const goAgentReleases = 'https://github.com/wimi321/GoAgent/releases'
-const goAgentIssues = `${goAgentUrl}/issues`
const lizzieUrl = 'https://github.com/wimi321/lizzieyzy-next'
const homeByLang = {
@@ -265,23 +266,7 @@ const navItems = [
{ href: localizedPath(siteLang, 'changelog'), label: changelogLabels[siteLang] },
{ href: localizedPath(siteLang, 'faq'), label: copy.nav.faq }
]
-
-const languageItems = [
- { href: localizedPath('zh-CN', languagePageKey), label: '简' },
- { href: localizedPath('zh-Hant', languagePageKey), label: '繁' },
- { href: localizedPath('en', languagePageKey), label: 'EN' },
- { href: localizedPath('ja', languagePageKey), label: '日' },
- { href: localizedPath('ko', languagePageKey), label: '한' },
- { href: localizedPath('th', languagePageKey), label: 'TH' },
- { href: localizedPath('vi', languagePageKey), label: 'VI' }
-]
-
-const resourceItems = [
- { href: '/katago-review', label: copy.resources.katago },
- { href: '/fox-go-review', label: copy.resources.fox },
- { href: '/ai-go-review', label: copy.resources.ai },
- { href: '/compare', label: copy.resources.compare }
-]
+const siteText = homeCopy[siteLang]
const alternateItems = localizedPageKeys.has(pageKey)
? [
@@ -323,55 +308,61 @@ const alternateItems = localizedPageKeys.has(pageKey)
{copy.skip}