Files
eryao/.trellis/spec/web/index.md
T
zl-q c12320cb79 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
2026-05-09 12:11:10 +08:00

8.0 KiB

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