feat: optimize docs pages and add 4 new doc articles (en + zh)
- 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>
This commit is contained in:
129
docs/superpowers/specs/2026-03-26-landing-refactor-design.md
Normal file
129
docs/superpowers/specs/2026-03-26-landing-refactor-design.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# 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`
|
||||
Reference in New Issue
Block a user