Handoff Doc:
IDE Agent Handoff Document
Project: Automotive Research Hub
Status: Development Complete → Production Prep Required
Framework: React + TypeScript → Cloudflare Pages
Outstanding Implementation Tasks
Priority 1: Pre-Production Fixes
Task 1.1: Reactive Scroll Indicator
typescript
// Current: Static SVG animation
// Required: React to scroll position, hide after scroll threshold
const ScrollIndicator = () => {
const [isVisible, setIsVisible] = useState(true);
useEffect(() => {
const handleScroll = () => {
setIsVisible(window.scrollY < 100);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
// Add opacity transition based on scroll velocity
};
Task 1.2: Search Bar Reveal
typescript
// Required: CTA button transforms to search input
// Implementation Pattern:
// - Click "Explore Sources" → morphs into search bar
// - Search should filter sources array by title + publisher
// - Hybrid search: exact match priority, then fuzzy match
interface SearchState {
isActive: boolean;
query: string;
results: Source[];
}
// Consider: Fuse.js for fuzzy search (2.4kb gzipped)
Framer Motion Migration Guide
Current State: CSS Transitions
css
/* Existing */
transition: all 0.3s ease-in-out;
transform: translateY(-8px);
Target State: Framer Motion
typescript
import { motion, useInView, AnimatePresence } from 'framer-motion';
// Card Animation
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{
duration: 0.5,
delay: index * 0.05,
ease: [0.22, 1, 0.36, 1] // Custom easing
}}
whileHover={{
y: -8,
boxShadow: '0 20px 25px -5px rgba(139, 92, 246, 0.2)'
}}
>
Migration Steps:
Install:
npm install framer-motionReplace
<div>with<motion.div>for animated elementsReplace
useStatevisibility withuseInViewhookReplace CSS transitions with
whileHover,whileTappropsUse
AnimatePresencefor accordion content expand/collapse
Benefits:
Spring physics for natural motion
Layout animations (accordion height)
Gesture detection (swipe on mobile)
Better performance (GPU acceleration)
Code Weak Spots & Potential Issues
1. State Management Constraint
Issue: Single expandedCard state at App level
Limitation: Can't expand multiple cards simultaneously
Fix Priority: Low (matches design intent)
Future Enhancement: Add multi-select mode for comparison
2. Scroll Observer Memory Leak Risk
typescript
// Current: Observer disconnects after first intersection
// Potential Issue: Rapid unmounting could leak observers
// Hardening Required:
useEffect(() => {
const observer = new IntersectionObserver(/*...*/);
const currentRef = cardRef.current;
if (currentRef) observer.observe(currentRef);
return () => {
if (currentRef) observer.unobserve(currentRef);
observer.disconnect(); // Ensure cleanup
};
}, []);
```
### 3. Data Structure Scalability
**Current:** 95-item array in component file
**Constraint:** No server-side rendering, all data client-side
**Recommendation:** Move to JSON file or CMS for >200 sources
**Production Path:**
```
/src
/data
sources.json ← Extract here
sources.schema.ts ← Type definitions
4. Search Performance
Concern: Filtering 95 items on every keystroke
Solution: Debounce search input (300ms)
typescript
const debouncedSearch = useMemo(
() => debounce((query) => filterSources(query), 300),
[]
);
5. Mobile Accordion Height Jump
Issue: max-height transitions can feel janky
Framer Motion Fix:
typescript
<motion.div
animate={{ height: isExpanded ? 'auto' : 0 }}
transition={{ type: 'spring', stiffness: 300, damping: 30 }}
>
6. No Error Boundaries
Missing: Graceful failure handling
Add:
typescript
class ErrorBoundary extends React.Component {
// Wrap App component
// Log errors to monitoring service
}
```
---
## Cloudflare Pages Deployment Configuration
### Required Files & Structure
```
project-root/
├── public/
│ ├── _headers ← Security headers
│ ├── _redirects ← URL redirects
│ └── robots.txt
│
├── src/
│ ├── components/
│ │ ├── Hero.tsx
│ │ ├── SourceCard.tsx
│ │ ├── LeverageFooter.tsx
│ │ └── SearchBar.tsx
│ ├── data/
│ │ └── sources.json
│ ├── App.tsx
│ └── main.tsx
│
├── .node-version ← Node 18.x
├── wrangler.toml ← Cloudflare config
├── package.json
├── vite.config.ts
├── tsconfig.json
├── tailwind.config.js
└── README.md
Configuration Files
1. wrangler.toml
toml
name = "automotive-research-hub"
compatibility_date = "2025-01-01"
[site]
bucket = "./dist"
[[pages_build_output_dir]]
value = "dist"
[build]
command = "npm run build"
[build.environment]
NODE_VERSION = "18"
```
**2. _headers**
```
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';
3. package.json (build scripts)
json
{
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"deploy": "npm run build && wrangler pages deploy dist"
}
}
4. vite.config.ts
typescript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
build: {
outDir: 'dist',
sourcemap: false,
minify: 'terser',
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
icons: ['lucide-react']
}
}
}
}
});
```
---
## Blog Integration: Yoopta-Editor
### Extended File Tree
```
src/
├── components/
│ ├── blog/
│ │ ├── BlogEditor.tsx ← Yoopta wrapper
│ │ ├── BlogPostCard.tsx ← List view
│ │ ├── BlogPostView.tsx ← Single post
│ │ └── AdminPanel.tsx ← Auth gated
│ │
│ ├── seo/
│ │ ├── MetaTags.tsx ← Dynamic meta tags
│ │ ├── StructuredData.tsx ← JSON-LD schemas
│ │ └── OpenGraph.tsx ← OG tags
│ │
├── data/
│ └── blog-posts.json ← D1 database alternative
│
├── lib/
│ ├── yoopta-config.ts ← Editor configuration
│ └── seo-utils.ts ← Meta generation
│
└── pages/
├── BlogIndex.tsx ← /blog
├── BlogPost.tsx ← /blog/:slug
└── AdminDashboard.tsx ← /admin (auth required)
Yoopta-Editor Setup
Installation:
bash
npm install @yoopta/editor @yoopta/exports
Basic Configuration:
typescript
// lib/yoopta-config.ts
import { createYooptaEditor } from '@yoopta/editor';
export const editorConfig = {
plugins: [
// Rich text
{ type: 'paragraph' },
{ type: 'heading', levels: [1, 2, 3] },
{ type: 'blockquote' },
// Media
{ type: 'image', upload: cloudflareR2Upload },
{ type: 'video', embed: true },
// SEO
{ type: 'metadata', fields: ['title', 'description', 'keywords'] }
],
toolbar: {
position: 'sticky',
formatting: ['bold', 'italic', 'link', 'code']
}
};
SEO Integration:
typescript
// components/seo/MetaTags.tsx
interface BlogPostSEO {
title: string;
description: string;
keywords: string[];
author: string;
publishDate: string;
slug: string;
}
export const MetaTags = ({ post }: { post: BlogPostSEO }) => (
<Helmet>
<title>{post.title} | Automotive Research Hub</title>
<meta name="description" content={post.description} />
<meta name="keywords" content={post.keywords.join(', ')} />
<meta name="author" content={post.author} />
{/* Open Graph */}
<meta property="og:type" content="article" />
<meta property="og:title" content={post.title} />
<meta property="article:published_time" content={post.publishDate} />
{/* Schema.org */}
<script type="application/ld+json">
{JSON.stringify({
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": post.title,
"datePublished": post.publishDate,
"author": { "@type": "Organization", "name": "LEVERAGEAI LLC" }
})}
</script>
</Helmet>
);
Admin Authentication Strategy
Options:
-
Cloudflare Access (Recommended)
Zero trust security
No custom auth code
/admin/* protected at edge
-
Custom Auth via D1
User table in D1 database
JWT tokens in cookies
Session management
Deployment Note: Yoopta content stored in Cloudflare D1 or R2 for persistence.
Pre-Deployment Checklist
Framer Motion migration complete
Search functionality implemented
Scroll indicator reactivity fixed
Error boundaries added
Blog editor integrated
SEO meta tags configured
Admin authentication enabled
Performance audit (<3s FCP)
Accessibility audit (WCAG 2.1 AA)
Mobile testing (iOS/Android)
Cloudflare D1 database schema created
Environment variables configured
Analytics integrated (Cloudflare Web Analytics)
Deployment Commands
bash
# Local Development
npm install
npm run dev
# Build & Test
npm run build
npm run preview
# Deploy to Cloudflare Pages
wrangler pages deploy dist --project-name=automotive-research-hub
# Environment Variables (via Dashboard or CLI)
wrangler pages secret put ADMIN_PASSWORD
wrangler pages secret put BLOG_API_KEY
Handoff Complete. All architectural decisions logged. Constraints identified. Migration path clear.