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
31 changes: 26 additions & 5 deletions website/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# WheelPlay 官网(Astro)

独立于 Android 内置浏览器客户端的 Astro 静态产品官网。页面由 Astro 组件在构建时生成,浏览器仅加载全局 CSS 和少量 TypeScript 编译出的主题、标签页交互脚本,无需 React/Vue hydration 或服务端运行时。没有远程字体、分析 SDK 或设备连接请求;只有深浅主题偏好会写入 localStorage。下载按钮通过 `/download` 的 Cloudflare Worker 查询 GitHub Actions 元数据,再重定向到 GitHub 产物页面。
独立于 Android 内置浏览器客户端的 Astro 静态产品官网。页面由 Astro 组件在构建时生成,浏览器仅加载全局 CSS 和少量 TypeScript 编译出的主题、语言、标签页交互脚本,无需 React/Vue hydration 或服务端运行时。没有远程字体、分析 SDK 或设备连接请求;深浅主题及手动选择的语言偏好会写入 localStorage。下载按钮通过 `/download` 的 Cloudflare Worker 查询 GitHub Actions 元数据,再重定向到 GitHub 产物页面。

## 本地开发

Expand Down Expand Up @@ -36,8 +36,11 @@ npx wrangler@4.152.0 dev --config website/wrangler.worker.jsonc --port 4174
| --- | --- |
| `astro.config.mjs` | 静态输出、开发端口、CSS/JS 外部文件策略 |
| `src/layouts/BaseLayout.astro` | HTML 外壳、SEO 元数据、全局样式 |
| `src/pages/index.astro` | 组合首页各功能区 |
| `src/pages/index.astro` | 中文首页路由,共用 HomePage 组件 |
| `src/pages/docs/*.md` | 使用指南、常见问题正文及页面元数据 |
| `src/pages/en/` | 英文首页和英文 Markdown 文档 |
| `src/i18n/` | 类型检查的英文界面翻译、语言识别与站内链接工具 |
| `src/components/HomePage.astro` | 两种语言共用的首页结构 |
| `src/layouts/DocsLayout.astro` | 文档导航、自动目录和共享页面布局 |
| `src/styles/docs.css` | Markdown 正文排版、深浅主题和移动端样式 |
| `src/pages/404.astro` | 独立 404 页面与 `noindex` 元数据 |
Expand Down Expand Up @@ -100,7 +103,21 @@ npx wrangler@4.152.0 deploy --config website/wrangler.worker.jsonc --dry-run
npx wrangler@4.152.0 deploy --config website/wrangler.worker.jsonc
```

Workers Git 构建设置根目录 `website`、Node.js 24、构建命令 `npm run build`、部署命令 `npx wrangler@4.152.0 deploy --config wrangler.worker.jsonc`。按需修改配置中的 `name`。
Workers Git 构建设置:

| 设置 | 值 |
| --- | --- |
| 根目录 | `website` |
| Node.js | `24` |
| 构建命令 | `npm run build` |
| 生产部署命令 | `npx wrangler@4.152.0 deploy --config wrangler.worker.jsonc` |
| PR/非生产分支预览命令 | `npx wrangler@4.152.0 preview --config wrangler.worker.jsonc` |

生产部署和预览命令是 Cloudflare Build 设置中的两个独立字段,两个命令都必须指定 Worker 配置,否则会读取用于 Pages 的默认 `wrangler.jsonc`。按需修改配置中的 `name`。

`wrangler.worker.jsonc` 包含 `previews: {}`,用于启用分支预览。此网站没有需要单独配置的数据绑定;`assets`(包括 `ASSETS`)及兼容性设置保留在顶层,预览上传当前分支构建出的静态文件。不要将生产部署命令用于 PR 预览,否则会发布到生产环境。

预览不会自动继承生产 `GITHUB_TOKEN`。如需提高预览下载入口的 GitHub API 限额,在 Worker 设置的 **Previews Base → Variables and Secrets** 中配置同名 Secret,供之后新建的预览使用;已存在的预览需要单独更新 Secret。无需把 token 写入配置文件,也不要只设置 Build 环境变量。详见 [Cloudflare Previews 配置](https://developers.cloudflare.com/workers/previews/configuration/)。

Pages Functions 和独立 Workers 共用同一个下载解析器,是两种独立托管方式,任选其一即可,无需同时部署。若未来增加按需服务端渲染,再引入对应 Astro adapter 并调整输出方式。部署凭据只配置在 Cloudflare 账户或 CI Secrets 中。

Expand Down Expand Up @@ -142,14 +159,18 @@ npx wrangler@4.152.0 pages secret put GITHUB_TOKEN --project-name wheelplay-webs

## 内容维护

- **中英文路由。** 中文使用 `/`、`/docs/`、`/docs/faq/`,英文使用 `/en/`、`/en/docs/`、`/en/docs/faq/`。导航中的语言链接切换到对应页面,无 JavaScript 时同样可用。脚本记住手动选择的语言;再次访问 `/` 时,已选择英文的用户会进入 `/en/`。明确的文档链接始终以 URL 的语言为准,不根据浏览器语言强制跳转。禁用存储不会影响语言链接。
- **界面翻译。** `src/i18n/en.ts` 以中文原文为键存放英文翻译,共用组件通过 `useTranslations(Astro.url.pathname)` 获取 `t` 和 `local`。修改中文原文时同步更新翻译键及所有调用;缺失键由类型检查发现。品牌名、协议名及装饰性英文标语可共用。页面元数据、无障碍标签、主题按钮也需要翻译。
- **英文文档。** `src/pages/en/docs/*.md` 与中文文档成对维护,英文文档的布局路径为 `../../../layouts/DocsLayout.astro`,站内链接使用 `/en/docs/`。新增页面时同时更新 `DocsLayout.astro` 的导航与 `LanguageSwitch.astro` 的页面映射。高级仓库文档仍可能为中文,英文站内指南已注明。
- **下载与错误页。** 英文下载链接使用 `/download?lang=en`,只在输出错误消息时翻译,仍与中文共用内存、边缘缓存和 GitHub 查询。静态 404 包含两种语言,在脚本可用时按实际请求路径选择语言。
- **文档页面使用 Markdown。** 使用指南位于 `src/pages/docs/index.md`,常见问题位于 `src/pages/docs/faq.md`;正文、标题、说明均在 Markdown 中维护,不在 Astro 布局中编写文档正文。首页仍由产品展示组件组成。
- 新增文档时,在 `src/pages/docs/` 添加 `.md` 文件,frontmatter 填写 `layout: ../../layouts/DocsLayout.astro`、`title` 和 `description`;文件名决定路径。在 `DocsLayout.astro` 的 `pages` 中添加导航入口即可。正文从 `##` 开始,页面主标题由布局读取 `title` 生成,二级标题自动生成本页目录。
- 使用标准 Markdown 编写段落、列表、链接、表格和代码块,无需内嵌 HTML。代码块关闭内联样式高亮以兼容 CSP;导航、主题与响应式排版由布局负责。Astro 原生支持 Markdown,无需新增运行时依赖。
- `GettingStarted.astro` 中的下载入口为 `/download`,仓库、工作流和产物名集中定义于 `worker/download.ts`。更换下载来源时同步修改解析器、缓存键版本、测试与页面说明。
- `ExperiencePreview.astro` 中的导航、音乐、配对是明确标注的示意,不是真实 CarPlay 截图,不播放音频,也不连接设备。
- 页面默认中文,并提供英文项目文档入口。
- 页面默认中文,提供内置英文首页及使用文档。
- 绿色 App 图标与 Material Symbols 许可证沿用仓库文件,来源见 [`docs/APP_ICON.md`](../docs/APP_ICON.md)。
- 部署域名确定后,可在 Astro 配置中增加 `site`,并在共享布局中补充 canonical 和分享图片;目前不写入虚构域名。
- Astro 的 `site` 使用 `https://wheelplay.gwo.app`,共享布局生成 canonical 及中英文 hreflang。更换正式域名时同步修改此设置和构建检查;分享图片可按需补充。
- 添加分析或外部 API 时,需要同步维护 CSP,不能直接关闭策略。

## 验证
Expand Down
2 changes: 2 additions & 0 deletions website/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { defineConfig } from "astro/config";

export default defineConfig({
site: "https://wheelplay.gwo.app",
i18n: { defaultLocale: "zh-CN", locales: ["zh-CN", "en"], routing: { prefixDefaultLocale: false } },
output: "static",
// Plain code blocks keep Markdown compatible with the no-inline-style CSP.
markdown: { syntaxHighlight: false },
Expand Down
8 changes: 5 additions & 3 deletions website/src/components/Brand.astro
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
---
import { useTranslations } from "../i18n";
const { t, local } = useTranslations(Astro.url.pathname);
interface Props {
href?: string;
size?: number;
label?: boolean;
}
const { href = "/", size = 32, label = false } = Astro.props;
const { href = local("/"), size = 32, label = false } = Astro.props;
---

<a class="brand" href={href} aria-label="WheelPlay 首页">
<a class="brand" href={href} aria-label={t("WheelPlay 首页")}>
<img src="/assets/app-icon.svg" width={size} height={size} alt="" />
WheelPlay{label && <span class="brand-label">开源项目</span>}
WheelPlay{label && <span class="brand-label">{t("开源项目")}</span>}
</a>
11 changes: 8 additions & 3 deletions website/src/components/Closing.astro
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
---
import { useTranslations } from "../i18n";
const { t } = useTranslations(Astro.url.pathname);
---

<section class="closing container">
<div>
<p class="eyebrow">OPEN SOURCE. OPEN POSSIBILITIES.</p>
<h2>下一程,一起把体验变得更好。</h2>
<p>从一次使用、一条反馈,到一份代码贡献。</p>
<h2>{t("下一程,一起把体验变得更好。")}</h2>
<p>{t("从一次使用、一条反馈,到一份代码贡献。")}</p>
</div>
<a class="button secondary" href="https://github.com/fython/wheelplay"
>在 GitHub 探索 WheelPlay <span aria-hidden="true">↗</span></a
>{t("在 GitHub 探索 WheelPlay")}<span aria-hidden="true">↗</span></a
>
</section>
93 changes: 42 additions & 51 deletions website/src/components/ExperiencePreview.astro
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
---
import { useTranslations } from "../i18n";
const { t } = useTranslations(Astro.url.pathname);
---

<section
class="demo-section container"
aria-label="WheelPlay 工作方式交互示意"
aria-label={t("WheelPlay 工作方式交互示意")}
>
<div class="workspace">
<div class="workspace-bar">
<div class="window-dots" aria-hidden="true">
<i></i><i></i><i></i>
</div>
<span class="workspace-title"
>WheelPlay <span>/</span> 浏览器里的驾驶搭档</span
><span class="demo-badge">交互示意</span>
>WheelPlay <span>/</span>{t("浏览器里的驾驶搭档")}</span
><span class="demo-badge">{t("交互示意")}</span>
</div>
<div class="workspace-body">
<aside class="source-panel" aria-label="设备连接说明">
<aside class="source-panel" aria-label={t("设备连接说明")}>
<div class="panel-heading">
<span class="small-icon"
><svg
Expand All @@ -23,7 +28,7 @@
aria-hidden="true"
>
<path d="M5 4v10h14m-5-5 5 5-5 5" /></svg></span
><span>连接你的世界</span><span class="mono">01 — 03</span>
><span>{t("连接你的世界")}</span><span class="mono">01 — 03</span>
</div>
<div class="device-flow">
<div class="device-step">
Expand All @@ -34,11 +39,11 @@
></span>
<div>
<strong>iPhone</strong>
<p>你的 CarPlay,原样带来</p>
<p>{t("你的 CarPlay,原样带来")}</p>
</div>
<span class="step-number">01</span>
</div>
<div class="flow-line"><span>USB 或无线连接</span></div>
<div class="flow-line"><span>{t("USB 或无线连接")}</span></div>
<div class="device-step active">
<img
class="device-icon app-icon"
Expand All @@ -49,20 +54,20 @@
/>
<div>
<strong>Android + WheelPlay</strong>
<p>小小的连接中枢</p>
<p>{t("小小的连接中枢")}</p>
</div>
<span class="step-number">02</span>
</div>
<div class="flow-line"><span>同一局域网</span></div>
<div class="flow-line"><span>{t("同一局域网")}</span></div>
<div class="device-step">
<span class="device-icon"
><svg viewBox="0 0 24 24" aria-hidden="true">
<rect x="2" y="4" width="20" height="14" rx="2" />
<path d="M8 22h8m-4-4v4" /></svg
></span>
<div>
<strong>车机浏览器</strong>
<p>打开网页,即可显示与触控</p>
<strong>{t("车机浏览器")}</strong>
<p>{t("打开网页,即可显示与触控")}</p>
</div>
<span class="step-number">03</span>
</div>
Expand All @@ -73,8 +78,8 @@
<path d="m8 12 3 3 5-6" />
</svg>
<div>
<strong>连接留在局域网</strong>
<p>串流无需额外部署云端服务器。</p>
<strong>{t("连接留在局域网")}</strong>
<p>{t("串流无需额外部署云端服务器。")}</p>
</div>
</div>
</aside>
Expand All @@ -83,7 +88,7 @@
<div
class="preview-tabs"
role="tablist"
aria-label="切换体验示意"
aria-label={t("切换体验示意")}
>
<button
id="tab-navigation"
Expand All @@ -92,8 +97,7 @@
aria-selected="true"
aria-controls="panel-navigation"
data-view="navigation"
>
导航视图</button
>{t("导航视图")}</button
><button
id="tab-music"
type="button"
Expand All @@ -102,8 +106,7 @@
aria-controls="panel-music"
tabindex="-1"
data-view="music"
>
音乐视图</button
>{t("音乐视图")}</button
><button
id="tab-connection"
type="button"
Expand All @@ -112,12 +115,10 @@
aria-controls="panel-connection"
tabindex="-1"
data-view="connection"
>
连接流程
</button>
>{t("连接流程")}</button>
</div>
<span class="preview-label"
><span class="status-dot"></span>体验预览</span
><span class="status-dot"></span>{t("体验预览")}</span
>
</div>
<div class="display-shell">
Expand Down Expand Up @@ -195,11 +196,9 @@
stroke-width="4"
/>
<g fill="#8b988e" font-size="11" font-family="sans-serif">
<text x="248" y="194">城市公园</text>
<text x="480" y="259">滨江绿道</text>
<text x="62" y="246" transform="rotate(-5 62 246)">
梧桐路
</text>
<text x="248" y="194">{t("城市公园")}</text>
<text x="480" y="259">{t("滨江绿道")}</text>
<text x="62" y="246" transform="rotate(-5 62 246)">{t("梧桐路")}</text>
</g>
<g transform="translate(202 245)">
<circle r="24" fill="#5087f2" opacity=".15" />
Expand All @@ -221,13 +220,13 @@
/></svg
></span>
<div>
<strong>前方 300 米</strong
><span>右转,驶入新的旅程</span>
<strong>{t("前方 300 米")}</strong
><span>{t("右转,驶入新的旅程")}</span>
</div>
</div>
<div class="arrival-card">
<strong>12 <small>分钟</small></strong
><span>6.8 公里 · 一路向前</span
<strong>12 <small>{t("分钟")}</small></strong
><span>{t("6.8 公里 · 一路向前")}</span
><span class="route-symbol" aria-hidden="true">↗</span>
</div>
</div>
Expand All @@ -236,16 +235,16 @@
<div class="album-art" aria-hidden="true">
<span></span>
</div>
<strong>On the road</strong><span>你的随行歌单</span>
<strong>On the road</strong><span>{t("你的随行歌单")}</span>
<div class="music-controls" aria-hidden="true">
‹ <span>Ⅱ</span> ›
</div>
</div>
<div class="destination-widget">
<span class="home-symbol" aria-hidden="true">⌂</span>
<div>
<strong>下一站,回家</strong
><span>熟悉的路,熟悉的体验</span>
<strong>{t("下一站,回家")}</strong
><span>{t("熟悉的路,熟悉的体验")}</span>
</div>
</div>
</div>
Expand All @@ -264,13 +263,10 @@
</div>
<div class="music-copy">
<span class="eyebrow">YOUR EVERYDAY SOUNDTRACK</span>
<h3>让喜欢的音乐,<br />陪你多走一程。</h3>
<p>
在 CarPlay 中使用你的音乐 App。<br />默认由 Android
输出音频,也可切换到浏览器。
</p>
<h3>{t("让喜欢的音乐,")}<br />{t("陪你多走一程。")}</h3>
<p>{t("在 CarPlay 中使用你的音乐 App。")}<br />{t("默认由 Android 输出音频,也可切换到浏览器。")}</p>
<div class="illustrated-track">
<span>On the road</span><span>示意歌单 · 不播放音频</span>
<span>On the road</span><span>{t("示意歌单 · 不播放音频")}</span>
</div>
<div class="track-progress" aria-hidden="true">
<span></span>
Expand Down Expand Up @@ -301,24 +297,22 @@
/>
<circle cx="12" cy="20" r=".8" /></svg
></span>
<h3>第一次配对,<br />下一次更从容。</h3>
<p>
用 WheelPlay 扫描车机网页二维码,<br />或在车机输入配对码。确认后,启动显示。
</p>
<h3>{t("第一次配对,")}<br />{t("下一次更从容。")}</h3>
<p>{t("用 WheelPlay 扫描车机网页二维码,")}<br />{t("或在车机输入配对码。确认后,启动显示。")}</p>
<div
class="pair-code"
aria-label="示例配对码,不可用于实际连接"
aria-label={t("示例配对码,不可用于实际连接")}
>
<span>1</span><span>2</span><span>3</span><span>4</span
><span>5</span><span>6</span>
</div>
<span class="connection-footnote"
>示例配对码 · 已记住的浏览器可恢复配对</span
>{t("示例配对码 · 已记住的浏览器可恢复配对")}</span
>
</div>
</div>
<div class="preview-status">
<span><span class="status-dot"></span>浏览器显示与触控</span
<span><span class="status-dot"></span>{t("浏览器显示与触控")}</span
><span class="mono" id="preview-mode"
>NAVIGATION / PREVIEW</span
>
Expand All @@ -336,10 +330,7 @@
aria-hidden="true"
>
<path d="M5 4v10h14m-5-5 5 5-5 5" /></svg
></span>
上方为交互示意,并非真实 CarPlay 截图或在线连接入口;实际界面由 iPhone
与所用 App 决定。
</p>
></span>{t("上方为交互示意,并非真实 CarPlay 截图或在线连接入口;实际界面由 iPhone 与所用 App 决定。")}</p>
</section>

<script>
Expand Down
Loading
Loading