- Rewrote DocsListPage and DocDetailPage with landing.css aesthetic (icon cards, skeleton loader, prose styles, CTA box) - Added docs-specific CSS to landing.css - Created image-to-latex, copy-to-word, ocr-accuracy, pdf-extraction articles in both English and Chinese - Updated DocsSeoSection guide cards to link to real doc slugs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
130 lines
5.9 KiB
Markdown
130 lines
5.9 KiB
Markdown
# Landing Page Refactor — Design Spec
|
||
**Date:** 2026-03-26
|
||
**Status:** Approved
|
||
|
||
## Goal
|
||
Replace all existing marketing home components with content and styles from `texpixel-landing.html`. The UI/UX must exactly match the reference file. The home page is a marketing/broadcast page; all CTAs navigate to `/app`.
|
||
|
||
---
|
||
|
||
## CSS Strategy
|
||
- Extract the full `<style>` block (lines 10–1593) from `texpixel-landing.html` into `src/styles/landing.css`.
|
||
- **Scope all rules** under a `.marketing-page` wrapper class to prevent bleed into the `/app` workspace.
|
||
- Body-level rules (`body { background }`, `body::before` grid overlay) are converted to `.marketing-page` and `.marketing-page::before` respectively.
|
||
- `:root` CSS variable declarations are kept as-is since landing variables use different names (`--primary`, `--bg`, etc.) from existing workspace variables (`--color-primary`, `--color-bg`). No conflict — they coexist.
|
||
- **Do NOT import in `main.tsx`** — import directly in `MarketingLayout.tsx` via `import '../styles/landing.css'` so it only applies to marketing routes.
|
||
- `MarketingLayout.tsx` wrapper div gets `className="marketing-page"`.
|
||
- `index.css` Tailwind layer remains untouched.
|
||
- Add Google Fonts to `index.html` `<head>`: Lora (serif, weights 400/600/700) and JetBrains Mono (monospace, weights 400/500). DM Sans already present.
|
||
|
||
---
|
||
|
||
## Component Mapping
|
||
|
||
| Reference section | Target file | Action |
|
||
|---|---|---|
|
||
| `<nav>` | `src/components/layout/MarketingNavbar.tsx` | Replace |
|
||
| `.hero` | `src/components/home/HeroSection.tsx` | Replace |
|
||
| `.product-suite` | `src/components/home/ProductSuiteSection.tsx` | New |
|
||
| `.core-features` | `src/components/home/FeaturesSection.tsx` | Replace |
|
||
| `.showcase` | `src/components/home/ShowcaseSection.tsx` | New |
|
||
| `.user-love` | `src/components/home/TestimonialsSection.tsx` | New |
|
||
| `.pricing` | `src/components/home/PricingSection.tsx` | Replace |
|
||
| `.docs-seo` | `src/components/home/DocsSeoSection.tsx` | New |
|
||
| `<footer>` | `src/components/layout/Footer.tsx` | Replace |
|
||
|
||
### Delete (no reference equivalent)
|
||
- `src/components/home/HowItWorksSection.tsx`
|
||
- `src/components/home/ContactSection.tsx`
|
||
|
||
---
|
||
|
||
## MarketingLayout.tsx
|
||
- Wrap outlet in `<div className="marketing-page">` — applies scoped landing CSS
|
||
- Render three `.glow-blob` divs (`.glow-blob-1`, `.glow-blob-2`, `.glow-blob-3`) as direct children of the `.marketing-page` wrapper — these are `position: fixed` ambient background elements visible across all marketing pages.
|
||
|
||
---
|
||
|
||
## HomePage.tsx
|
||
Update to render sections in order:
|
||
```
|
||
HeroSection
|
||
<div className="section-divider" />
|
||
ProductSuiteSection
|
||
FeaturesSection
|
||
ShowcaseSection
|
||
<div className="section-divider" />
|
||
TestimonialsSection
|
||
<div className="section-divider" />
|
||
PricingSection
|
||
<div className="section-divider" />
|
||
DocsSeoSection
|
||
```
|
||
Section dividers are plain `<div className="section-divider" />` JSX inlined in `HomePage.tsx` — no abstraction needed.
|
||
|
||
---
|
||
|
||
## Navbar (MarketingNavbar.tsx)
|
||
- Sticky, height 72px, backdrop blur on scroll (existing scroll state logic kept)
|
||
- Logo: SVG icon (lines symbol) + "TexPixel" text — **remove `font-display` Tailwind class** from logo `<span>`, replace with `style={{ fontFamily: "'Lora', serif" }}` to avoid Plus Jakarta Sans conflict
|
||
- Nav links: Home `/`, Docs `/docs`, Blog `/blog`, Pricing `#pricing` (anchor on home only), **no Contact link** — also remove the existing `anchorLinks` `#contact` entry
|
||
- Right side:
|
||
- Lang switch button (existing `useLanguage` toggle)
|
||
- User avatar/menu using `const { user, signOut } = useAuth()` — show avatar dropdown when `user !== null`; show "登录/Login" CTA button when `user === null`
|
||
- Avatar dropdown items: "启动应用" → `/app`, then logout (calls `signOut()`). **No profile settings link** (route does not exist — omitted)
|
||
- "Try Free" CTA button → `/app`
|
||
- i18n: `useLanguage` for all labels
|
||
- Remove unused `t.marketing.nav.contact` references from this component
|
||
|
||
---
|
||
|
||
## JS Behaviors → React hooks/useEffect
|
||
|
||
### Scroll Reveal Hook
|
||
- **Create `src/hooks/` directory** (does not exist yet)
|
||
- Create `src/hooks/useScrollReveal.ts` — sets up a single `IntersectionObserver` targeting all `.reveal` elements, adds `.visible` class on intersection
|
||
- Called once in `HomePage.tsx` via `useScrollReveal()`
|
||
|
||
### Nav Active on Scroll
|
||
- `useEffect` in `MarketingNavbar.tsx` — watches `window.scroll`, adds `.active` class to nav link matching current section `id`
|
||
|
||
### Testimonial Carousel (TestimonialsSection.tsx)
|
||
- React state: `currentPage` (0-indexed), 6 cards, 3 visible, 4 pages
|
||
- `useEffect` auto-advances every 5s, resets on manual navigation
|
||
- Prev/Next buttons + rendered dots
|
||
- Window resize recalcs slide offset
|
||
|
||
### Typing Effect (HeroSection.tsx)
|
||
- `useRef` on `.output-code` element
|
||
- `useEffect` cycles through 3 LaTeX strings every 3500ms via `innerHTML` + cursor span
|
||
|
||
---
|
||
|
||
## CTA Links
|
||
- "Try TexPixel", "Try Free", "Get Started" (Free/Monthly/Quarterly plans) → `<Link to="/app">`
|
||
- "Buy Desktop" → `<Link to="/app">` (placeholder, no separate purchase flow)
|
||
- Doc card links → `/docs`
|
||
- Footer blog link → `/blog`
|
||
- Pricing anchor `#pricing` → `<a href="#pricing">`
|
||
|
||
---
|
||
|
||
## Content / i18n
|
||
- All text from the reference HTML is hardcoded in components (Chinese/English bilingual where reference already has it)
|
||
- Existing `useLanguage` / `t` translations are used where keys already exist
|
||
- New section text is **hardcoded** (not added to `translations.ts`) — the reference HTML content is the source of truth; full i18n for new sections is out of scope for this refactor
|
||
|
||
---
|
||
|
||
## Cleanup
|
||
- Remove `contact` key from `marketing.nav` in `src/lib/translations.ts` (both `en` and `zh` blocks) — becomes dead code after ContactSection and `#contact` link are removed.
|
||
|
||
---
|
||
|
||
## What Does NOT Change
|
||
- `src/App.tsx`, routing (`AppRouter.tsx`), auth system, workspace (`WorkspacePage`)
|
||
- `index.css` Tailwind layer
|
||
- Docs/Blog pages
|
||
- `SEOHead` component usage in `HomePage.tsx`
|
||
- `tailwind.config.js`
|