91 lines
4.4 KiB
Markdown
91 lines
4.4 KiB
Markdown
# AGENTS.md — @app/web
|
||
|
||
## 职责
|
||
|
||
**薄 SSR** Astro 前端(Node standalone):布局 / head / SEO / 中间件服务端渲染;页面主体为 React 客户端组件(`client:load`)。另含 tRPC HTTP 适配、SEO 文本端点、**i18n 路由**。
|
||
|
||
产品页面:首页、鉴权、仪表盘、媒体库 / 浏览 / 播放 / 挂载 / 弹幕设置与错误页。视觉遵循仓库根 `DESIGN.md` 与 `@app/design-tokens`。
|
||
|
||
## i18n
|
||
|
||
- 语言:`zh-CN`(`/zh-CN/...`)、`en`(`/en/...`)。**中文也带前缀**,不把中文留在裸 `/`。
|
||
- **单套路由**:`src/pages/[locale]/...` + `src/views/*`;禁止再复制 `pages/zh-CN`、`pages/en` 目录。
|
||
- 文案:`@app/i18n` 的 `t(locale, key)`;React island 传 `locale` prop,不引入 i18next。
|
||
- 裸 `/`:`src/middleware.ts` 按 cookie `app-lang` → `Accept-Language` 跳 `/zh-CN` 或 `/en`;响应 `Vary: Accept-Language`;非法/大小写 `zh-cn` 规范化。
|
||
- 手动切换:header 语言链接写 cookie 后跳转(布局内联脚本)。
|
||
- 设计说明:`docs/superpowers/specs/2026-09-24-i18n-design.md`。
|
||
|
||
## 结构
|
||
|
||
```
|
||
src/
|
||
pages/
|
||
[locale]/
|
||
index.astro | dashboard.astro | library.astro | browse.astro
|
||
watch.astro | mounts.astro | danmaku.astro | settings.astro
|
||
auth/login.astro | auth/register.astro
|
||
auth/forgot-password.astro | auth/reset-password.astro
|
||
api/trpc/[...trpc].ts | api/stream.ts | api/users.ts
|
||
sitemap.xml.ts | robots.txt.ts | llms.txt.ts | llms-full.txt.ts
|
||
403.astro | 404.astro | 500.astro
|
||
views/ # SSR 壳 + seo/nav(每页一个)
|
||
home.astro | dashboard.astro | library.astro | browse.astro
|
||
watch.astro | mounts.astro | danmaku.astro | auth.astro | error.astro
|
||
middleware.ts # 裸 / 语言检测跳转 + locale 规范化
|
||
layouts/AppLayout.astro
|
||
components/
|
||
pages/ # 薄 SSR 主体(client:load)
|
||
HomeBody.tsx | DashboardBody.tsx | LibraryBody.tsx | BrowseBody.tsx
|
||
WatchBody.tsx | MountsBody.tsx | DanmakuSettingsBody.tsx
|
||
AuthBody.tsx | ErrorBody.tsx
|
||
UserList.tsx | UserMenu.tsx | ThemeSwitch.tsx | AuthForm.tsx | errors/*
|
||
lib/
|
||
trpc.ts | seo.ts(getSiteSeo(locale))| nav.ts | theme.ts
|
||
danmaku-render.ts | errors.ts | utils.ts(cn re-export)
|
||
styles/globals.css
|
||
astro.config.ts
|
||
```
|
||
|
||
路径别名
|
||
|
||
- `~/*`、`@/*` → `src/*`
|
||
- `@app/i18n` / `@app/trpc` / `@app/types` / `@app/db` / `@app/seo-geo` → 各包 `dist`(astro.config.ts)
|
||
- `@app/ui` → `packages/ui/src`(源码直出)
|
||
- typecheck 时 tsconfig paths 指向各包 `src`——**改上游后先 build 再 dev/build web**
|
||
|
||
## 页面与 SEO(薄 SSR)
|
||
|
||
- **服务端**:`AppLayout.astro`(head、导航、脚注)、`seo` prop、middleware(locale / 鉴权跳转)、API / sitemap 等端点。
|
||
- **客户端**:`views/*` 只保留壳,主体为 `components/pages/*Body.tsx`,统一 `client:load`。
|
||
- 布局统一走 `AppLayout.astro`,必传 `locale`,通过 `seo` prop 传 `PageSeoInput`。
|
||
- 站点 SEO:`lib/seo.ts` 的 `getSiteSeo(locale)`;sitemap 双语 URL + hreflang `alternates`。
|
||
- 新公开页面:登记 `PUBLIC_PATHS` / views,并同步 `getSiteSeo` 的 `llms.pages` 与 sitemap;主体写成 `*Body.tsx`。
|
||
- 导航项集中在 `lib/nav.ts`,改菜单只动这一处。
|
||
|
||
## React islands
|
||
|
||
- 页面主体默认 `client:load`(薄 SSR);局部岛仍可用 `client:visible`。
|
||
- 文案:`import { t } from "@app/i18n"` + `locale` prop;不要绑 i18next Provider。
|
||
- tRPC:组件内 `QueryClientProvider` + trpc Provider(参考 `UserList.tsx`)。
|
||
- UI:`@app/ui`(通用基础组件)+ `cn()`(`~/lib/utils` re-export);颜色用 CSS 变量。
|
||
- 播放页弹幕渲染逻辑在 `lib/danmaku-render.ts`,与 `WatchBody` 解耦。
|
||
|
||
## 修改指南
|
||
|
||
- **加文案**:先改 `packages/i18n/src/messages/zh-CN.ts`,再补 `en.ts`。
|
||
- **加业务页面**:沿用 `views/*` + `components/pages/*Body` 薄 SSR 模式扩展。
|
||
- **调 API**:优先 tRPC(`trpc.media.*`);`api/users.ts` 仅演示;`api/stream.ts` 为受保护的媒体流。
|
||
- **主题**:`localStorage` key `app-theme`;语言 cookie `app-lang`。
|
||
- Astro 保留字:组件 props 避免 `slot`。
|
||
|
||
## 命令
|
||
|
||
```bash
|
||
yarn workspace @app/web typecheck
|
||
yarn workspace @app/web lint
|
||
yarn workspace @app/web dev # :4321
|
||
yarn workspace @app/web build
|
||
yarn dev:web
|
||
yarn test:e2e # Playwright(e2e/ 目录)
|
||
```
|