From 549f74c10b96f95327c0a851db4e601ca468822c Mon Sep 17 00:00:00 2001 From: Matiss Jurevics Date: Tue, 3 Feb 2026 16:52:50 +0000 Subject: [PATCH] updated hero section and added google auth --- app/(app)/onboarding/page.tsx | 365 ----------------------------- app/onboarding/page.tsx | 398 ++++++++++++++++++++++++++++++++ app/page.tsx | 98 +------- components/auth/SignIn.tsx | 103 ++++++--- components/features-section.tsx | 86 +++++++ components/hero-section.tsx | 87 +++++++ components/hero-shader.tsx | 10 +- convex/auth.config.ts | 7 +- convex/auth.ts | 3 +- docs/changelog.md | 2 + public/onboarding-bg.png | Bin 0 -> 648453 bytes 11 files changed, 662 insertions(+), 497 deletions(-) delete mode 100644 app/(app)/onboarding/page.tsx create mode 100644 app/onboarding/page.tsx create mode 100644 components/features-section.tsx create mode 100644 components/hero-section.tsx create mode 100644 docs/changelog.md create mode 100644 public/onboarding-bg.png diff --git a/app/(app)/onboarding/page.tsx b/app/(app)/onboarding/page.tsx deleted file mode 100644 index 92a053c..0000000 --- a/app/(app)/onboarding/page.tsx +++ /dev/null @@ -1,365 +0,0 @@ -'use client' - -import { useState } from 'react' -import { useRouter } from 'next/navigation' -import { Button } from '@/components/ui/button' -import { Input } from '@/components/ui/input' -import { Textarea } from '@/components/ui/textarea' -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' -import { Label } from '@/components/ui/label' -import { Skeleton } from '@/components/ui/skeleton' -import { Alert, AlertDescription } from '@/components/ui/alert' -import { ArrowRight, Globe, Loader2, Sparkles, AlertCircle, ArrowLeft } from 'lucide-react' -import type { ProductAnalysis } from '@/lib/types' - -const examples = [ - { name: 'Notion', url: 'https://notion.so' }, - { name: 'Stripe', url: 'https://stripe.com' }, - { name: 'Figma', url: 'https://figma.com' }, - { name: 'Linear', url: 'https://linear.app' }, -] - -export default function OnboardingPage() { - const router = useRouter() - const [url, setUrl] = useState('') - const [loading, setLoading] = useState(false) - const [progress, setProgress] = useState('') - const [error, setError] = useState('') - const [showManualInput, setShowManualInput] = useState(false) - - // Manual input fields - const [manualProductName, setManualProductName] = useState('') - const [manualDescription, setManualDescription] = useState('') - const [manualFeatures, setManualFeatures] = useState('') - - async function analyzeWebsite() { - if (!url) return - - setLoading(true) - setError('') - setProgress('Scraping website...') - - try { - const response = await fetch('/api/analyze', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ url }), - }) - - const data = await response.json() - - if (!response.ok) { - if (data.needsManualInput) { - setShowManualInput(true) - setManualProductName(url.replace(/^https?:\/\//, '').replace(/\/$/, '')) - throw new Error(data.error) - } - throw new Error(data.error || 'Failed to analyze') - } - - setProgress('Analyzing with AI...') - - // Store in localStorage for dashboard - localStorage.setItem('productAnalysis', JSON.stringify(data.data)) - localStorage.setItem('analysisStats', JSON.stringify(data.stats)) - - setProgress('Redirecting to dashboard...') - - // Redirect to dashboard with product name in query - const params = new URLSearchParams({ product: data.data.productName }) - router.push(`/dashboard?${params.toString()}`) - } catch (err: any) { - console.error('Analysis error:', err) - setError(err.message || 'Failed to analyze website') - } finally { - setLoading(false) - } - } - - async function analyzeManually() { - if (!manualProductName || !manualDescription) return - - setLoading(true) - setError('') - setProgress('Analyzing with AI...') - - try { - // Create a mock analysis from manual input - const manualAnalysis: ProductAnalysis = { - productName: manualProductName, - tagline: manualDescription.split('.')[0], - description: manualDescription, - features: manualFeatures.split('\n').filter(f => f.trim()), - problemsSolved: [], - targetAudience: [], - valuePropositions: [], - keywords: manualProductName.toLowerCase().split(' '), - scrapedAt: new Date().toISOString() - } - - // Send to API to enhance with AI - const response = await fetch('/api/analyze-manual', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - productName: manualProductName, - description: manualDescription, - features: manualFeatures - }), - }) - - let finalAnalysis = manualAnalysis - - if (response.ok) { - const data = await response.json() - finalAnalysis = data.data - } - - // Store in localStorage for dashboard - localStorage.setItem('productAnalysis', JSON.stringify(finalAnalysis)) - localStorage.setItem('analysisStats', JSON.stringify({ - features: finalAnalysis.features.length, - keywords: finalAnalysis.keywords.length, - personas: finalAnalysis.personas.length, - useCases: finalAnalysis.useCases.length, - competitors: finalAnalysis.competitors.length, - dorkQueries: finalAnalysis.dorkQueries.length - })) - - // Redirect to dashboard - const params = new URLSearchParams({ product: finalAnalysis.productName }) - router.push(`/dashboard?${params.toString()}`) - } catch (err: any) { - console.error('Manual analysis error:', err) - setError(err.message || 'Failed to analyze') - } finally { - setLoading(false) - } - } - - if (showManualInput) { - return ( -
-
-
-
-
- -
-
-

Couldn't Reach Website

-

- No problem! Tell us about your product and we'll analyze it manually. -

-
- - {error && ( - - - {error} - - )} - - - - Describe Your Product - - Enter your product details and we'll extract the key information. - - - -
- - setManualProductName(e.target.value)} - /> -
- -
- -