Added onboarding progress tracking & landing page
This commit is contained in:
140
frontend/src/components/Landing/EnterpriseCTA.tsx
Normal file
140
frontend/src/components/Landing/EnterpriseCTA.tsx
Normal file
@@ -0,0 +1,140 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Container,
|
||||
Typography,
|
||||
Stack,
|
||||
Grid,
|
||||
useTheme,
|
||||
alpha
|
||||
} from '@mui/material';
|
||||
import OptimizedImage from './OptimizedImage';
|
||||
import { SignInButton } from '@clerk/clerk-react';
|
||||
import { RocketLaunch } from '@mui/icons-material';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const EnterpriseCTA: React.FC = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
// Framer Motion variants
|
||||
const fadeInUp = {
|
||||
hidden: { opacity: 0, y: 24 },
|
||||
visible: { opacity: 1, y: 0, transition: { duration: 0.6, ease: "easeOut" as const } },
|
||||
};
|
||||
|
||||
const stagger = {
|
||||
hidden: {},
|
||||
visible: { transition: { staggerChildren: 0.12 } },
|
||||
};
|
||||
|
||||
// Glassmorphism styles
|
||||
const glassPanelSx = {
|
||||
background: `linear-gradient(135deg, ${alpha(theme.palette.common.white, 0.06)} 0%, ${alpha(theme.palette.common.white, 0.02)} 100%)`,
|
||||
backdropFilter: 'blur(12px)',
|
||||
border: '1px solid rgba(255,255,255,0.12)',
|
||||
borderRadius: 4,
|
||||
boxShadow: '0 10px 30px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.06)'
|
||||
} as const;
|
||||
|
||||
return (
|
||||
<Container maxWidth="lg" sx={{ py: 8 }}>
|
||||
<motion.div variants={stagger} initial="hidden" whileInView="visible" viewport={{ once: true, amount: 0.2 }}>
|
||||
<Box
|
||||
sx={{
|
||||
...glassPanelSx,
|
||||
p: { xs: 4, md: 8 },
|
||||
textAlign: 'center'
|
||||
}}
|
||||
>
|
||||
<Grid container spacing={6} alignItems="center">
|
||||
{/* Left side - Image (40%) */}
|
||||
<Grid item xs={12} md={5}>
|
||||
<motion.div variants={fadeInUp}>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
height: '100%',
|
||||
minHeight: { xs: '350px', md: '500px' },
|
||||
width: '100%'
|
||||
}}
|
||||
>
|
||||
<OptimizedImage
|
||||
src="/alwrity_landing_copilot.png"
|
||||
alt="ALwrity Co-Pilot Interface"
|
||||
priority={true}
|
||||
sx={{
|
||||
borderRadius: 3,
|
||||
boxShadow: '0 20px 40px rgba(0,0,0,0.3)',
|
||||
transition: 'transform 0.3s ease',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.02)'
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</motion.div>
|
||||
</Grid>
|
||||
|
||||
{/* Right side - Content (60%) */}
|
||||
<Grid item xs={12} md={7}>
|
||||
<motion.div variants={fadeInUp}>
|
||||
<Stack spacing={4} alignItems={{ xs: 'center', md: 'flex-start' }} textAlign={{ xs: 'center', md: 'left' }}>
|
||||
<Typography variant="h3" fontWeight={700}>
|
||||
Ready to Transform Your Content Creation?
|
||||
</Typography>
|
||||
<Typography variant="h6" color="text.secondary" maxWidth="700px">
|
||||
Join thousands of creators, marketers, and businesses already using ALwrity's open-source AI platform.
|
||||
Start creating professional content in minutes, not hours.
|
||||
</Typography>
|
||||
|
||||
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={3} alignItems="center">
|
||||
<SignInButton mode="redirect" forceRedirectUrl="/">
|
||||
<Button
|
||||
variant="contained"
|
||||
size="large"
|
||||
startIcon={<RocketLaunch />}
|
||||
sx={{
|
||||
py: 2,
|
||||
px: 6,
|
||||
fontSize: '1.2rem',
|
||||
fontWeight: 600,
|
||||
borderRadius: 2,
|
||||
background: 'linear-gradient(45deg, #667eea 30%, #764ba2 90%)',
|
||||
boxShadow: '0 8px 32px rgba(102, 126, 234, 0.3)',
|
||||
'&:hover': {
|
||||
boxShadow: '0 12px 40px rgba(102, 126, 234, 0.4)',
|
||||
transform: 'translateY(-2px)'
|
||||
},
|
||||
transition: 'all 0.3s ease'
|
||||
}}
|
||||
>
|
||||
Start Creating Now
|
||||
</Button>
|
||||
</SignInButton>
|
||||
|
||||
<Stack alignItems={{ xs: 'center', sm: 'flex-start' }} spacing={1}>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
✓ Free to get started
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
✓ Open-source & transparent
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
✓ No credit card required
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</motion.div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</motion.div>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default EnterpriseCTA;
|
||||
416
frontend/src/components/Landing/FeatureShowcase.tsx
Normal file
416
frontend/src/components/Landing/FeatureShowcase.tsx
Normal file
@@ -0,0 +1,416 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Box, Container, Typography, Stack, IconButton, useTheme, alpha } from '@mui/material';
|
||||
import { ArrowBack, ArrowForward, Psychology, Search, FactCheck, Edit, Assistant, Verified } from '@mui/icons-material';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
|
||||
interface Feature {
|
||||
image: string;
|
||||
title: string;
|
||||
description: string;
|
||||
icon: React.ReactNode;
|
||||
badge: string;
|
||||
}
|
||||
|
||||
const features: Feature[] = [
|
||||
{
|
||||
image: '/Alwrity-copilot1.png',
|
||||
title: 'AI-First Copilot',
|
||||
description: 'Your personal LinkedIn writing assistant with persona-aware content generation. Create professional posts, articles, and carousels that match your unique voice.',
|
||||
icon: <Assistant />,
|
||||
badge: 'Persona-Aware'
|
||||
},
|
||||
{
|
||||
image: '/Alwrity-copilot2.png',
|
||||
title: 'Intelligent Writing Partner',
|
||||
description: 'Context-aware AI copilot that understands your content goals and audience. Get real-time suggestions and enhancements tailored to your strategy.',
|
||||
icon: <Psychology />,
|
||||
badge: 'Context-Aware'
|
||||
},
|
||||
{
|
||||
image: '/alwrty_research.png',
|
||||
title: 'Interactive Web Research',
|
||||
description: 'AI-powered research engine with 25+ source integration. Get SERP rankings, credibility scores, and real-time market insights for data-driven content.',
|
||||
icon: <Search />,
|
||||
badge: 'Live Research'
|
||||
},
|
||||
{
|
||||
image: '/ALwrity-assistive-writing.png',
|
||||
title: 'Assistive Writing Flow',
|
||||
description: 'Smart writing assistant that contextually continues your thoughts. Never face writer\'s block again with AI that understands your draft and goals.',
|
||||
icon: <Edit />,
|
||||
badge: 'Smart Assist'
|
||||
},
|
||||
{
|
||||
image: '/Fact-check1.png',
|
||||
title: 'Hallucination-Free Content',
|
||||
description: 'Advanced fact-checking with source verification and credibility scoring. Every claim is analyzed, validated, and cited with authority ratings.',
|
||||
icon: <FactCheck />,
|
||||
badge: 'Verified'
|
||||
},
|
||||
{
|
||||
image: '/Alwrity-fact-check.png',
|
||||
title: 'Claims Analysis Engine',
|
||||
description: 'Comprehensive fact-check results with supported, refuted, and insufficient claims. Ensure accuracy with AI-powered reasoning and source citations.',
|
||||
icon: <Verified />,
|
||||
badge: 'AI-Verified'
|
||||
},
|
||||
];
|
||||
|
||||
const FeatureShowcase: React.FC = () => {
|
||||
const theme = useTheme();
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const itemsPerPage = 3;
|
||||
const totalPages = Math.ceil(features.length / itemsPerPage);
|
||||
|
||||
const handleNext = () => {
|
||||
setCurrentPage((prev) => (prev + 1) % totalPages);
|
||||
};
|
||||
|
||||
const handlePrev = () => {
|
||||
setCurrentPage((prev) => (prev - 1 + totalPages) % totalPages);
|
||||
};
|
||||
|
||||
const currentFeatures = features.slice(
|
||||
currentPage * itemsPerPage,
|
||||
(currentPage + 1) * itemsPerPage
|
||||
);
|
||||
|
||||
const slideVariants = {
|
||||
enter: (direction: number) => ({
|
||||
x: direction > 0 ? 1000 : -1000,
|
||||
opacity: 0,
|
||||
scale: 0.8,
|
||||
}),
|
||||
center: {
|
||||
x: 0,
|
||||
opacity: 1,
|
||||
scale: 1,
|
||||
transition: {
|
||||
duration: 0.5,
|
||||
ease: "easeOut" as const,
|
||||
},
|
||||
},
|
||||
exit: (direction: number) => ({
|
||||
x: direction > 0 ? -1000 : 1000,
|
||||
opacity: 0,
|
||||
scale: 0.8,
|
||||
transition: {
|
||||
duration: 0.5,
|
||||
ease: "easeOut" as const,
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
const cardVariants = {
|
||||
hidden: { opacity: 0, y: 50 },
|
||||
visible: (i: number) => ({
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
delay: i * 0.15,
|
||||
duration: 0.6,
|
||||
ease: "easeOut" as const,
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'relative',
|
||||
'&::before': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundImage: 'url(/alwrity_platform_experience.png)',
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: 'center',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
zIndex: 0,
|
||||
},
|
||||
'&::after': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
background: 'linear-gradient(135deg, rgba(0, 0, 0, 0.3) 0%, rgba(25, 118, 210, 0.2) 50%, rgba(156, 39, 176, 0.2) 100%)',
|
||||
zIndex: 1,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Container maxWidth="xl" sx={{ py: 10, position: 'relative', zIndex: 2 }}>
|
||||
<Stack spacing={6} alignItems="center">
|
||||
{/* Section Header */}
|
||||
<Stack spacing={2} alignItems="center" textAlign="center">
|
||||
<Typography variant="h3" fontWeight={700} sx={{ fontSize: { xs: '2rem', md: '2.5rem' } }}>
|
||||
Experience the Platform
|
||||
</Typography>
|
||||
<Typography variant="h6" color="text.secondary" maxWidth="750px" sx={{ lineHeight: 1.6 }}>
|
||||
Explore ALwrity's powerful features designed to transform your content workflow.
|
||||
From AI copilots to fact-checking, everything you need in one platform.
|
||||
</Typography>
|
||||
</Stack>
|
||||
|
||||
{/* Carousel Container */}
|
||||
<Box sx={{ position: 'relative', width: '100%', overflow: 'hidden', px: { xs: 2, md: 4 } }}>
|
||||
<AnimatePresence mode="wait" custom={currentPage}>
|
||||
<motion.div
|
||||
key={currentPage}
|
||||
custom={currentPage}
|
||||
variants={slideVariants}
|
||||
initial="enter"
|
||||
animate="center"
|
||||
exit="exit"
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: { xs: '1fr', md: 'repeat(3, 1fr)' },
|
||||
gap: 4,
|
||||
px: { xs: 2, md: 4 },
|
||||
}}
|
||||
>
|
||||
{currentFeatures.map((feature, index) => (
|
||||
<motion.div
|
||||
key={feature.title}
|
||||
custom={index}
|
||||
variants={cardVariants}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'relative',
|
||||
borderRadius: 3,
|
||||
overflow: 'hidden',
|
||||
background: `linear-gradient(135deg, ${alpha(theme.palette.primary.main, 0.08)} 0%, ${alpha(theme.palette.secondary.main, 0.08)} 100%)`,
|
||||
border: `1px solid ${alpha(theme.palette.primary.main, 0.2)}`,
|
||||
boxShadow: `0 12px 40px ${alpha(theme.palette.primary.main, 0.15)}`,
|
||||
transition: 'all 0.4s cubic-bezier(0.32, 0.72, 0, 1)',
|
||||
'&:hover': {
|
||||
transform: 'translateY(-12px) scale(1.02)',
|
||||
boxShadow: `0 20px 60px ${alpha(theme.palette.primary.main, 0.25)}`,
|
||||
borderColor: alpha(theme.palette.primary.main, 0.4),
|
||||
},
|
||||
}}
|
||||
>
|
||||
{/* Badge */}
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 16,
|
||||
right: 16,
|
||||
zIndex: 2,
|
||||
background: `linear-gradient(135deg, ${theme.palette.primary.main} 0%, ${theme.palette.secondary.main} 50%, ${theme.palette.primary.dark} 100%)`,
|
||||
backdropFilter: 'blur(12px)',
|
||||
px: 2.5,
|
||||
py: 1,
|
||||
borderRadius: 3,
|
||||
border: '1px solid rgba(255, 255, 255, 0.3)',
|
||||
boxShadow: `
|
||||
0 8px 32px ${alpha(theme.palette.primary.main, 0.4)},
|
||||
0 4px 16px ${alpha(theme.palette.secondary.main, 0.3)},
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.2)
|
||||
`,
|
||||
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
'&:hover': {
|
||||
transform: 'translateY(-2px) scale(1.05)',
|
||||
boxShadow: `
|
||||
0 12px 40px ${alpha(theme.palette.primary.main, 0.5)},
|
||||
0 6px 20px ${alpha(theme.palette.secondary.main, 0.4)},
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.3)
|
||||
`,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="caption"
|
||||
fontWeight={700}
|
||||
color="white"
|
||||
sx={{
|
||||
fontSize: '0.8rem',
|
||||
textShadow: '0 1px 2px rgba(0, 0, 0, 0.3)',
|
||||
letterSpacing: '0.5px',
|
||||
textTransform: 'uppercase',
|
||||
}}
|
||||
>
|
||||
{feature.badge}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
{/* Feature Image */}
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
height: 280,
|
||||
backgroundImage: `url(${feature.image})`,
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: 'center top',
|
||||
position: 'relative',
|
||||
'&::after': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: '40%',
|
||||
background: 'linear-gradient(to bottom, transparent, rgba(0,0,0,0.4))',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Feature Info */}
|
||||
<Box
|
||||
sx={{
|
||||
p: 3,
|
||||
background: `linear-gradient(135deg, ${alpha(theme.palette.common.white, 0.06)} 0%, ${alpha(theme.palette.common.white, 0.02)} 100%)`,
|
||||
backdropFilter: 'blur(12px)',
|
||||
}}
|
||||
>
|
||||
<Stack spacing={2}>
|
||||
<Stack direction="row" spacing={1.5} alignItems="center">
|
||||
<Box
|
||||
sx={{
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius: 2,
|
||||
background: `linear-gradient(135deg, ${theme.palette.primary.main} 0%, ${theme.palette.secondary.main} 100%)`,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
color: 'white',
|
||||
boxShadow: `0 4px 12px ${alpha(theme.palette.primary.main, 0.4)}`,
|
||||
}}
|
||||
>
|
||||
{feature.icon}
|
||||
</Box>
|
||||
<Typography
|
||||
variant="h6"
|
||||
fontWeight={700}
|
||||
color="white"
|
||||
sx={{
|
||||
fontSize: '1.2rem',
|
||||
textShadow: '0 1px 3px rgba(0, 0, 0, 0.7)',
|
||||
letterSpacing: '0.5px',
|
||||
}}
|
||||
>
|
||||
{feature.title}
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="white"
|
||||
sx={{
|
||||
lineHeight: 1.6,
|
||||
fontSize: '1rem',
|
||||
fontWeight: 500,
|
||||
textShadow: '0 1px 3px rgba(0, 0, 0, 0.7)',
|
||||
letterSpacing: '0.3px',
|
||||
}}
|
||||
>
|
||||
{feature.description}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Box>
|
||||
</motion.div>
|
||||
))}
|
||||
</Box>
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
|
||||
{/* Navigation Arrows */}
|
||||
{totalPages > 1 && (
|
||||
<>
|
||||
<IconButton
|
||||
onClick={handlePrev}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
left: { xs: 0, md: -10 },
|
||||
top: '50%',
|
||||
transform: 'translateY(-50%)',
|
||||
background: `linear-gradient(135deg, ${theme.palette.primary.main} 0%, ${theme.palette.secondary.main} 100%)`,
|
||||
color: 'white',
|
||||
width: 50,
|
||||
height: 50,
|
||||
boxShadow: `0 8px 24px ${alpha(theme.palette.primary.main, 0.4)}`,
|
||||
'&:hover': {
|
||||
background: `linear-gradient(135deg, ${theme.palette.primary.dark} 0%, ${theme.palette.secondary.dark} 100%)`,
|
||||
transform: 'translateY(-50%) scale(1.1)',
|
||||
boxShadow: `0 12px 32px ${alpha(theme.palette.primary.main, 0.5)}`,
|
||||
},
|
||||
transition: 'all 0.3s ease',
|
||||
zIndex: 10,
|
||||
}}
|
||||
>
|
||||
<ArrowBack />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
onClick={handleNext}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
right: { xs: 0, md: -10 },
|
||||
top: '50%',
|
||||
transform: 'translateY(-50%)',
|
||||
background: `linear-gradient(135deg, ${theme.palette.primary.main} 0%, ${theme.palette.secondary.main} 100%)`,
|
||||
color: 'white',
|
||||
width: 50,
|
||||
height: 50,
|
||||
boxShadow: `0 8px 24px ${alpha(theme.palette.primary.main, 0.4)}`,
|
||||
'&:hover': {
|
||||
background: `linear-gradient(135deg, ${theme.palette.primary.dark} 0%, ${theme.palette.secondary.dark} 100%)`,
|
||||
transform: 'translateY(-50%) scale(1.1)',
|
||||
boxShadow: `0 12px 32px ${alpha(theme.palette.primary.main, 0.5)}`,
|
||||
},
|
||||
transition: 'all 0.3s ease',
|
||||
zIndex: 10,
|
||||
}}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* Page Indicators */}
|
||||
{totalPages > 1 && (
|
||||
<Stack direction="row" spacing={1.5} alignItems="center">
|
||||
{Array.from({ length: totalPages }).map((_, index) => (
|
||||
<Box
|
||||
key={index}
|
||||
onClick={() => setCurrentPage(index)}
|
||||
sx={{
|
||||
width: index === currentPage ? 40 : 12,
|
||||
height: 12,
|
||||
borderRadius: 6,
|
||||
background: index === currentPage
|
||||
? `linear-gradient(90deg, ${theme.palette.primary.main} 0%, ${theme.palette.secondary.main} 100%)`
|
||||
: alpha(theme.palette.text.secondary, 0.2),
|
||||
cursor: 'pointer',
|
||||
transition: 'all 0.3s ease',
|
||||
boxShadow: index === currentPage ? `0 4px 12px ${alpha(theme.palette.primary.main, 0.4)}` : 'none',
|
||||
'&:hover': {
|
||||
background: index === currentPage
|
||||
? `linear-gradient(90deg, ${theme.palette.primary.main} 0%, ${theme.palette.secondary.main} 100%)`
|
||||
: alpha(theme.palette.text.secondary, 0.4),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
</Stack>
|
||||
</Container>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default FeatureShowcase;
|
||||
|
||||
401
frontend/src/components/Landing/HeroSection.tsx
Normal file
401
frontend/src/components/Landing/HeroSection.tsx
Normal file
@@ -0,0 +1,401 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Container,
|
||||
Typography,
|
||||
Stack,
|
||||
Grid,
|
||||
Chip,
|
||||
useTheme,
|
||||
alpha
|
||||
} from '@mui/material';
|
||||
import { SignInButton } from '@clerk/clerk-react';
|
||||
import {
|
||||
RocketLaunch,
|
||||
Lightbulb,
|
||||
Verified,
|
||||
Security,
|
||||
Shield,
|
||||
CloudDone,
|
||||
} from '@mui/icons-material';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
// Rotating text component
|
||||
const RotatingText: React.FC<{ words: string[]; interval?: number }> = ({
|
||||
words,
|
||||
interval = 2000
|
||||
}) => {
|
||||
const [currentIndex, setCurrentIndex] = React.useState(0);
|
||||
|
||||
React.useEffect(() => {
|
||||
const timer = setInterval(() => {
|
||||
setCurrentIndex((prev) => (prev + 1) % words.length);
|
||||
}, interval);
|
||||
return () => clearInterval(timer);
|
||||
}, [words.length, interval]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
component="span"
|
||||
sx={{
|
||||
color: '#fff',
|
||||
fontWeight: 900,
|
||||
// Strong text shadow for readability
|
||||
textShadow: `
|
||||
0 2px 10px rgba(0, 0, 0, 0.9),
|
||||
0 4px 20px rgba(0, 0, 0, 0.7),
|
||||
0 0 40px rgba(102, 126, 234, 0.4)
|
||||
`,
|
||||
}}
|
||||
>
|
||||
{words[currentIndex]}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const HeroSection: React.FC = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
const fadeInUp = {
|
||||
hidden: { opacity: 0, y: 24 },
|
||||
visible: { opacity: 1, y: 0, transition: { duration: 0.6, ease: "easeOut" as const } },
|
||||
};
|
||||
|
||||
const stagger = {
|
||||
hidden: {},
|
||||
visible: { transition: { staggerChildren: 0.12 } },
|
||||
};
|
||||
|
||||
const stats = [
|
||||
{ value: '70%', label: 'Time Savings' },
|
||||
{ value: '65%', label: 'Better Engagement' },
|
||||
{ value: '5x', label: 'Faster Publishing' },
|
||||
{ value: '21%', label: 'More ROI Tracking' }
|
||||
];
|
||||
|
||||
const trustSignals = [
|
||||
{ icon: <Security />, label: "Hyper Personalization" },
|
||||
{ icon: <Shield />, label: "Hallucination Free" },
|
||||
{ icon: <CloudDone />, label: "SME AI Platform" },
|
||||
{ icon: <Verified />, label: "Connected Platforms" }
|
||||
];
|
||||
|
||||
const glassPanelSx = {
|
||||
background: `linear-gradient(135deg, ${alpha(theme.palette.common.white, 0.08)} 0%, ${alpha(theme.palette.common.white, 0.03)} 100%)`,
|
||||
backdropFilter: 'blur(16px) saturate(180%)',
|
||||
border: '1px solid rgba(255,255,255,0.15)',
|
||||
borderRadius: 4,
|
||||
boxShadow: '0 12px 40px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.08)'
|
||||
} as const;
|
||||
|
||||
return (
|
||||
<Box sx={{ position: 'relative', bgcolor: '#000', color: theme.palette.getContrastText('#000'), overflow: 'hidden' }}>
|
||||
{/* Background Image */}
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundImage: 'url(/alwrity_landing_hero_bg.png)',
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: 'center',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
zIndex: 0,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Dark Overlay for Better Readability */}
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
background: `
|
||||
linear-gradient(135deg,
|
||||
rgba(0, 0, 0, 0.55) 0%,
|
||||
rgba(0, 0, 0, 0.45) 50%,
|
||||
rgba(0, 0, 0, 0.50) 100%
|
||||
)
|
||||
`,
|
||||
zIndex: 1,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Subtle Gradient Enhancement */}
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
background: `
|
||||
radial-gradient(circle at 50% 50%, ${alpha(theme.palette.primary.main, 0.10)} 0%, transparent 60%),
|
||||
radial-gradient(circle at 20% 80%, ${alpha(theme.palette.secondary.main, 0.08)} 0%, transparent 50%)
|
||||
`,
|
||||
zIndex: 2,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Hero Content */}
|
||||
<Container maxWidth="lg" sx={{ pt: 10, pb: 6, position: 'relative', zIndex: 3 }}>
|
||||
<motion.div variants={stagger} initial="hidden" animate="visible">
|
||||
<Stack spacing={6} alignItems="center" textAlign="center">
|
||||
{/* Main Headline */}
|
||||
<motion.div variants={fadeInUp}>
|
||||
<Stack spacing={3} alignItems="center">
|
||||
<Stack direction="row" spacing={2} alignItems="center" flexWrap="wrap" justifyContent="center">
|
||||
<Chip
|
||||
icon={<RocketLaunch />}
|
||||
label="AI Marketing Platform"
|
||||
variant="outlined"
|
||||
sx={{
|
||||
background: alpha(theme.palette.primary.main, 0.15),
|
||||
borderColor: theme.palette.primary.main,
|
||||
color: theme.palette.primary.light,
|
||||
fontWeight: 600,
|
||||
fontSize: '0.9rem'
|
||||
}}
|
||||
/>
|
||||
<Chip
|
||||
icon={<Verified />}
|
||||
label="AI-First Copilot"
|
||||
variant="outlined"
|
||||
sx={{
|
||||
background: alpha(theme.palette.success.main, 0.15),
|
||||
borderColor: theme.palette.success.main,
|
||||
color: theme.palette.success.light,
|
||||
fontWeight: 600,
|
||||
fontSize: '0.9rem'
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
<Typography
|
||||
variant="h1"
|
||||
component="h1"
|
||||
sx={{
|
||||
fontSize: { xs: '2.8rem', md: '4.5rem', lg: '5.5rem' },
|
||||
fontWeight: 900,
|
||||
letterSpacing: '-0.03em',
|
||||
lineHeight: 1.05,
|
||||
mb: 2,
|
||||
color: '#fff',
|
||||
// Enhanced text shadow for better readability
|
||||
textShadow: `
|
||||
0 2px 10px rgba(0, 0, 0, 0.8),
|
||||
0 4px 20px rgba(0, 0, 0, 0.6),
|
||||
0 0 40px rgba(102, 126, 234, 0.3)
|
||||
`,
|
||||
}}
|
||||
>
|
||||
Enterprise AI for{' '}
|
||||
<RotatingText
|
||||
words={['Revenue Growth', 'Brand Automation', 'Content Strategy', 'Market Intelligence']}
|
||||
/>
|
||||
</Typography>
|
||||
|
||||
<Typography
|
||||
variant="h4"
|
||||
sx={{
|
||||
fontSize: { xs: '1.2rem', md: '1.5rem' },
|
||||
fontWeight: 500,
|
||||
maxWidth: '950px',
|
||||
lineHeight: 1.5,
|
||||
mb: 3,
|
||||
color: 'rgba(255, 255, 255, 0.92)',
|
||||
// Enhanced text shadow for description
|
||||
textShadow: `
|
||||
0 2px 8px rgba(0, 0, 0, 0.8),
|
||||
0 4px 16px rgba(0, 0, 0, 0.5)
|
||||
`,
|
||||
}}
|
||||
>
|
||||
AI-powered marketing copilot that learns your brand voice, analyzes competitors,
|
||||
and creates hyper-personalized content strategies. Built for solopreneurs and SMEs
|
||||
who want enterprise-level AI without the enterprise complexity.
|
||||
</Typography>
|
||||
|
||||
{/* Trust Signals */}
|
||||
<Stack
|
||||
direction="row"
|
||||
spacing={3}
|
||||
alignItems="center"
|
||||
flexWrap="wrap"
|
||||
justifyContent="center"
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
{trustSignals.map((signal, index) => (
|
||||
<Stack
|
||||
key={index}
|
||||
direction="row"
|
||||
spacing={1}
|
||||
alignItems="center"
|
||||
sx={{
|
||||
// Add background for better visibility
|
||||
background: 'rgba(0, 0, 0, 0.3)',
|
||||
backdropFilter: 'blur(8px)',
|
||||
px: 2,
|
||||
py: 1,
|
||||
borderRadius: 2,
|
||||
border: '1px solid rgba(255, 255, 255, 0.1)',
|
||||
}}
|
||||
>
|
||||
<Box sx={{ color: theme.palette.success.light }}>{signal.icon}</Box>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{
|
||||
color: 'rgba(255, 255, 255, 0.95)',
|
||||
fontWeight: 600,
|
||||
textShadow: '0 2px 4px rgba(0, 0, 0, 0.6)'
|
||||
}}
|
||||
>
|
||||
{signal.label}
|
||||
</Typography>
|
||||
</Stack>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</motion.div>
|
||||
|
||||
{/* Glass CTA Panel */}
|
||||
<motion.div variants={fadeInUp}>
|
||||
<Box sx={{ ...glassPanelSx, px: { xs: 3, md: 5 }, py: { xs: 4, md: 6 }, maxWidth: 1000, width: '100%' }}>
|
||||
<Stack spacing={4} alignItems="center">
|
||||
<SignInButton mode="redirect" forceRedirectUrl="/">
|
||||
<Button
|
||||
variant="contained"
|
||||
size="large"
|
||||
startIcon={<Lightbulb />}
|
||||
sx={{
|
||||
py: 2.5,
|
||||
px: 5,
|
||||
fontSize: '1.2rem',
|
||||
fontWeight: 700,
|
||||
borderRadius: 3,
|
||||
background: 'linear-gradient(45deg, #667eea 30%, #764ba2 90%)',
|
||||
backgroundImage: `
|
||||
linear-gradient(120deg, transparent 0%, rgba(255,255,255,0.3) 50%, transparent 100%),
|
||||
linear-gradient(45deg, #667eea 30%, #764ba2 90%)
|
||||
`,
|
||||
backgroundSize: '200% 100%, 100% 100%',
|
||||
backgroundPosition: '200% 0, 0 0',
|
||||
boxShadow: '0 10px 40px rgba(102, 126, 234, 0.4)',
|
||||
'&:hover': {
|
||||
boxShadow: '0 15px 50px rgba(102, 126, 234, 0.5)',
|
||||
transform: 'translateY(-3px)',
|
||||
backgroundPosition: '0 0, 0 0'
|
||||
},
|
||||
transition: 'all 0.3s ease',
|
||||
animation: 'shimmer 2.5s ease-in-out infinite',
|
||||
'@keyframes shimmer': {
|
||||
'0%': { backgroundPosition: '200% 0, 0 0' },
|
||||
'100%': { backgroundPosition: '-200% 0, 0 0' },
|
||||
},
|
||||
}}
|
||||
>
|
||||
ALwrity For Free - BYOK
|
||||
</Button>
|
||||
</SignInButton>
|
||||
|
||||
<Typography
|
||||
variant="body1"
|
||||
sx={{
|
||||
color: 'rgba(255, 255, 255, 0.85)',
|
||||
fontWeight: 500,
|
||||
textShadow: '0 2px 6px rgba(0, 0, 0, 0.7)'
|
||||
}}
|
||||
>
|
||||
Bring Your Own Keys • No vendor lock-in • Enterprise security
|
||||
</Typography>
|
||||
|
||||
{/* Stats Row with Mini Charts */}
|
||||
<Grid container spacing={4} sx={{ mt: 1, mx: 'auto', maxWidth: '700px' }}>
|
||||
{stats.map((stat, index) => (
|
||||
<Grid item xs={6} md={3} key={index}>
|
||||
<Stack alignItems="center" spacing={1.5}>
|
||||
{/* Mini Progress Bar */}
|
||||
<Box sx={{ width: '100%', maxWidth: 80 }}>
|
||||
<Box
|
||||
sx={{
|
||||
height: 6,
|
||||
borderRadius: 3,
|
||||
background: 'rgba(255, 255, 255, 0.1)',
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
height: '100%',
|
||||
width: stat.value,
|
||||
background: 'linear-gradient(90deg, #667eea 0%, #764ba2 100%)',
|
||||
borderRadius: 3,
|
||||
boxShadow: '0 0 10px rgba(102, 126, 234, 0.6)',
|
||||
animation: 'fillBar 1.5s ease-out',
|
||||
'@keyframes fillBar': {
|
||||
'0%': { width: '0%' },
|
||||
'100%': { width: stat.value },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Typography
|
||||
variant="h3"
|
||||
sx={{
|
||||
fontWeight: 800,
|
||||
color: '#fff',
|
||||
textShadow: `
|
||||
0 2px 8px rgba(0, 0, 0, 0.9),
|
||||
0 0 20px rgba(102, 126, 234, 0.4)
|
||||
`,
|
||||
}}
|
||||
>
|
||||
{stat.value}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{
|
||||
color: 'rgba(255, 255, 255, 0.85)',
|
||||
fontWeight: 600,
|
||||
textShadow: '0 2px 6px rgba(0, 0, 0, 0.8)',
|
||||
fontSize: '0.85rem'
|
||||
}}
|
||||
>
|
||||
{stat.label}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Stack>
|
||||
</Box>
|
||||
</motion.div>
|
||||
</Stack>
|
||||
</motion.div>
|
||||
</Container>
|
||||
|
||||
{/* Bottom Fade Transition */}
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: -1,
|
||||
height: 100,
|
||||
background: `linear-gradient(180deg, rgba(0,0,0,0) 0%, ${alpha(theme.palette.background.default, 1)} 100%)`,
|
||||
zIndex: 0
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeroSection;
|
||||
|
||||
298
frontend/src/components/Landing/IntroducingAlwrity.tsx
Normal file
298
frontend/src/components/Landing/IntroducingAlwrity.tsx
Normal file
@@ -0,0 +1,298 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Container,
|
||||
Typography,
|
||||
Stack,
|
||||
Grid,
|
||||
Card,
|
||||
CardContent,
|
||||
useTheme,
|
||||
alpha,
|
||||
Skeleton
|
||||
} from '@mui/material';
|
||||
import { SignInButton } from '@clerk/clerk-react';
|
||||
import {
|
||||
RocketLaunch,
|
||||
Business,
|
||||
ContentCopy,
|
||||
TrendingUp,
|
||||
People,
|
||||
Code,
|
||||
Security,
|
||||
Speed
|
||||
} from '@mui/icons-material';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const IntroducingAlwrity: React.FC = () => {
|
||||
const theme = useTheme();
|
||||
const [imageLoaded, setImageLoaded] = useState(false);
|
||||
|
||||
// Preload the background image
|
||||
useEffect(() => {
|
||||
const img = new Image();
|
||||
img.onload = () => setImageLoaded(true);
|
||||
img.src = '/alwrity_landing_bg_vortex.png';
|
||||
}, []);
|
||||
|
||||
// Framer Motion variants
|
||||
const fadeInUp = {
|
||||
hidden: { opacity: 0, y: 24 },
|
||||
visible: { opacity: 1, y: 0, transition: { duration: 0.6, ease: "easeOut" as const } },
|
||||
};
|
||||
|
||||
const stagger = {
|
||||
hidden: {},
|
||||
visible: { transition: { staggerChildren: 0.12 } },
|
||||
};
|
||||
|
||||
// Platform capabilities instead of fake testimonials
|
||||
const platformCapabilities = [
|
||||
{
|
||||
icon: <Code />,
|
||||
title: 'Open Source Foundation',
|
||||
description: 'Built with transparency and community in mind. Full source code available on GitHub for inspection and contribution.',
|
||||
highlight: '100% Open Source'
|
||||
},
|
||||
{
|
||||
icon: <Security />,
|
||||
title: 'Privacy First',
|
||||
description: 'Your data stays yours. No tracking, no data mining, no selling of user information. Complete privacy protection.',
|
||||
highlight: 'Zero Tracking'
|
||||
},
|
||||
{
|
||||
icon: <Speed />,
|
||||
title: 'Lightning Fast',
|
||||
description: 'Optimized for speed and efficiency. Generate high-quality content in seconds, not minutes.',
|
||||
highlight: 'Sub-second Response'
|
||||
}
|
||||
];
|
||||
|
||||
const socialProofStats = [
|
||||
{ icon: <Business />, value: "1K+", label: "GitHub Stars" },
|
||||
{ icon: <ContentCopy />, value: "10K+", label: "Content Pieces Generated" },
|
||||
{ icon: <TrendingUp />, value: "95%", label: "User Satisfaction" },
|
||||
{ icon: <People />, value: "500+", label: "Active Contributors" }
|
||||
];
|
||||
|
||||
// Glassmorphism styles
|
||||
const glassCardSx = {
|
||||
background: `linear-gradient(135deg, ${alpha(theme.palette.common.white, 0.08)} 0%, ${alpha(theme.palette.common.white, 0.03)} 100%)`,
|
||||
backdropFilter: 'blur(16px)',
|
||||
border: '1px solid rgba(255,255,255,0.15)',
|
||||
borderRadius: 3,
|
||||
boxShadow: '0 15px 35px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.08)'
|
||||
} as const;
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'relative',
|
||||
minHeight: '100vh',
|
||||
backgroundImage: imageLoaded ? 'url(/alwrity_landing_bg_vortex.png)' : 'none',
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: 'center',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundColor: '#0a0a0a', // Fallback color
|
||||
transition: 'background-image 0.3s ease',
|
||||
'&::before': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
background: 'linear-gradient(135deg, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.5) 100%)',
|
||||
zIndex: 1
|
||||
}
|
||||
}}
|
||||
>
|
||||
{/* Loading skeleton for background image */}
|
||||
{!imageLoaded && (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
zIndex: 0
|
||||
}}
|
||||
>
|
||||
<Skeleton
|
||||
variant="rectangular"
|
||||
width="100%"
|
||||
height="100%"
|
||||
sx={{ bgcolor: 'rgba(255,255,255,0.1)' }}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
{/* Solution Bridge Section */}
|
||||
<Container maxWidth="lg" sx={{ py: 8, position: 'relative', zIndex: 2 }}>
|
||||
<motion.div variants={stagger} initial="hidden" whileInView="visible" viewport={{ once: true, amount: 0.2 }}>
|
||||
<Stack spacing={6} alignItems="center" textAlign="center">
|
||||
<motion.div variants={fadeInUp}>
|
||||
<Typography variant="h3" fontWeight={700} sx={{ color: 'white' }}>
|
||||
Introducing ALwrity
|
||||
</Typography>
|
||||
</motion.div>
|
||||
<motion.div variants={fadeInUp}>
|
||||
<Typography variant="h5" color="rgba(255,255,255,0.9)" maxWidth="800px">
|
||||
Transform from a manual implementer to a strategic director.
|
||||
ALwrity automates the entire content strategy process with AI-powered intelligence.
|
||||
</Typography>
|
||||
</motion.div>
|
||||
|
||||
<motion.div variants={fadeInUp}>
|
||||
<Box sx={{ mt: 4 }}>
|
||||
<SignInButton mode="redirect" forceRedirectUrl="/">
|
||||
<Button
|
||||
variant="contained"
|
||||
size="large"
|
||||
startIcon={<RocketLaunch />}
|
||||
sx={{
|
||||
py: 2,
|
||||
px: 6,
|
||||
fontSize: '1.2rem',
|
||||
fontWeight: 600,
|
||||
borderRadius: 2,
|
||||
background: 'linear-gradient(45deg, #667eea 30%, #764ba2 90%)',
|
||||
boxShadow: '0 8px 32px rgba(102, 126, 234, 0.3)',
|
||||
'&:hover': {
|
||||
boxShadow: '0 12px 40px rgba(102, 126, 234, 0.4)',
|
||||
transform: 'translateY(-2px)'
|
||||
},
|
||||
transition: 'all 0.3s ease'
|
||||
}}
|
||||
>
|
||||
Start Your AI Journey
|
||||
</Button>
|
||||
</SignInButton>
|
||||
</Box>
|
||||
</motion.div>
|
||||
</Stack>
|
||||
</motion.div>
|
||||
</Container>
|
||||
|
||||
{/* Platform Capabilities Section */}
|
||||
<Container maxWidth="lg" sx={{ py: 8, position: 'relative', zIndex: 2 }}>
|
||||
<motion.div variants={stagger} initial="hidden" whileInView="visible" viewport={{ once: true, amount: 0.2 }}>
|
||||
<Stack spacing={6} alignItems="center">
|
||||
<motion.div variants={fadeInUp}>
|
||||
<Stack spacing={2} alignItems="center" textAlign="center">
|
||||
<Typography variant="h3" fontWeight={700} sx={{ color: 'white' }}>
|
||||
Why Choose ALwrity?
|
||||
</Typography>
|
||||
<Typography variant="h6" color="rgba(255,255,255,0.9)" maxWidth="700px">
|
||||
Built for creators, by creators. Open-source, privacy-focused, and designed to scale with your ambitions.
|
||||
</Typography>
|
||||
</Stack>
|
||||
</motion.div>
|
||||
|
||||
<Grid container spacing={4}>
|
||||
{platformCapabilities.map((capability, index) => (
|
||||
<Grid item xs={12} md={4} key={index}>
|
||||
<motion.div variants={fadeInUp}>
|
||||
<Card sx={{ ...glassCardSx, height: '100%', transition: 'all 0.3s ease', '&:hover': { transform: 'translateY(-8px)', boxShadow: `0 24px 48px ${alpha(theme.palette.primary.main, 0.18)}`, borderColor: alpha('#fff', 0.2) } }}>
|
||||
<CardContent sx={{ p: 4 }}>
|
||||
<Stack spacing={3}>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="flex-start">
|
||||
<Box
|
||||
sx={{
|
||||
width: 56,
|
||||
height: 56,
|
||||
borderRadius: 2,
|
||||
background: `linear-gradient(45deg, ${alpha(theme.palette.primary.main, 0.2)}, ${alpha(theme.palette.secondary.main, 0.2)})`,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
color: theme.palette.primary.main
|
||||
}}
|
||||
>
|
||||
{capability.icon}
|
||||
</Box>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{
|
||||
background: alpha(theme.palette.primary.main, 0.1),
|
||||
color: theme.palette.primary.main,
|
||||
fontWeight: 600,
|
||||
px: 2,
|
||||
py: 0.5,
|
||||
borderRadius: 1
|
||||
}}
|
||||
>
|
||||
{capability.highlight}
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Stack spacing={2}>
|
||||
<Typography variant="h6" fontWeight={700} sx={{ fontSize: '1.1rem', color: 'white' }}>
|
||||
{capability.title}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="rgba(255,255,255,0.8)" lineHeight={1.6} sx={{ fontSize: '0.95rem' }}>
|
||||
{capability.description}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</motion.div>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Stack>
|
||||
</motion.div>
|
||||
</Container>
|
||||
|
||||
{/* Social Proof Stats */}
|
||||
<Container maxWidth="lg" sx={{ py: 6, position: 'relative', zIndex: 2 }}>
|
||||
<motion.div variants={stagger} initial="hidden" whileInView="visible" viewport={{ once: true, amount: 0.2 }}>
|
||||
<Grid container spacing={4}>
|
||||
{socialProofStats.map((stat, index) => (
|
||||
<Grid item xs={6} md={3} key={index}>
|
||||
<motion.div variants={fadeInUp}>
|
||||
<Stack alignItems="center" spacing={2}>
|
||||
<Box
|
||||
sx={{
|
||||
width: 56,
|
||||
height: 56,
|
||||
borderRadius: 2,
|
||||
background: `linear-gradient(45deg, ${alpha(theme.palette.primary.main, 0.2)}, ${alpha(theme.palette.secondary.main, 0.2)})`,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
color: theme.palette.primary.main
|
||||
}}
|
||||
>
|
||||
{stat.icon}
|
||||
</Box>
|
||||
<Stack alignItems="center" spacing={0.5}>
|
||||
<Typography
|
||||
variant="h4"
|
||||
sx={{
|
||||
fontWeight: 800,
|
||||
background: 'linear-gradient(45deg, #667eea 30%, #764ba2 90%)',
|
||||
WebkitBackgroundClip: 'text',
|
||||
WebkitTextFillColor: 'transparent',
|
||||
color: 'white'
|
||||
}}
|
||||
>
|
||||
{stat.value}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="rgba(255,255,255,0.8)" fontWeight={500} textAlign="center">
|
||||
{stat.label}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</motion.div>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</motion.div>
|
||||
</Container>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default IntroducingAlwrity;
|
||||
623
frontend/src/components/Landing/Landing.tsx
Normal file
623
frontend/src/components/Landing/Landing.tsx
Normal file
@@ -0,0 +1,623 @@
|
||||
import React, { Suspense, lazy } from 'react';
|
||||
import usePerformanceMonitor from '../../hooks/usePerformanceMonitor';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Container,
|
||||
Typography,
|
||||
Stack,
|
||||
Grid,
|
||||
Card,
|
||||
CardContent,
|
||||
Chip,
|
||||
Avatar,
|
||||
useTheme,
|
||||
alpha,
|
||||
CircularProgress
|
||||
} from '@mui/material';
|
||||
import { keyframes } from '@mui/system';
|
||||
import { SignInButton } from '@clerk/clerk-react';
|
||||
import {
|
||||
AutoAwesome,
|
||||
Speed,
|
||||
TrendingUp,
|
||||
Security,
|
||||
Analytics,
|
||||
Psychology,
|
||||
AccessTime,
|
||||
MonetizationOn,
|
||||
TrendingDown,
|
||||
Group,
|
||||
CalendarToday,
|
||||
Create,
|
||||
Publish,
|
||||
Chat,
|
||||
Refresh,
|
||||
OpenInNew
|
||||
} from '@mui/icons-material';
|
||||
import { motion } from 'framer-motion';
|
||||
import HeroSection from './HeroSection';
|
||||
|
||||
// Lazy load components for better performance
|
||||
const FeatureShowcase = lazy(() => import('./FeatureShowcase'));
|
||||
const SolopreneurDilemma = lazy(() => import('./SolopreneurDilemma'));
|
||||
const EnterpriseCTA = lazy(() => import('./EnterpriseCTA'));
|
||||
const IntroducingAlwrity = lazy(() => import('./IntroducingAlwrity'));
|
||||
|
||||
const Landing: React.FC = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
// Monitor performance
|
||||
usePerformanceMonitor('Landing');
|
||||
|
||||
// Optimized Framer Motion variants for better performance
|
||||
const fadeInUp = {
|
||||
hidden: { opacity: 0, y: 24 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
duration: 0.4,
|
||||
ease: "easeOut" as const,
|
||||
// Use transform3d for hardware acceleration
|
||||
transform: "translate3d(0,0,0)"
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const stagger = {
|
||||
hidden: {},
|
||||
visible: {
|
||||
transition: {
|
||||
staggerChildren: 0.08, // Reduced stagger time
|
||||
delayChildren: 0.1
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Cinematic lifecycle section animations
|
||||
const backgroundFade = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: { duration: 1, ease: "easeInOut" as const }
|
||||
}
|
||||
};
|
||||
|
||||
const titleFlyIn = {
|
||||
hidden: { opacity: 0, y: -80, scale: 0.8 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
scale: 1,
|
||||
transition: {
|
||||
delay: 1,
|
||||
duration: 0.8,
|
||||
ease: [0.22, 1, 0.36, 1] as const // Custom easing
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const chipsFlyIn = {
|
||||
hidden: { opacity: 0, y: 60 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
delay: 1.3,
|
||||
duration: 0.7,
|
||||
ease: "easeOut" as const
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const descriptionFade = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
delay: 1.6,
|
||||
duration: 0.6
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Card zoom animations from different directions
|
||||
const cardVariants = [
|
||||
// Top-left
|
||||
{
|
||||
hidden: { opacity: 0, scale: 0.3, x: -200, y: -200, rotate: -15 },
|
||||
visible: { opacity: 1, scale: 1, x: 0, y: 0, rotate: 0 }
|
||||
},
|
||||
// Top
|
||||
{
|
||||
hidden: { opacity: 0, scale: 0.3, y: -250, rotate: 0 },
|
||||
visible: { opacity: 1, scale: 1, y: 0, rotate: 0 }
|
||||
},
|
||||
// Top-right
|
||||
{
|
||||
hidden: { opacity: 0, scale: 0.3, x: 200, y: -200, rotate: 15 },
|
||||
visible: { opacity: 1, scale: 1, x: 0, y: 0, rotate: 0 }
|
||||
},
|
||||
// Bottom-left
|
||||
{
|
||||
hidden: { opacity: 0, scale: 0.3, x: -200, y: 200, rotate: 15 },
|
||||
visible: { opacity: 1, scale: 1, x: 0, y: 0, rotate: 0 }
|
||||
},
|
||||
// Bottom
|
||||
{
|
||||
hidden: { opacity: 0, scale: 0.3, y: 250, rotate: 0 },
|
||||
visible: { opacity: 1, scale: 1, y: 0, rotate: 0 }
|
||||
},
|
||||
// Bottom-right
|
||||
{
|
||||
hidden: { opacity: 0, scale: 0.3, x: 200, y: 200, rotate: -15 },
|
||||
visible: { opacity: 1, scale: 1, x: 0, y: 0, rotate: 0 }
|
||||
}
|
||||
];
|
||||
|
||||
const cardsStagger = {
|
||||
hidden: {},
|
||||
visible: {
|
||||
transition: {
|
||||
delayChildren: 2,
|
||||
staggerChildren: 0.15
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: <CalendarToday />,
|
||||
title: 'Content Planning',
|
||||
description: 'ALwrity builds a living strategy and calendar from your goals, audience and market signals. Drag-and-drop calendar, briefs, topics and distribution plans generated automatically.',
|
||||
badge: 'Strategy'
|
||||
},
|
||||
{
|
||||
icon: <Create />,
|
||||
title: 'Content Generation',
|
||||
description: 'Generate text, images, audio, video and channel-ready posts for LinkedIn, Facebook, Instagram and blogs. Templates, brand voice and Personas baked in.',
|
||||
badge: 'Multi‑Format'
|
||||
},
|
||||
{
|
||||
icon: <Publish />,
|
||||
title: 'Content Publishing',
|
||||
description: 'Publish and schedule directly to connected social channels and your website. One-click cross‑posting while preserving native formats.',
|
||||
badge: 'Automated'
|
||||
},
|
||||
{
|
||||
icon: <Analytics />,
|
||||
title: 'Content Analytics',
|
||||
description: 'Pulls analytics from connected platforms, analyzes with AI and surfaces actionable insights. Signals flow back to strategy and calendar for adaptive learning.',
|
||||
badge: 'AI Insights'
|
||||
},
|
||||
{
|
||||
icon: <Chat />,
|
||||
title: 'Content Engagement',
|
||||
description: 'Monitor comments, DMs and reactions. Research communities and reply with AI assistance from within ALwrity to grow audience authentically.',
|
||||
badge: 'Community'
|
||||
},
|
||||
{
|
||||
icon: <Refresh />,
|
||||
title: 'Content Remarketing',
|
||||
description: 'Analyzes historic performance, suggests edits, variants and redistribution. Measures KPI attainment and explains what worked—and what did not.',
|
||||
badge: 'Optimization'
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
const painPoints = [
|
||||
{
|
||||
icon: <AccessTime />,
|
||||
title: 'Time Constraints',
|
||||
description: 'Limited time for content creation and strategy development. Solopreneurs wear many hats and struggle to maintain consistent content output.'
|
||||
},
|
||||
{
|
||||
icon: <TrendingDown />,
|
||||
title: 'Lack of Expertise',
|
||||
description: 'Not trained as content strategists, SEO experts, or data analysts. Missing the knowledge to create effective marketing campaigns.'
|
||||
},
|
||||
{
|
||||
icon: <MonetizationOn />,
|
||||
title: 'Resource Limitations',
|
||||
description: 'Cannot afford full marketing teams or expensive enterprise tools. Need cost-effective solutions that deliver professional results.'
|
||||
},
|
||||
{
|
||||
icon: <Analytics />,
|
||||
title: 'Poor ROI Tracking',
|
||||
description: 'Only 21% of marketers successfully track content ROI. Lack of data-driven insights to optimize marketing spend and strategy.'
|
||||
},
|
||||
{
|
||||
icon: <Group />,
|
||||
title: 'Manual Processes',
|
||||
description: 'Overwhelmed by repetitive content creation tasks. Need automation to scale efforts without sacrificing quality.'
|
||||
},
|
||||
{
|
||||
icon: <Psychology />,
|
||||
title: 'Inconsistent Voice',
|
||||
description: 'Struggle to maintain brand voice across platforms. Need personalized AI that understands your unique style and messaging.'
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
|
||||
// Glassmorphism styles
|
||||
const glassPanelSx = {
|
||||
background: `linear-gradient(135deg, ${alpha(theme.palette.common.white, 0.06)} 0%, ${alpha(theme.palette.common.white, 0.02)} 100%)`,
|
||||
backdropFilter: 'blur(12px)',
|
||||
border: '1px solid rgba(255,255,255,0.12)',
|
||||
borderRadius: 4,
|
||||
boxShadow: '0 10px 30px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.06)'
|
||||
} as const;
|
||||
|
||||
const glassCardSx = {
|
||||
background: `linear-gradient(135deg, ${alpha(theme.palette.common.white, 0.05)} 0%, ${alpha(theme.palette.common.white, 0.015)} 100%)`,
|
||||
backdropFilter: 'blur(14px)',
|
||||
border: '1px solid rgba(255,255,255,0.12)',
|
||||
borderRadius: 3,
|
||||
boxShadow: '0 10px 25px rgba(0,0,0,0.28), inset 0 1px 0 rgba(255,255,255,0.06)',
|
||||
p: 0
|
||||
} as const;
|
||||
|
||||
// Shimmer animation for lifecycle chip line
|
||||
const shimmer = keyframes`
|
||||
0% { background-position: 0% 50%; }
|
||||
100% { background-position: 100% 50%; }
|
||||
`;
|
||||
|
||||
// Glow pulse animation for chips
|
||||
const glowPulse = keyframes`
|
||||
0%, 100% {
|
||||
box-shadow: 0 0 10px ${alpha(theme.palette.primary.main, 0.3)},
|
||||
0 0 20px ${alpha(theme.palette.primary.main, 0.2)},
|
||||
inset 0 0 10px ${alpha(theme.palette.primary.main, 0.1)};
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 20px ${alpha(theme.palette.primary.main, 0.6)},
|
||||
0 0 30px ${alpha(theme.palette.primary.main, 0.4)},
|
||||
inset 0 0 15px ${alpha(theme.palette.primary.main, 0.2)};
|
||||
}
|
||||
`;
|
||||
|
||||
// Slide in animation for lifecycle image
|
||||
const slideIn = keyframes`
|
||||
0% { opacity: 0; transform: scale(0.9) translateY(20px); }
|
||||
100% { opacity: 1; transform: scale(1) translateY(0); }
|
||||
`;
|
||||
|
||||
// Loading component for Suspense
|
||||
const LoadingSpinner = () => (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
py: 8,
|
||||
minHeight: '200px'
|
||||
}}
|
||||
>
|
||||
<CircularProgress size={40} />
|
||||
</Box>
|
||||
);
|
||||
|
||||
return (
|
||||
<Box sx={{ minHeight: '100vh', overflow: 'hidden', position: 'relative' }}>
|
||||
{/* Hero Section - Extracted to separate component */}
|
||||
<HeroSection />
|
||||
|
||||
{/* Lifecycle Section with Background Image */}
|
||||
<Box
|
||||
sx={{
|
||||
position: 'relative',
|
||||
minHeight: '100vh',
|
||||
py: 12,
|
||||
overflow: 'hidden'
|
||||
}}
|
||||
>
|
||||
{/* Background Image Layer */}
|
||||
<motion.div
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true, amount: 0.1 }}
|
||||
variants={backgroundFade}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundImage: 'url(/content_lifecycle.png)',
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: 'center',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
zIndex: 0
|
||||
}}
|
||||
/>
|
||||
{/* Dark overlay for readability */}
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
background: `linear-gradient(
|
||||
135deg,
|
||||
rgba(0,0,0,0.85) 0%,
|
||||
rgba(0,0,0,0.75) 50%,
|
||||
rgba(0,0,0,0.85) 100%
|
||||
)`,
|
||||
backdropFilter: 'blur(2px)',
|
||||
zIndex: 1
|
||||
}}
|
||||
/>
|
||||
</motion.div>
|
||||
|
||||
{/* Content Layer */}
|
||||
<Container maxWidth="lg" sx={{ position: 'relative', zIndex: 2 }}>
|
||||
<motion.div
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true, amount: 0.1 }}
|
||||
>
|
||||
<Stack spacing={8} alignItems="center">
|
||||
{/* Title */}
|
||||
<motion.div variants={titleFlyIn} style={{ width: '100%' }}>
|
||||
<Stack spacing={3} alignItems="center" textAlign="center">
|
||||
<Typography
|
||||
variant="h2"
|
||||
fontWeight={700}
|
||||
sx={{
|
||||
color: 'white',
|
||||
textShadow: `0 0 30px ${alpha(theme.palette.primary.main, 0.5)}, 0 4px 20px rgba(0,0,0,0.8)`
|
||||
}}
|
||||
>
|
||||
ALwrity Content Lifecycle
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="h5"
|
||||
fontWeight={600}
|
||||
sx={{
|
||||
color: alpha('#fff', 0.9),
|
||||
textShadow: '0 2px 10px rgba(0,0,0,0.6)'
|
||||
}}
|
||||
>
|
||||
End‑to‑End, HITL by Design
|
||||
</Typography>
|
||||
</Stack>
|
||||
</motion.div>
|
||||
|
||||
{/* Phases chips with animated connector */}
|
||||
<motion.div variants={chipsFlyIn} style={{ width: '100%' }}>
|
||||
<Box sx={{ position: 'relative', width: '100%', maxWidth: 1100, px: { xs: 2, md: 4 }, py: 2 }}>
|
||||
{/* animated line */}
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: { xs: 28, md: 32 },
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: 3,
|
||||
borderRadius: 2,
|
||||
background: `linear-gradient(90deg,
|
||||
${alpha(theme.palette.primary.main, 0.4)},
|
||||
${alpha(theme.palette.secondary.main, 0.5)},
|
||||
${alpha(theme.palette.primary.main, 0.4)})`,
|
||||
overflow: 'hidden',
|
||||
boxShadow: `0 0 20px ${alpha(theme.palette.primary.main, 0.6)}`
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: '40%',
|
||||
height: '100%',
|
||||
background: `linear-gradient(90deg,
|
||||
transparent,
|
||||
${alpha(theme.palette.primary.main, 1)},
|
||||
${alpha(theme.palette.secondary.main, 1)},
|
||||
transparent)`,
|
||||
backgroundSize: '200% 100%',
|
||||
animation: `${shimmer} 3s ease-in-out infinite`
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
{/* chips */}
|
||||
<Grid container spacing={{ xs: 1, md: 2 }} justifyContent="space-between" alignItems="center">
|
||||
{['Plan','Generate','Publish','Analyze','Engage','Remarket'].map((label, idx) => (
|
||||
<Grid item key={label} xs={2} sx={{ display: 'flex', justifyContent: idx === 0 ? 'flex-start' : idx === 5 ? 'flex-end' : 'center' }}>
|
||||
<Chip
|
||||
label={
|
||||
<Stack direction="row" spacing={0.5} alignItems="center">
|
||||
<Typography
|
||||
variant="caption"
|
||||
sx={{
|
||||
fontWeight: 800,
|
||||
fontSize: { xs: '0.65rem', md: '0.75rem' },
|
||||
color: 'primary.main'
|
||||
}}
|
||||
>
|
||||
{idx+1}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="caption"
|
||||
sx={{
|
||||
fontWeight: 700,
|
||||
fontSize: { xs: '0.7rem', md: '0.8rem' },
|
||||
color: 'white'
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</Typography>
|
||||
</Stack>
|
||||
}
|
||||
size="medium"
|
||||
sx={{
|
||||
px: { xs: 1, md: 2 },
|
||||
py: { xs: 1.5, md: 2 },
|
||||
fontWeight: 700,
|
||||
letterSpacing: 0.5,
|
||||
background: `linear-gradient(135deg,
|
||||
${alpha(theme.palette.primary.main, 0.3)},
|
||||
${alpha(theme.palette.secondary.main, 0.3)})`,
|
||||
border: `2px solid ${alpha(theme.palette.primary.main, 0.6)}`,
|
||||
backdropFilter: 'blur(12px)',
|
||||
animation: `${glowPulse} 3s ease-in-out infinite`,
|
||||
animationDelay: `${idx * 0.3}s`,
|
||||
transition: 'all 0.3s ease',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.1) translateY(-2px)',
|
||||
background: `linear-gradient(135deg,
|
||||
${alpha(theme.palette.primary.main, 0.5)},
|
||||
${alpha(theme.palette.secondary.main, 0.5)})`,
|
||||
boxShadow: `0 8px 30px ${alpha(theme.palette.primary.main, 0.7)}`
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Box>
|
||||
</motion.div>
|
||||
|
||||
{/* Description */}
|
||||
<motion.div variants={descriptionFade}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
color={alpha('#fff', 0.9)}
|
||||
maxWidth="900px"
|
||||
textAlign="center"
|
||||
sx={{
|
||||
textShadow: '0 2px 10px rgba(0,0,0,0.6)',
|
||||
lineHeight: 1.8
|
||||
}}
|
||||
>
|
||||
ALwrity automates each phase with AI while you review and approve as the human‑in‑the‑loop.
|
||||
</Typography>
|
||||
</motion.div>
|
||||
|
||||
{/* Cards with zoom animations */}
|
||||
<motion.div
|
||||
variants={cardsStagger}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true, amount: 0.1 }}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
<Grid container spacing={2.5}>
|
||||
{features.map((feature, index) => (
|
||||
<Grid item xs={12} md={6} lg={4} key={index}>
|
||||
<motion.div
|
||||
variants={cardVariants[index]}
|
||||
transition={{
|
||||
duration: 0.6,
|
||||
ease: [0.25, 0.46, 0.45, 0.94]
|
||||
}}
|
||||
>
|
||||
<Card
|
||||
sx={{
|
||||
...glassCardSx,
|
||||
height: '100%',
|
||||
background: `linear-gradient(135deg, ${alpha(theme.palette.common.white, 0.08)} 0%, ${alpha(theme.palette.common.white, 0.03)} 100%)`,
|
||||
backdropFilter: 'blur(20px)',
|
||||
border: `1px solid ${alpha(theme.palette.common.white, 0.15)}`,
|
||||
transition: 'all 0.25s ease',
|
||||
'&:hover': {
|
||||
transform: 'translateY(-6px)',
|
||||
boxShadow: `0 24px 48px ${alpha(theme.palette.primary.main, 0.25)}`,
|
||||
borderColor: alpha(theme.palette.primary.main, 0.4)
|
||||
}
|
||||
}}
|
||||
>
|
||||
<CardContent sx={{ p: 3 }}>
|
||||
<Stack spacing={2}>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
||||
<Avatar
|
||||
sx={{
|
||||
width: 44,
|
||||
height: 44,
|
||||
borderRadius: 2,
|
||||
background: `linear-gradient(45deg, ${alpha(theme.palette.primary.main, 0.25)}, ${alpha(theme.palette.secondary.main, 0.25)})`,
|
||||
color: theme.palette.primary.main
|
||||
}}
|
||||
>
|
||||
{feature.icon}
|
||||
</Avatar>
|
||||
<Chip
|
||||
label={feature.badge}
|
||||
size="small"
|
||||
sx={{
|
||||
background: alpha(theme.palette.primary.main, 0.2),
|
||||
color: theme.palette.primary.main,
|
||||
fontWeight: 600,
|
||||
backdropFilter: 'blur(10px)'
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack spacing={1.25}>
|
||||
<Typography variant="h6" fontWeight={700} sx={{ fontSize: '1.05rem', color: 'white' }}>
|
||||
{feature.title}
|
||||
</Typography>
|
||||
<Typography variant="body2" color={alpha('#fff', 0.85)} lineHeight={1.6} sx={{ fontSize: '0.93rem' }}>
|
||||
{feature.description}
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Box sx={{ pt: 0.5 }}>
|
||||
<Button
|
||||
size="small"
|
||||
endIcon={<OpenInNew sx={{ fontSize: 16 }} />}
|
||||
sx={{
|
||||
textTransform: 'none',
|
||||
fontWeight: 600,
|
||||
px: 0,
|
||||
minWidth: 0,
|
||||
color: theme.palette.primary.main,
|
||||
'&:hover': {
|
||||
color: theme.palette.primary.light
|
||||
}
|
||||
}}
|
||||
href="#"
|
||||
>
|
||||
Learn more
|
||||
</Button>
|
||||
</Box>
|
||||
</Stack>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</motion.div>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</motion.div>
|
||||
</Stack>
|
||||
</motion.div>
|
||||
</Container>
|
||||
</Box>
|
||||
|
||||
{/* Feature Showcase with Carousel - Lazy Loaded */}
|
||||
<Suspense fallback={<LoadingSpinner />}>
|
||||
<FeatureShowcase />
|
||||
</Suspense>
|
||||
|
||||
{/* The Solopreneur's Dilemma Section - Lazy Loaded */}
|
||||
<Suspense fallback={<LoadingSpinner />}>
|
||||
<SolopreneurDilemma />
|
||||
</Suspense>
|
||||
|
||||
{/* Introducing ALwrity Section with Background - Lazy Loaded */}
|
||||
<Suspense fallback={<LoadingSpinner />}>
|
||||
<IntroducingAlwrity />
|
||||
</Suspense>
|
||||
|
||||
{/* Final CTA Section - Lazy Loaded */}
|
||||
<Suspense fallback={<LoadingSpinner />}>
|
||||
<EnterpriseCTA />
|
||||
</Suspense>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Landing;
|
||||
|
||||
|
||||
97
frontend/src/components/Landing/OptimizedImage.tsx
Normal file
97
frontend/src/components/Landing/OptimizedImage.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { Box, Skeleton } from '@mui/material';
|
||||
|
||||
interface OptimizedImageProps {
|
||||
src: string;
|
||||
alt: string;
|
||||
width?: string | number;
|
||||
height?: string | number;
|
||||
sx?: object;
|
||||
priority?: boolean;
|
||||
placeholder?: 'blur' | 'empty';
|
||||
}
|
||||
|
||||
const OptimizedImage: React.FC<OptimizedImageProps> = ({
|
||||
src,
|
||||
alt,
|
||||
width = '100%',
|
||||
height = 'auto',
|
||||
sx = {},
|
||||
priority = false,
|
||||
placeholder = 'blur'
|
||||
}) => {
|
||||
const [imageLoaded, setImageLoaded] = useState(false);
|
||||
const [imageError, setImageError] = useState(false);
|
||||
|
||||
const handleLoad = useCallback(() => {
|
||||
setImageLoaded(true);
|
||||
}, []);
|
||||
|
||||
const handleError = useCallback(() => {
|
||||
setImageError(true);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'relative',
|
||||
width,
|
||||
height,
|
||||
overflow: 'hidden',
|
||||
...sx
|
||||
}}
|
||||
>
|
||||
{!imageLoaded && !imageError && (
|
||||
<Skeleton
|
||||
variant="rectangular"
|
||||
width="100%"
|
||||
height="100%"
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
bgcolor: 'rgba(255,255,255,0.1)'
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!imageError && (
|
||||
<Box
|
||||
component="img"
|
||||
src={src}
|
||||
alt={alt}
|
||||
onLoad={handleLoad}
|
||||
onError={handleError}
|
||||
loading={priority ? 'eager' : 'lazy'}
|
||||
decoding="async"
|
||||
sx={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'cover',
|
||||
opacity: imageLoaded ? 1 : 0,
|
||||
transition: 'opacity 0.3s ease',
|
||||
...sx
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{imageError && (
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: 'rgba(255,255,255,0.1)',
|
||||
color: 'text.secondary'
|
||||
}}
|
||||
>
|
||||
Image failed to load
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default OptimizedImage;
|
||||
392
frontend/src/components/Landing/SolopreneurDilemma.tsx
Normal file
392
frontend/src/components/Landing/SolopreneurDilemma.tsx
Normal file
@@ -0,0 +1,392 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Box,
|
||||
Container,
|
||||
Typography,
|
||||
Stack,
|
||||
Grid,
|
||||
useTheme,
|
||||
alpha,
|
||||
Button
|
||||
} from '@mui/material';
|
||||
import {
|
||||
Psychology,
|
||||
TrendingUp,
|
||||
Speed,
|
||||
CheckCircle,
|
||||
ArrowForward
|
||||
} from '@mui/icons-material';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const SolopreneurDilemma: React.FC = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
const painPoints = [
|
||||
{
|
||||
icon: <Psychology />,
|
||||
title: "Content Overwhelm",
|
||||
description: "Managing 8+ social platforms with different audiences, tones, and posting schedules"
|
||||
},
|
||||
{
|
||||
icon: <TrendingUp />,
|
||||
title: "Inconsistent Brand Voice",
|
||||
description: "Struggling to maintain your unique voice across all platforms while scaling content"
|
||||
},
|
||||
{
|
||||
icon: <Speed />,
|
||||
title: "Time Drain",
|
||||
description: "Spending 4-6 hours daily on content creation, research, and platform management"
|
||||
}
|
||||
];
|
||||
|
||||
const solutions = [
|
||||
{
|
||||
icon: <CheckCircle />,
|
||||
title: "Unified AI Copilot",
|
||||
description: "One intelligent assistant that understands your brand voice and adapts to each platform"
|
||||
},
|
||||
{
|
||||
icon: <CheckCircle />,
|
||||
title: "Automated Research",
|
||||
description: "AI-powered competitor analysis and trend discovery across 25+ sources"
|
||||
},
|
||||
{
|
||||
icon: <CheckCircle />,
|
||||
title: "Content at Scale",
|
||||
description: "Generate weeks of content in minutes, not hours, with fact-checked accuracy"
|
||||
}
|
||||
];
|
||||
|
||||
const containerVariants = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.2,
|
||||
delayChildren: 0.1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const itemVariants = {
|
||||
hidden: { opacity: 0, y: 30 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
duration: 0.6,
|
||||
ease: "easeOut" as const
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'relative',
|
||||
py: { xs: 8, md: 12 },
|
||||
'&::before': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundImage: 'url(/alwrity_landing_pg_bg.png)',
|
||||
backgroundSize: 'contain',
|
||||
backgroundPosition: 'center',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
zIndex: 0,
|
||||
},
|
||||
'&::after': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
background: 'linear-gradient(135deg, rgba(0, 0, 0, 0.7) 0%, rgba(25, 118, 210, 0.3) 50%, rgba(156, 39, 176, 0.3) 100%)',
|
||||
zIndex: 1,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Container maxWidth="lg" sx={{ position: 'relative', zIndex: 2, pt: { xs: 2, md: 3 } }}>
|
||||
<motion.div
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true, amount: 0.3 }}
|
||||
>
|
||||
{/* Section Header - Side by Side */}
|
||||
<Stack
|
||||
direction={{ xs: 'column', md: 'row' }}
|
||||
spacing={{ xs: 1, md: 2 }}
|
||||
alignItems={{ xs: 'center', md: 'flex-start' }}
|
||||
sx={{ mb: 6 }}
|
||||
>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<motion.div variants={itemVariants}>
|
||||
<Typography
|
||||
variant="h2"
|
||||
fontWeight={800}
|
||||
sx={{
|
||||
fontSize: { xs: '2.5rem', md: '3.5rem' },
|
||||
color: 'white',
|
||||
textShadow: '0 2px 10px rgba(0, 0, 0, 0.8)',
|
||||
letterSpacing: '-0.02em'
|
||||
}}
|
||||
>
|
||||
The Content Struggle is Real
|
||||
</Typography>
|
||||
</motion.div>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<motion.div variants={itemVariants}>
|
||||
<Typography
|
||||
variant="h5"
|
||||
sx={{
|
||||
color: 'rgba(255, 255, 255, 0.9)',
|
||||
fontWeight: 400,
|
||||
textShadow: '0 1px 3px rgba(0, 0, 0, 0.7)',
|
||||
lineHeight: 1.4
|
||||
}}
|
||||
>
|
||||
You're juggling multiple platforms, struggling to maintain your voice,
|
||||
and spending hours on content that should take minutes.
|
||||
</Typography>
|
||||
</motion.div>
|
||||
</Box>
|
||||
</Stack>
|
||||
|
||||
<Box sx={{ ml: { xs: 0, md: '45%' } }}>
|
||||
<Grid container spacing={6} alignItems="center">
|
||||
{/* Left Column - Pain Points */}
|
||||
<Grid item xs={12} md={6}>
|
||||
<motion.div variants={itemVariants}>
|
||||
<Stack spacing={4}>
|
||||
{/* Before ALwrity Label */}
|
||||
<Box
|
||||
sx={{
|
||||
display: 'inline-block',
|
||||
px: 2,
|
||||
py: 1,
|
||||
background: `linear-gradient(135deg, ${theme.palette.error.main} 0%, ${theme.palette.error.dark} 100%)`,
|
||||
borderRadius: 2,
|
||||
mb: 2
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="caption"
|
||||
fontWeight={700}
|
||||
sx={{
|
||||
color: 'white',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: '1px',
|
||||
fontSize: '0.8rem'
|
||||
}}
|
||||
>
|
||||
Before ALwrity
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
|
||||
|
||||
{painPoints.map((point, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
variants={itemVariants}
|
||||
whileHover={{ scale: 1.02 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
p: 3,
|
||||
borderRadius: 3,
|
||||
background: `linear-gradient(135deg, ${alpha(theme.palette.error.main, 0.1)} 0%, ${alpha(theme.palette.error.dark, 0.05)} 100%)`,
|
||||
border: `1px solid ${alpha(theme.palette.error.main, 0.2)}`,
|
||||
backdropFilter: 'blur(10px)',
|
||||
transition: 'all 0.3s ease',
|
||||
'&:hover': {
|
||||
background: `linear-gradient(135deg, ${alpha(theme.palette.error.main, 0.15)} 0%, ${alpha(theme.palette.error.dark, 0.08)} 100%)`,
|
||||
border: `1px solid ${alpha(theme.palette.error.main, 0.3)}`,
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" spacing={2} alignItems="flex-start">
|
||||
<Box
|
||||
sx={{
|
||||
p: 1.5,
|
||||
borderRadius: 2,
|
||||
background: `linear-gradient(135deg, ${theme.palette.error.main} 0%, ${theme.palette.error.dark} 100%)`,
|
||||
color: 'white',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
minWidth: 48,
|
||||
height: 48,
|
||||
}}
|
||||
>
|
||||
{point.icon}
|
||||
</Box>
|
||||
<Stack spacing={1} sx={{ flex: 1 }}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
fontWeight={600}
|
||||
sx={{
|
||||
color: 'white',
|
||||
textShadow: '0 1px 2px rgba(0, 0, 0, 0.7)'
|
||||
}}
|
||||
>
|
||||
{point.title}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body1"
|
||||
sx={{
|
||||
color: 'rgba(255, 255, 255, 0.8)',
|
||||
textShadow: '0 1px 2px rgba(0, 0, 0, 0.5)',
|
||||
lineHeight: 1.5
|
||||
}}
|
||||
>
|
||||
{point.description}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Box>
|
||||
</motion.div>
|
||||
))}
|
||||
</Stack>
|
||||
</motion.div>
|
||||
</Grid>
|
||||
|
||||
{/* Right Column - Solutions */}
|
||||
<Grid item xs={12} md={6}>
|
||||
<motion.div variants={itemVariants}>
|
||||
<Stack spacing={4}>
|
||||
{/* After ALwrity Label */}
|
||||
<Box
|
||||
sx={{
|
||||
display: 'inline-block',
|
||||
px: 2,
|
||||
py: 1,
|
||||
background: `linear-gradient(135deg, ${theme.palette.success.main} 0%, ${theme.palette.success.dark} 100%)`,
|
||||
borderRadius: 2,
|
||||
mb: 2
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="caption"
|
||||
fontWeight={700}
|
||||
sx={{
|
||||
color: 'white',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: '1px',
|
||||
fontSize: '0.8rem'
|
||||
}}
|
||||
>
|
||||
After ALwrity
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
{solutions.map((solution, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
variants={itemVariants}
|
||||
whileHover={{ scale: 1.02 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
p: 3,
|
||||
borderRadius: 3,
|
||||
background: `linear-gradient(135deg, ${alpha(theme.palette.success.main, 0.1)} 0%, ${alpha(theme.palette.success.dark, 0.05)} 100%)`,
|
||||
border: `1px solid ${alpha(theme.palette.success.main, 0.2)}`,
|
||||
backdropFilter: 'blur(10px)',
|
||||
transition: 'all 0.3s ease',
|
||||
'&:hover': {
|
||||
background: `linear-gradient(135deg, ${alpha(theme.palette.success.main, 0.15)} 0%, ${alpha(theme.palette.success.dark, 0.08)} 100%)`,
|
||||
border: `1px solid ${alpha(theme.palette.success.main, 0.3)}`,
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" spacing={2} alignItems="flex-start">
|
||||
<Box
|
||||
sx={{
|
||||
p: 1.5,
|
||||
borderRadius: 2,
|
||||
background: `linear-gradient(135deg, ${theme.palette.success.main} 0%, ${theme.palette.success.dark} 100%)`,
|
||||
color: 'white',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
minWidth: 48,
|
||||
height: 48,
|
||||
}}
|
||||
>
|
||||
{solution.icon}
|
||||
</Box>
|
||||
<Stack spacing={1} sx={{ flex: 1 }}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
fontWeight={600}
|
||||
sx={{
|
||||
color: 'white',
|
||||
textShadow: '0 1px 2px rgba(0, 0, 0, 0.7)'
|
||||
}}
|
||||
>
|
||||
{solution.title}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body1"
|
||||
sx={{
|
||||
color: 'rgba(255, 255, 255, 0.8)',
|
||||
textShadow: '0 1px 2px rgba(0, 0, 0, 0.5)',
|
||||
lineHeight: 1.5
|
||||
}}
|
||||
>
|
||||
{solution.description}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Box>
|
||||
</motion.div>
|
||||
))}
|
||||
|
||||
{/* CTA Button */}
|
||||
<motion.div variants={itemVariants}>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="large"
|
||||
endIcon={<ArrowForward />}
|
||||
sx={{
|
||||
mt: 3,
|
||||
py: 2,
|
||||
px: 4,
|
||||
fontSize: '1.1rem',
|
||||
fontWeight: 700,
|
||||
borderRadius: 3,
|
||||
background: `linear-gradient(135deg, ${theme.palette.primary.main} 0%, ${theme.palette.secondary.main} 100%)`,
|
||||
boxShadow: `0 8px 32px ${alpha(theme.palette.primary.main, 0.4)}`,
|
||||
'&:hover': {
|
||||
background: `linear-gradient(135deg, ${theme.palette.primary.dark} 0%, ${theme.palette.secondary.dark} 100%)`,
|
||||
transform: 'translateY(-2px)',
|
||||
boxShadow: `0 12px 40px ${alpha(theme.palette.primary.main, 0.5)}`,
|
||||
},
|
||||
transition: 'all 0.3s ease',
|
||||
}}
|
||||
>
|
||||
End the Struggle Today
|
||||
</Button>
|
||||
</motion.div>
|
||||
</Stack>
|
||||
</motion.div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</motion.div>
|
||||
</Container>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default SolopreneurDilemma;
|
||||
Reference in New Issue
Block a user