- 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>
5.9 KiB
5.9 KiB
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) fromtexpixel-landing.htmlintosrc/styles/landing.css. - Scope all rules under a
.marketing-pagewrapper class to prevent bleed into the/appworkspace.- Body-level rules (
body { background },body::beforegrid overlay) are converted to.marketing-pageand.marketing-page::beforerespectively. :rootCSS 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.
- Body-level rules (
- Do NOT import in
main.tsx— import directly inMarketingLayout.tsxviaimport '../styles/landing.css'so it only applies to marketing routes. MarketingLayout.tsxwrapper div getsclassName="marketing-page".index.cssTailwind 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.tsxsrc/components/home/ContactSection.tsx
MarketingLayout.tsx
- Wrap outlet in
<div className="marketing-page">— applies scoped landing CSS - Render three
.glow-blobdivs (.glow-blob-1,.glow-blob-2,.glow-blob-3) as direct children of the.marketing-pagewrapper — these areposition: fixedambient 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-displayTailwind class from logo<span>, replace withstyle={{ 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 existinganchorLinks#contactentry - Right side:
- Lang switch button (existing
useLanguagetoggle) - User avatar/menu using
const { user, signOut } = useAuth()— show avatar dropdown whenuser !== null; show "登录/Login" CTA button whenuser === null - Avatar dropdown items: "启动应用" →
/app, then logout (callssignOut()). No profile settings link (route does not exist — omitted) - "Try Free" CTA button →
/app
- Lang switch button (existing
- i18n:
useLanguagefor all labels - Remove unused
t.marketing.nav.contactreferences 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 singleIntersectionObservertargeting all.revealelements, adds.visibleclass on intersection - Called once in
HomePage.tsxviauseScrollReveal()
Nav Active on Scroll
useEffectinMarketingNavbar.tsx— watcheswindow.scroll, adds.activeclass to nav link matching current sectionid
Testimonial Carousel (TestimonialsSection.tsx)
- React state:
currentPage(0-indexed), 6 cards, 3 visible, 4 pages useEffectauto-advances every 5s, resets on manual navigation- Prev/Next buttons + rendered dots
- Window resize recalcs slide offset
Typing Effect (HeroSection.tsx)
useRefon.output-codeelementuseEffectcycles through 3 LaTeX strings every 3500ms viainnerHTML+ 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/ttranslations 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
contactkey frommarketing.navinsrc/lib/translations.ts(bothenandzhblocks) — becomes dead code after ContactSection and#contactlink are removed.
What Does NOT Change
src/App.tsx, routing (AppRouter.tsx), auth system, workspace (WorkspacePage)index.cssTailwind layer- Docs/Blog pages
SEOHeadcomponent usage inHomePage.tsxtailwind.config.js