feat(web): rebuild web with Astro 6 + React 19 + Tailwind 4
Replace static HTML website with Astro SSG framework: - Astro 6 + React 19 (client islands) + Tailwind CSS 4 + shadcn/ui - i18n: zh/zh_Hant/en with URL prefix routing - Pages: Landing, Features, Pricing, About, Privacy, Terms (3 locales) - Responsive full-width layout with scroll reveal animations - Cyber gradient theme with particle effects inspired by Kimi - Features page: alternating layout with hexagram illustrations - Legal pages: markdown rendering with side info card - Language switcher preserves current page path - Assets shared via symlinks to web/design/assets/ (no duplication) Tech decisions documented in .trellis/spec/web/index.md Task: .trellis/tasks/05-08-web-astro-react-tailwind-shadcn-ui
This commit is contained in:
@@ -0,0 +1,232 @@
|
||||
# Web Development Guidelines
|
||||
|
||||
> Astro 6 + React 19 + Tailwind CSS 4 + shadcn/ui
|
||||
|
||||
---
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Layer | Technology | Version |
|
||||
|-------|-----------|---------|
|
||||
| Framework | Astro | 6.x |
|
||||
| Interactive UI | React | 19.x (client-only, no RSC) |
|
||||
| Styling | Tailwind CSS | 4.x (via `@tailwindcss/vite`) |
|
||||
| Component Library | shadcn/ui | latest |
|
||||
| Language | TypeScript | 5.x (strict) |
|
||||
| i18n | Built-in (type-safe object in `src/i18n/utils.ts`) | - |
|
||||
| Markdown Rendering | `marked` | latest |
|
||||
| Auth | Supabase Auth JS SDK | - |
|
||||
|
||||
### Architecture Decision
|
||||
|
||||
- **Astro SSG** for marketing/public pages (SEO-critical)
|
||||
- **React client islands** for interactive parts (Login, Dashboard, Notifications)
|
||||
- **No React Server Components** — CVE-2025-55182 risk eliminated
|
||||
- **No Next.js** — multiple critical CVEs (CVE-2025-55182, CVE-2025-29927, CVE-2025-66478)
|
||||
|
||||
### Actual Dependencies
|
||||
|
||||
```
|
||||
astro, @astrojs/react, react, react-dom, @tailwindcss/vite, tailwindcss, marked
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pre-Development Checklist
|
||||
|
||||
Before writing web code, read:
|
||||
|
||||
- [ ] This index
|
||||
- [ ] Design file: `web/design/eryao.pen`
|
||||
- [ ] Backend API contracts: `docs/protocols/`
|
||||
- [ ] Error code mapping: `docs/protocols/common/http-error-codes.md`
|
||||
- [ ] Mobile i18n files (for translation sync): `apps/lib/l10n/app_*.arb`
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
web/
|
||||
├── design/ # Pencil design files (.pen)
|
||||
│ ├── eryao.pen
|
||||
│ └── assets/ # Shared assets (images, legal)
|
||||
│ ├── images/
|
||||
│ └── legal/{zh,zh_Hant,en}/
|
||||
├── public/
|
||||
│ ├── images -> ../design/assets/images # symlink, no duplication
|
||||
│ ├── legal -> ../design/assets/legal # symlink, no duplication
|
||||
│ ├── favicon.ico
|
||||
│ └── favicon.svg
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ │ ├── Navbar.astro # Marketing nav (responsive, lang switcher)
|
||||
│ │ ├── Footer.astro # Marketing footer (responsive)
|
||||
│ │ ├── Hero.astro # Landing hero section
|
||||
│ │ ├── Showcase.astro # Landing showcase section
|
||||
│ │ ├── Testimonials.astro # Landing testimonials section
|
||||
│ │ ├── CtaSection.astro # Landing CTA section
|
||||
│ │ ├── FeaturesPage.astro # Features grid page
|
||||
│ │ ├── PricingPage.astro # Pricing cards page
|
||||
│ │ ├── AboutPage.astro # About + company info page
|
||||
│ │ └── LegalPage.astro # Markdown legal page (generic)
|
||||
│ ├── layouts/
|
||||
│ │ └── Marketing.astro # Nav + content + footer + scroll animations
|
||||
│ ├── pages/
|
||||
│ │ ├── index.astro # Root redirect -> /zh/
|
||||
│ │ ├── {zh,zh_Hant,en}/
|
||||
│ │ │ ├── index.astro # Landing
|
||||
│ │ │ ├── features.astro
|
||||
│ │ │ ├── pricing.astro
|
||||
│ │ │ ├── about.astro
|
||||
│ │ │ ├── privacy.astro
|
||||
│ │ │ └── terms.astro
|
||||
│ ├── i18n/
|
||||
│ │ └── utils.ts # Type-safe translations (all inline)
|
||||
│ └── styles/
|
||||
│ ├── global.css # Tailwind entry
|
||||
│ └── animations.css # Scroll reveal animations
|
||||
├── astro.config.mjs
|
||||
├── tsconfig.json
|
||||
└── package.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Responsive Layout
|
||||
|
||||
**All pages must be fully responsive: full-width sections, no fixed pixel widths.**
|
||||
|
||||
### Layout Principles
|
||||
|
||||
1. **Full-width sections** — Each section spans `w-full`, content is centered with `max-w-7xl mx-auto`
|
||||
2. **No fixed pixel widths** — Use `w-full`, `max-w-*`, and `flex/grid` for all layouts
|
||||
3. **Mobile-first** — Base styles target mobile, `md:` breakpoint for desktop
|
||||
4. **Viewport-filling sections** — Hero and CTA use `min-h-screen` or generous padding to fill viewport
|
||||
5. **Smooth scroll transitions** — Each section flows into the next with gradients or color changes
|
||||
|
||||
### Breakpoints
|
||||
|
||||
| Breakpoint | Target |
|
||||
|-----------|--------|
|
||||
| Base (< 768px) | Mobile phones |
|
||||
| `md:` (>= 768px) | Tablets and desktop |
|
||||
|
||||
### Section Patterns
|
||||
|
||||
```
|
||||
Hero: w-full, min-h-screen, bg-gradient, centered content
|
||||
Showcase: w-full, flex-col md:flex-row, gap, centered max-w
|
||||
Testimonials: w-full, bg-slate-900, grid cols-1 md:cols-3
|
||||
CTA: w-full, bg-violet-600, centered
|
||||
Footer: w-full, bg-slate-950, responsive flex
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Design Tokens
|
||||
|
||||
All colors from design map directly to Tailwind defaults:
|
||||
|
||||
| Token | Tailwind | Hex |
|
||||
|-------|----------|-----|
|
||||
| Primary | `violet-600` | #7C3AED |
|
||||
| Primary light | `violet-100` | — |
|
||||
| Background | `white` | #FFFFFF |
|
||||
| Surface | `slate-50` | #F8FAFC |
|
||||
| Dark bg | `slate-900` | #0F172A |
|
||||
| Footer bg | `slate-950` | #020617 |
|
||||
| Border | `slate-200` | #E2E8F0 |
|
||||
| Warning bg | `amber-50` | #FFFBEB |
|
||||
| Gradient top | `white` -> `violet-50` | — |
|
||||
|
||||
---
|
||||
|
||||
## Scroll Animations
|
||||
|
||||
Defined in `src/styles/animations.css`, triggered by `IntersectionObserver` in `Marketing.astro`.
|
||||
|
||||
| Class | Effect | Use Case |
|
||||
|-------|--------|----------|
|
||||
| `.reveal` | Fade up (translateY 24px) | Default for most elements |
|
||||
| `.reveal-left` | Slide from left | Showcase left column |
|
||||
| `.reveal-right` | Slide from right | Showcase right column |
|
||||
| `.reveal-scale` | Scale in (0.95 -> 1) | CTA section |
|
||||
| `.stagger-1` to `.stagger-4` | Delay 0.1s-0.4s | Grouped elements (cards, grid items) |
|
||||
|
||||
- All animations: `0.6-0.7s`, `cubic-bezier(0.22, 1, 0.36, 1)` (ease-out-quint)
|
||||
- `prefers-reduced-motion: reduce` disables all animations
|
||||
- Observer `rootMargin: 0px 0px -60px 0px` for pre-trigger
|
||||
- Elements are `opacity: 0` until `.visible` class is added, then `animation-fill-mode: forwards`
|
||||
|
||||
---
|
||||
|
||||
## i18n (CRITICAL)
|
||||
|
||||
**Every user-visible text must use i18n keys. No hardcoded strings.**
|
||||
|
||||
### Supported Locales
|
||||
| Code | Language | Brand Name |
|
||||
|------|----------|------------|
|
||||
| `zh` | 简体中文 | 觅爻签问 |
|
||||
| `zh_Hant` | 繁體中文 | 覓爻簽問 |
|
||||
| `en` | English | MeiYao Divination |
|
||||
|
||||
### Implementation
|
||||
|
||||
- All translations are in `src/i18n/utils.ts` as a typed `Record<Locale, Translations>` object
|
||||
- Access via `t(locale, 'section')` which returns the section object (e.g., `t(locale, 'nav').features`)
|
||||
- URL strategy: `/{locale}/path` prefix (e.g., `/zh/`, `/en/`)
|
||||
- Default locale: `zh`, root `/` redirects to `/zh/`
|
||||
- Config in `astro.config.mjs` with `prefixDefaultLocale: true`
|
||||
|
||||
### Rules
|
||||
1. **All text must come from `t()`** — never inline strings
|
||||
2. **Brand name** is always from `footer.brandName` (consistent across Navbar/Footer)
|
||||
3. **Check Flutter i18n first** (`apps/lib/l10n/app_*.arb`) before inventing translations
|
||||
4. **Legal content** loaded from `public/legal/{locale}/` markdown files
|
||||
|
||||
---
|
||||
|
||||
## Assets
|
||||
|
||||
- Shared assets live in `web/design/assets/` (used by Pencil)
|
||||
- `web/public/images` and `web/public/legal` are **symlinks** to `../design/assets/*`
|
||||
- **Never duplicate** assets — always use symlinks or references
|
||||
|
||||
---
|
||||
|
||||
## Cross-Layer Contracts
|
||||
|
||||
### API Integration
|
||||
- Backend: FastAPI REST endpoints (see `docs/protocols/`)
|
||||
- Auth: Supabase Auth JS SDK (client-side)
|
||||
- Error format: RFC 7807 `ApiProblem` (same as mobile)
|
||||
|
||||
### Brand Consistency (Flutter app)
|
||||
- App title: "觅爻签问" / "MeiYao Divination" (NOT "MiYao")
|
||||
- Company: 洵觅科技(深圳)有限公司 / Xunmee Technology (Shenzhen) Co., Ltd.
|
||||
- Contact: xuyunlong@xunmee.com
|
||||
- ICP: 粤ICP备2025428416号-1A
|
||||
|
||||
---
|
||||
|
||||
## Quality Rules
|
||||
|
||||
### Forbidden
|
||||
- Do not use React Server Components (RSC)
|
||||
- Do not import server-only modules in client islands
|
||||
- Do not hardcode colors outside Tailwind tokens
|
||||
- Do not use fixed pixel widths for layout (use responsive utilities)
|
||||
- Do not use `any` in TypeScript
|
||||
- Do not use third-party shadcn registries (official only)
|
||||
- Do not duplicate assets — use symlinks
|
||||
|
||||
### Required
|
||||
- All pages must be fully responsive (mobile + desktop)
|
||||
- All sections must be full-width with centered content
|
||||
- All pages must pass Lighthouse SEO >= 95 (marketing pages)
|
||||
- All interactive components must be accessible (ARIA)
|
||||
- `npm audit` must be clean before merge
|
||||
- TypeScript strict mode enabled
|
||||
- `prefers-reduced-motion` must disable animations
|
||||
@@ -0,0 +1,2 @@
|
||||
{"file": ".trellis/spec/web/index.md", "reason": "Verify no hardcoded strings (i18n), correct Tailwind tokens, no RSC usage"}
|
||||
{"file": ".trellis/tasks/05-08-web-astro-react-tailwind-shadcn-ui/prd.md", "reason": "Acceptance criteria: pixel match, SEO >= 95, npm audit clean"}
|
||||
@@ -0,0 +1,3 @@
|
||||
{"file": ".trellis/spec/web/index.md", "reason": "Web tech stack, design tokens, i18n rules, quality constraints"}
|
||||
{"file": ".trellis/tasks/05-08-web-astro-react-tailwind-shadcn-ui/prd.md", "reason": "Task PRD with design analysis, architecture, acceptance criteria"}
|
||||
{"file": "web/design/eryao.pen", "reason": "Pencil design file - Landing Page layout, colors, typography, spacing"}
|
||||
@@ -0,0 +1,137 @@
|
||||
# Web 端技术选型 PRD
|
||||
|
||||
## 背景
|
||||
|
||||
eryao 项目需要建设 Web 端。移动端已有 Flutter 应用(iOS/Android),后端为 Python FastAPI + Supabase。Pencil 设计稿已完成(`web/design/eryao.pen`),包含 19 个页面。
|
||||
|
||||
## 设计稿分析
|
||||
|
||||
### 页面分类
|
||||
|
||||
**营销/公开页面**(需要 SEO):
|
||||
- Landing Page — Hero + Showcase + Testimonials + CTA + Footer
|
||||
- Features Page — 功能特性展示
|
||||
- Pricing Page — 定价方案卡片
|
||||
- About Page — 关于我们 + 法律声明
|
||||
- Privacy Policy Page
|
||||
- Terms of Service Page
|
||||
|
||||
**Dashboard/应用页面**(Auth 后 SPA):
|
||||
- Login Page — 登录表单卡片
|
||||
- Dashboard — 侧边栏(260px) + 主区域(1180px) 布局
|
||||
- NotificationPage — 通知列表
|
||||
- 其余 9 个页面(待展开)
|
||||
|
||||
### 设计特征
|
||||
- 宽度 1440px,桌面端为主
|
||||
- 色系:紫色主色(#7C3AED)、深蓝底色(#0F172A/#020617)、白色/浅灰背景
|
||||
- 渐变背景(linear-gradient)、圆角(16px)、阴影(blur 24px)
|
||||
- 全部色值来自 Tailwind CSS 默认色板
|
||||
- i18n 支持:zh / zh_Hant / en(与移动端一致)
|
||||
|
||||
## 技术选型
|
||||
|
||||
### 决策:Astro 5 + React + Tailwind CSS 4 + shadcn/ui
|
||||
|
||||
### 选型理由
|
||||
|
||||
#### 1. Astro 5 作为框架
|
||||
|
||||
| 考量 | 结论 |
|
||||
|------|------|
|
||||
| 营销页 SEO | Astro 默认零 JS 输出,SSG 开箱即用,SEO 最优 |
|
||||
| Dashboard SPA | React islands 模式,客户端全功能渲染 |
|
||||
| 安全性 | 静态生成,无服务端运行时,攻击面极小 |
|
||||
| 无已知 CVE | 搜索未发现 Astro 框架本身的 CVE 记录 |
|
||||
|
||||
**为什么不用 Next.js:**
|
||||
- CVE-2025-55182(CVSS 10.0 "React2Shell")RCE,已被武器化
|
||||
- CVE-2025-29927 中间件鉴权绕过
|
||||
- CVE-2025-66478 Next.js 对应编号,766 台主机被入侵
|
||||
- Server Components 攻击面大,对于本项目过度设计
|
||||
|
||||
**为什么不用 Vite + React SPA:**
|
||||
- 营销页 SEO 差,需要额外 SSR 方案
|
||||
- 两个场景(营销+应用)用一套框架更简洁
|
||||
|
||||
#### 2. React 作为交互层
|
||||
|
||||
- shadcn/ui 原生 React,组件覆盖度最高
|
||||
- Astro islands 一等公民支持
|
||||
- 生态最大,Dashboard 复杂交互组件丰富
|
||||
|
||||
**关于 CVE-2025-55182:**
|
||||
该漏洞仅影响 React Server Components(RSC),即 Next.js App Router 服务端渲染场景。我们的架构使用 Astro SSG + React 客户端 islands,不使用 RSC,漏洞不适用。
|
||||
|
||||
#### 3. Tailwind CSS 4
|
||||
|
||||
- 设计稿色值全部来自 Tailwind 色板,零适配成本
|
||||
- 渐变、flexbox、阴影、圆角全部原生支持
|
||||
- 无已知直接漏洞(Snyk 确认)
|
||||
- v4 已修复 v3 的 glob 传递依赖问题
|
||||
|
||||
#### 4. shadcn/ui
|
||||
|
||||
- 源码级复制,可完全自定义,无锁定
|
||||
- Card / Button / Input / Form / Sidebar 等组件与设计稿高度吻合
|
||||
- 无已知直接漏洞(Snyk 确认)
|
||||
- 只使用官方 registry,避免第三方 registry 注入风险
|
||||
|
||||
### 架构概览
|
||||
|
||||
```
|
||||
web/
|
||||
├── src/
|
||||
│ ├── components/ # 共享 UI 组件(shadcn/ui + 自定义)
|
||||
│ │ ├── ui/ # shadcn/ui 组件
|
||||
│ │ ├── Navbar.astro # 营销页导航栏
|
||||
│ │ ├── Footer.astro # 营销页页脚
|
||||
│ │ └── Sidebar.tsx # Dashboard 侧边栏(React island)
|
||||
│ ├── layouts/
|
||||
│ │ ├── Marketing.astro # 营销页布局(Navbar + Footer)
|
||||
│ │ └── Dashboard.astro # Dashboard 布局(Sidebar + Main)
|
||||
│ ├── pages/
|
||||
│ │ ├── index.astro # Landing Page
|
||||
│ │ ├── features.astro # Features Page
|
||||
│ │ ├── pricing.astro # Pricing Page
|
||||
│ │ ├── about.astro # About Page
|
||||
│ │ ├── privacy.astro # Privacy Policy
|
||||
│ │ ├── terms.astro # Terms of Service
|
||||
│ │ ├── login.astro # Login Page(含 React island)
|
||||
│ │ └── dashboard/
|
||||
│ │ ├── index.astro # Dashboard(含 React island)
|
||||
│ │ └── notifications.astro
|
||||
│ └── styles/
|
||||
│ └── global.css # Tailwind 入口
|
||||
├── astro.config.mjs
|
||||
├── tailwind.config.ts
|
||||
├── tsconfig.json
|
||||
└── package.json
|
||||
```
|
||||
|
||||
### API 集成
|
||||
|
||||
- 后端:FastAPI(已有)
|
||||
- Auth:Supabase Auth JS SDK(客户端)
|
||||
- 数据:通过 FastAPI REST API + Supabase JS SDK
|
||||
|
||||
### i18n 方案
|
||||
|
||||
- 使用 `astro-i18next` 或 `@astrolicious/i18n` 处理 Astro 页面
|
||||
- React islands 使用 `react-i18next`
|
||||
- 翻译文件与移动端共享(zh / zh_Hant / en)
|
||||
|
||||
### 部署
|
||||
|
||||
- 营销页:SSG 静态部署(Vercel / Cloudflare Pages / 自托管)
|
||||
- Dashboard SPA:同一构建产物,客户端渲染
|
||||
- 无需 Node.js 服务端运行时
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 所有设计稿页面可在浏览器中像素级还原
|
||||
- [ ] 营销页 Lighthouse SEO 评分 >= 95
|
||||
- [ ] Dashboard 侧边栏导航和主区域交互正常
|
||||
- [ ] i18n 三语言切换正常
|
||||
- [ ] 无安全漏洞(npm audit clean)
|
||||
- [ ] 设计稿中所有渐变、阴影、圆角、布局精确匹配
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"id": "web-astro-react-tailwind-shadcn-ui",
|
||||
"name": "web-astro-react-tailwind-shadcn-ui",
|
||||
"title": "Web端技术选型:Astro + React + Tailwind + shadcn/ui",
|
||||
"description": "",
|
||||
"status": "in_progress",
|
||||
"dev_type": null,
|
||||
"scope": null,
|
||||
"package": null,
|
||||
"priority": "P2",
|
||||
"creator": "zl-q",
|
||||
"assignee": "zl-q",
|
||||
"createdAt": "2026-05-08",
|
||||
"completedAt": null,
|
||||
"branch": null,
|
||||
"base_branch": "dev",
|
||||
"worktree_path": null,
|
||||
"commit": null,
|
||||
"pr_url": null,
|
||||
"subtasks": [],
|
||||
"children": [],
|
||||
"parent": null,
|
||||
"relatedFiles": [],
|
||||
"notes": "",
|
||||
"meta": {}
|
||||
}
|
||||
Reference in New Issue
Block a user