Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/deploy-website.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
paths:
- "website/**"
- "scripts/check_website.mjs"
- "pnpm-lock.yaml"
- ".github/workflows/deploy-website.yml"
workflow_dispatch:

Expand Down Expand Up @@ -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 }}
75 changes: 51 additions & 24 deletions design-qa.md
Original file line number Diff line number Diff line change
@@ -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
```
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 15 additions & 23 deletions scripts/check_website.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -57,13 +58,16 @@ 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')
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')
Expand All @@ -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('<HomePage lang="zh-CN"')) fail('homepage must use the shared localized design')
for (const keyword of ['LizzieYzy Next', '下过的每一盘', '免费开源', 'AI 解说需自行连接服务']) {
if (!homeCopy.includes(keyword)) fail(`homepage must include user-facing guidance: ${keyword}`)
}
if (index.includes('README')) fail('homepage should say official recommendation instead of README wording')
if (!index.includes("const lizzieDownload = '/download'")) fail('homepage must route LizzieYzy Next downloads through the official download center')
for (const keyword of ['review-hero', 'review-steps', 'DownloadChooser', 'compact', 'lizzie-review.webp']) {
if (!home.includes(keyword)) fail(`homepage must retain the selected design and real product image: ${keyword}`)
}
for (const asset of ['lizzie-review.webp', 'review-room.webp', 'review-download.webp']) requireFile(`website/public/images/${asset}`)
if (index.includes(chooserCopy)) fail('homepage hero must not use unnecessary chooser copy')
if (index.includes('打不开再用')) fail('homepage should use priority/backup wording instead of troubleshooting-first wording')
if (!index.includes('https://github.com/wimi321/GoAgent/releases')) fail('homepage must still link GoAgent GitHub download')
if (!layout.includes('https://github.com/wimi321/GoAgent/releases')) fail('footer must retain the experimental project link')
if (!layout.includes('QQ 1030632742')) fail('site layout must expose QQ community')
if (index.includes('Trust')) fail('homepage should not include Trust section')
if (!index.includes('下载顺序很简单')) fail('homepage download section must use simple download sequence copy')
if (!downloadPage.includes('<DownloadChooser lang="zh-CN" />')) 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 [
Expand Down Expand Up @@ -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'")
Expand Down Expand Up @@ -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',
Expand Down
5 changes: 3 additions & 2 deletions website/DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
21 changes: 21 additions & 0 deletions website/DESIGN.md
Original file line number Diff line number Diff line change
@@ -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.
14 changes: 13 additions & 1 deletion website/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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'
}
}
}
}
})
1 change: 1 addition & 0 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"dependencies": {
"@astrojs/check": "^0.9.4",
"astro": "^5.16.4",
"bootstrap-icons": "1.13.1",
"typescript": "^5.9.3"
}
}
Binary file added website/public/images/lizzie-review.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added website/public/images/review-download.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added website/public/images/review-room.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading