# Website Restructure Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Restructure the single-page OCR app into a multi-section marketing website with dedicated workspace, docs, and blog pages.
**Architecture:** SPA with react-router-dom layout routes. MarketingLayout (Navbar + Footer) wraps Home/Docs/Blog. AppLayout wraps the OCR workspace at `/app`. Markdown content compiled at build time via a Vite plugin. SEO handled by react-helmet-async + vite-plugin-prerender.
**Tech Stack:** React 18, react-router-dom, Tailwind CSS, react-helmet-async, vite-plugin-prerender, remark/rehype (existing), gray-matter
---
## File Structure
```
src/
├── components/
│ ├── home/
│ │ ├── HeroSection.tsx — Hero with OCR demo + CTA
│ │ ├── FeaturesSection.tsx — Feature cards grid
│ │ ├── HowItWorksSection.tsx — 3-step flow
│ │ ├── PricingSection.tsx — Price cards
│ │ └── ContactSection.tsx — Contact info + form
│ ├── layout/
│ │ ├── MarketingNavbar.tsx — Full site nav
│ │ ├── AppNavbar.tsx — Workspace nav (from Navbar.tsx)
│ │ ├── Footer.tsx — Site footer
│ │ ├── MarketingLayout.tsx — MarketingNavbar + Outlet + Footer
│ │ └── AppLayout.tsx — AppNavbar + Outlet
│ └── seo/
│ └── SEOHead.tsx — react-helmet-async wrapper
├── pages/
│ ├── HomePage.tsx
│ ├── WorkspacePage.tsx — migrated from App.tsx
│ ├── DocsListPage.tsx
│ ├── DocDetailPage.tsx
│ ├── BlogListPage.tsx
│ └── BlogDetailPage.tsx
├── lib/
│ └── content.ts — Load markdown manifests
├── routes/
│ └── AppRouter.tsx — Updated with layout routes
content/
├── docs/
│ ├── en/getting-started.md
│ └── zh/getting-started.md
└── blog/
├── en/2026-03-25-introducing-texpixel.md
└── zh/2026-03-25-introducing-texpixel.md
scripts/
└── build-content.ts — Compile markdown to JSON
```
---
### Task 1: Install dependencies and setup
**Files:**
- Modify: `package.json`
- [ ] **Step 1: Install react-helmet-async and gray-matter**
```bash
npm install react-helmet-async gray-matter
```
- [ ] **Step 2: Wrap app with HelmetProvider**
In `src/main.tsx`, add `HelmetProvider` wrapping:
```tsx
import { HelmetProvider } from 'react-helmet-async';
// Wrap inside StrictMode:
```
- [ ] **Step 3: Commit**
```bash
git add package.json package-lock.json src/main.tsx
git commit -m "feat: install react-helmet-async and gray-matter, add HelmetProvider"
```
---
### Task 2: Create SEOHead component
**Files:**
- Create: `src/components/seo/SEOHead.tsx`
- [ ] **Step 1: Create SEOHead component**
```tsx
import { Helmet } from 'react-helmet-async';
interface SEOHeadProps {
title: string;
description: string;
path: string;
type?: 'website' | 'article';
image?: string;
publishedTime?: string;
noindex?: boolean;
}
const BASE_URL = 'https://texpixel.com';
export default function SEOHead({
title,
description,
path,
type = 'website',
image = 'https://cdn.texpixel.com/public/og-cover.png',
publishedTime,
noindex = false,
}: SEOHeadProps) {
const url = `${BASE_URL}${path}`;
const fullTitle = path === '/' ? title : `${title} | TexPixel`;
return (
{fullTitle}
{noindex && }
{/* Open Graph */}
{publishedTime && }
{/* Twitter */}
);
}
```
- [ ] **Step 2: Commit**
```bash
git add src/components/seo/SEOHead.tsx
git commit -m "feat: add SEOHead component with react-helmet-async"
```
---
### Task 3: Create layout components
**Files:**
- Create: `src/components/layout/MarketingNavbar.tsx`
- Create: `src/components/layout/AppNavbar.tsx`
- Create: `src/components/layout/Footer.tsx`
- Create: `src/components/layout/MarketingLayout.tsx`
- Create: `src/components/layout/AppLayout.tsx`
- [ ] **Step 1: Create MarketingNavbar**
Full-width navbar with logo, nav links (Home, Docs, Blog), anchor links (Pricing, Contact on home page), language switcher, and CTA button to `/app`. Use `useLocation` to show anchor links only when on `/`. Responsive with mobile hamburger menu.
```tsx
// src/components/layout/MarketingNavbar.tsx
import { useState } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { Languages, ChevronDown, Check, Menu, X } from 'lucide-react';
import { useLanguage } from '../../contexts/LanguageContext';
export default function MarketingNavbar() {
const { language, setLanguage, t } = useLanguage();
const location = useLocation();
const [showLangMenu, setShowLangMenu] = useState(false);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const isHome = location.pathname === '/';
const navLinks = [
{ to: '/', label: t.marketing?.nav?.home ?? 'Home' },
{ to: '/docs', label: t.marketing?.nav?.docs ?? 'Docs' },
{ to: '/blog', label: t.marketing?.nav?.blog ?? 'Blog' },
];
const anchorLinks = isHome
? [
{ href: '#pricing', label: t.marketing?.nav?.pricing ?? 'Pricing' },
{ href: '#contact', label: t.marketing?.nav?.contact ?? 'Contact' },
]
: [];
return (
);
}
```
- [ ] **Step 2: Create AppNavbar**
Simplified version of current `Navbar.tsx` for the workspace. Keep language switcher, reward, contact, guide, help — remove marketing nav links. Add a "Back to Home" link.
Copy current `src/components/Navbar.tsx` content into `src/components/layout/AppNavbar.tsx`. Add a `Link` to `/` (home icon or "TexPixel" logo links to `/`). Keep all existing functionality (reward modal, contact dropdown, language switcher, guide button).
- [ ] **Step 3: Create Footer**
```tsx
// src/components/layout/Footer.tsx
import { Link } from 'react-router-dom';
import { useLanguage } from '../../contexts/LanguageContext';
export default function Footer() {
const { t } = useLanguage();
return (
);
}
```
- [ ] **Step 4: Create MarketingLayout and AppLayout**
```tsx
// src/components/layout/MarketingLayout.tsx
import { Outlet } from 'react-router-dom';
import MarketingNavbar from './MarketingNavbar';
import Footer from './Footer';
export default function MarketingLayout() {
return (
);
}
```
```tsx
// src/components/layout/AppLayout.tsx
import { Outlet } from 'react-router-dom';
import AppNavbar from './AppNavbar';
export default function AppLayout() {
return (
);
}
```
- [ ] **Step 5: Commit**
```bash
git add src/components/layout/
git commit -m "feat: add layout components (MarketingNavbar, AppNavbar, Footer, layouts)"
```
---
### Task 4: Add marketing translations
**Files:**
- Modify: `src/lib/translations.ts`
- [ ] **Step 1: Add marketing section to translations**
Add `marketing` key to both `en` and `zh` objects in `translations.ts`:
```typescript
marketing: {
nav: {
home: 'Home', // zh: '首页'
docs: 'Docs', // zh: '文档'
blog: 'Blog', // zh: '博客'
pricing: 'Pricing', // zh: '价格'
contact: 'Contact', // zh: '联系我们'
launchApp: 'Launch App', // zh: '启动应用'
},
hero: {
title: 'Convert Math Formulas to LaTeX in Seconds',
// zh: '数学公式秒级转换为 LaTeX'
subtitle: 'AI-powered OCR for handwritten and printed mathematical formulas. Get LaTeX, MathML, and Markdown output instantly.',
// zh: 'AI 驱动的手写和印刷体数学公式识别,即时输出 LaTeX、MathML 和 Markdown。'
cta: 'Try It Free', // zh: '免费试用'
ctaSecondary: 'Learn More', // zh: '了解更多'
},
features: {
title: 'Features', // zh: '功能特性'
subtitle: 'Everything you need for formula recognition',
// zh: '公式识别所需的一切'
items: [
{ title: 'Handwriting Recognition', description: 'Accurately recognize handwritten math formulas from photos or scans' },
{ title: 'Multi-Format Output', description: 'Export to LaTeX, MathML, Markdown, Word, and more' },
{ title: 'PDF Support', description: 'Upload PDF documents and extract formulas automatically' },
{ title: 'Batch Processing', description: 'Process multiple files at once for maximum efficiency' },
{ title: 'High Accuracy', description: 'Powered by advanced AI models for industry-leading accuracy' },
{ title: 'Free to Start', description: 'Get started with free uploads, no credit card required' },
],
// zh versions of items array
},
howItWorks: {
title: 'How It Works', // zh: '使用流程'
steps: [
{ title: 'Upload', description: 'Upload an image or PDF containing math formulas' },
{ title: 'Recognize', description: 'Our AI analyzes and recognizes the formulas' },
{ title: 'Export', description: 'Copy or export results in your preferred format' },
],
},
pricing: {
title: 'Pricing', // zh: '价格方案'
subtitle: 'Choose the plan that fits your needs',
// zh: '选择适合您的方案'
plans: [
{ name: 'Free', price: '$0', period: '/month', features: ['3 uploads/day', 'LaTeX & Markdown output', 'Community support'], cta: 'Get Started' },
{ name: 'Pro', price: '$9.9', period: '/month', features: ['Unlimited uploads', 'All export formats', 'Priority processing', 'API access'], cta: 'Coming Soon', popular: true },
{ name: 'Enterprise', price: 'Custom', period: '', features: ['Custom volume', 'Dedicated support', 'SLA guarantee', 'On-premise option'], cta: 'Contact Us' },
],
},
contact: {
title: 'Contact Us', // zh: '联系我们'
subtitle: 'Get in touch with our team',
// zh: '与我们的团队取得联系'
nameLabel: 'Name', // zh: '姓名'
emailLabel: 'Email', // zh: '邮箱'
messageLabel: 'Message', // zh: '留言'
send: 'Send Message', // zh: '发送消息'
sending: 'Sending...', // zh: '发送中...'
sent: 'Message sent!', // zh: '消息已发送!'
qqGroup: 'QQ Group', // zh: 'QQ 群'
},
footer: {
tagline: 'AI-powered math formula recognition',
// zh: 'AI 驱动的数学公式识别'
product: 'Product', // zh: '产品'
resources: 'Resources', // zh: '资源'
contactTitle: 'Contact', // zh: '联系方式'
},
},
```
- [ ] **Step 2: Commit**
```bash
git add src/lib/translations.ts
git commit -m "feat: add marketing translations for en and zh"
```
---
### Task 5: Create Home page sections
**Files:**
- Create: `src/components/home/HeroSection.tsx`
- Create: `src/components/home/FeaturesSection.tsx`
- Create: `src/components/home/HowItWorksSection.tsx`
- Create: `src/components/home/PricingSection.tsx`
- Create: `src/components/home/ContactSection.tsx`
- Create: `src/pages/HomePage.tsx`
- [ ] **Step 1: Create HeroSection**
Hero with product tagline, a mini drag-and-drop demo area (visual only, clicking it navigates to `/app`), and CTA buttons. Use Tailwind for gradient backgrounds and animations.
Key elements:
- Large heading from `t.marketing.hero.title`
- Subtitle from `t.marketing.hero.subtitle`
- Primary CTA button → links to `/app`
- Secondary CTA button → scrolls to `#features`
- A decorative mock preview showing a formula being converted (static image or CSS illustration)
- [ ] **Step 2: Create FeaturesSection**
6-card grid from `t.marketing.features.items`. Each card has an icon (from lucide-react), title, and description. Use icons: `PenTool`, `FileOutput`, `FileText`, `Layers`, `Zap`, `Gift`.
- [ ] **Step 3: Create HowItWorksSection**
3-step horizontal flow with numbered circles, title, description. Steps from `t.marketing.howItWorks.steps`. Use icons: `Upload`, `Cpu`, `Download`.
- [ ] **Step 4: Create PricingSection**
3-column card layout from `t.marketing.pricing.plans`. Middle card (Pro) has `popular: true` → highlighted border/badge. CTA buttons: Free → link to `/app`, Pro → disabled "Coming Soon", Enterprise → link to `#contact`.
Section has `id="pricing"` for anchor navigation.
- [ ] **Step 5: Create ContactSection**
Two-column layout. Left: contact info (email, QQ group). Right: form with name, email, message fields + submit button. Form initially just shows a success toast on submit (no backend). `id="contact"` for anchor nav.
- [ ] **Step 6: Create HomePage**
```tsx
// src/pages/HomePage.tsx
import SEOHead from '../components/seo/SEOHead';
import HeroSection from '../components/home/HeroSection';
import FeaturesSection from '../components/home/FeaturesSection';
import HowItWorksSection from '../components/home/HowItWorksSection';
import PricingSection from '../components/home/PricingSection';
import ContactSection from '../components/home/ContactSection';
import { useLanguage } from '../contexts/LanguageContext';
export default function HomePage() {
const { t } = useLanguage();
return (
<>
>
);
}
```
- [ ] **Step 7: Commit**
```bash
git add src/components/home/ src/pages/HomePage.tsx
git commit -m "feat: add Home page with Hero, Features, HowItWorks, Pricing, Contact sections"
```
---
### Task 6: Migrate App.tsx to WorkspacePage
**Files:**
- Create: `src/pages/WorkspacePage.tsx`
- Modify: `src/App.tsx` (will become thin redirect or removed)
- [ ] **Step 1: Create WorkspacePage**
Move all logic from `App.tsx` into `WorkspacePage.tsx`. Remove the outer `
` and `` wrappers since `AppLayout` provides those. Keep the inner flex container with LeftSidebar, FilePreview, ResultPanel, modals, and loading overlay.
The component should render:
```tsx
<>
{/* Left Sidebar */}