This commit is contained in:
Timo Knuth 2026-01-09 11:29:02 +01:00
parent 91b819e9c1
commit 1a93c0f5ed
23 changed files with 588 additions and 451 deletions

View File

@ -213,10 +213,21 @@
<!-- Performance Optimization --> <!-- Performance Optimization -->
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="dns-prefetch" href="https://fonts.gstatic.com" /> <link rel="dns-prefetch" href="https://fonts.gstatic.com" />
<!-- Non-blocking font loading with font-display: swap -->
<link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@600;700;800&display=swap" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@600;700;800&display=swap" media="print" onload="this.media='all'" />
<noscript><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@600;700;800&display=swap" /></noscript>
<!-- Critical asset preloads -->
<link rel="preload" href="/logo_bayarea.svg" as="image" /> <link rel="preload" href="/logo_bayarea.svg" as="image" />
<link rel="preload" href="/serverroom.webp" as="image" type="image/webp" /> <link rel="preload" href="/serverroom.webp" as="image" type="image/webp" />
<!-- Canonical URL -->
<link rel="canonical" href="https://bayarea-cc.com/" />
<!-- Favicon --> <!-- Favicon -->
<link rel="icon" type="image/svg+xml" href="/logo_bayarea.svg" /> <link rel="icon" type="image/svg+xml" href="/logo_bayarea.svg" />
<link rel="apple-touch-icon" sizes="180x180" href="/logo_bayarea.svg" /> <link rel="apple-touch-icon" sizes="180x180" href="/logo_bayarea.svg" />

View File

@ -20,7 +20,7 @@ const Footer = () => {
]; ];
return ( return (
<footer className="bg-background-deep border-t border-border"> <footer role="contentinfo" className="bg-background-deep border-t border-border">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-12"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-12">
{/* Company info */} {/* Company info */}

View File

@ -37,9 +37,9 @@ const Navigation = () => {
<motion.nav <motion.nav
className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${isScrolled className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${isScrolled
? 'bg-white/5 backdrop-blur-2xl border-b border-white/20 shadow-2xl shadow-black/20' ? 'bg-background-deep/80 backdrop-blur-md border-b border-neon/30 shadow-[0_0_20px_rgba(0,0,0,0.5)]'
: 'bg-transparent' : 'bg-transparent border-b border-transparent'
}`} }`}
initial="hidden" initial="hidden"
animate="visible" animate="visible"
variants={navVariants} variants={navVariants}
@ -48,153 +48,153 @@ const Navigation = () => {
> >
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex items-center justify-between h-14 md:h-16"> <div className="flex items-center justify-between h-14 md:h-16">
{/* Logo with animation */} {/* Logo with animation */}
<Link to="/" className="flex items-center space-x-3"> <Link to="/" className="flex items-center space-x-3">
<motion.div
className="w-12 h-12 flex items-center justify-center overflow-visible"
whileHover={{ rotate: 360 }}
transition={{ duration: 0.6, ease: "easeInOut" }}
>
<img
src="/logo_bayarea.svg"
alt="Bay Area Affiliates Logo"
className="w-10 h-10 opacity-90"
/>
</motion.div>
<span className="font-heading font-bold text-lg text-white">
Bay Area Affiliates
</span>
</Link>
{/* Desktop Navigation with animations */}
<div className="hidden md:flex items-center space-x-8">
{navItems.map((item, index) => (
<motion.div <motion.div
key={item.name} className="w-12 h-12 flex items-center justify-center overflow-visible"
initial={{ opacity: 0, y: -20 }} whileHover={{ rotate: 360 }}
animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.6, ease: "easeInOut" }}
transition={{ delay: index * 0.1, duration: 0.5 }}
> >
<Link <img
to={item.path} src="/logo_bayarea.svg"
className={`font-medium transition-all duration-200 relative group px-2 py-1 ${isActive(item.path) alt="Bay Area Affiliates Logo"
? 'text-neon' className="w-10 h-10 opacity-90"
: 'text-white hover:text-neon' />
}`}
>
{item.name}
{/* Animated underline */}
<motion.span
className="absolute -bottom-1 left-0 h-0.5 bg-neon rounded-full"
initial={{ width: isActive(item.path) ? '100%' : 0 }}
whileHover={{ width: '100%', boxShadow: '0 0 8px rgba(51, 102, 255, 0.6)' }}
transition={{ duration: 0.3, ease: "easeOut" }}
/>
{/* Glow effect on hover */}
<motion.span
className="absolute inset-0 bg-neon/5 rounded-lg -z-10"
initial={{ opacity: 0, scale: 0.8 }}
whileHover={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.2 }}
/>
</Link>
</motion.div> </motion.div>
))} <span className="font-heading font-bold text-lg text-white">
<motion.div Bay Area Affiliates
initial={{ opacity: 0, scale: 0.8 }} </span>
animate={{ opacity: 1, scale: 1 }} </Link>
transition={{ delay: 0.5, duration: 0.5 }}
whileHover={buttonHover}
whileTap={buttonTap}
>
<Link
to="/contact"
className="btn-neon ml-4"
>
Get Started
</Link>
</motion.div>
</div>
{/* Mobile menu button with animation */} {/* Desktop Navigation with animations */}
<motion.button <div className="hidden md:flex items-center space-x-8">
onClick={() => setIsOpen(!isOpen)} {navItems.map((item, index) => (
className="md:hidden text-white hover:text-neon transition-colors"
aria-label="Toggle navigation menu"
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
>
<AnimatePresence mode="wait">
{isOpen ? (
<motion.div <motion.div
key="close" key={item.name}
initial={{ rotate: -90, opacity: 0 }} initial={{ opacity: 0, y: -20 }}
animate={{ rotate: 0, opacity: 1 }} animate={{ opacity: 1, y: 0 }}
exit={{ rotate: 90, opacity: 0 }} transition={{ delay: index * 0.1, duration: 0.5 }}
transition={{ duration: 0.2 }}
> >
<X size={24} />
</motion.div>
) : (
<motion.div
key="menu"
initial={{ rotate: 90, opacity: 0 }}
animate={{ rotate: 0, opacity: 1 }}
exit={{ rotate: -90, opacity: 0 }}
transition={{ duration: 0.2 }}
>
<Menu size={24} />
</motion.div>
)}
</AnimatePresence>
</motion.button>
</div>
{/* Mobile Navigation with smooth animations */}
<AnimatePresence>
{isOpen && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.3, ease: "easeInOut" }}
className="md:hidden bg-white/5 backdrop-blur-2xl border-t border-white/20 overflow-hidden"
>
<motion.div
className="px-2 pt-2 pb-3 space-y-1"
variants={staggerContainer}
initial="hidden"
animate="visible"
>
{navItems.map((item) => (
<motion.div key={item.name} variants={staggerItem}>
<Link
to={item.path}
onClick={() => setIsOpen(false)}
className={`block px-3 py-2 rounded-md text-base font-medium transition-colors ${isActive(item.path)
? 'text-neon bg-neon/10'
: 'text-white hover:text-neon hover:bg-neon/5'
}`}
>
{item.name}
</Link>
</motion.div>
))}
<motion.div variants={staggerItem}>
<Link <Link
to="/contact" to={item.path}
onClick={() => setIsOpen(false)} className={`font-medium transition-all duration-200 relative group px-2 py-1 ${isActive(item.path)
className="block w-full text-center btn-neon mt-4" ? 'text-neon'
: 'text-white hover:text-neon'
}`}
> >
Get Started {item.name}
{/* Animated underline */}
<motion.span
className="absolute -bottom-1 left-0 h-0.5 bg-neon rounded-full"
initial={{ width: isActive(item.path) ? '100%' : 0 }}
whileHover={{ width: '100%', boxShadow: '0 0 8px rgba(51, 102, 255, 0.6)' }}
transition={{ duration: 0.3, ease: "easeOut" }}
/>
{/* Glow effect on hover */}
<motion.span
className="absolute inset-0 bg-neon/5 rounded-lg -z-10"
initial={{ opacity: 0, scale: 0.8 }}
whileHover={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.2 }}
/>
</Link> </Link>
</motion.div> </motion.div>
))}
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ delay: 0.5, duration: 0.5 }}
whileHover={buttonHover}
whileTap={buttonTap}
>
<Link
to="/contact"
className="btn-neon ml-4"
>
Get Started
</Link>
</motion.div> </motion.div>
</motion.div> </div>
)}
</AnimatePresence> {/* Mobile menu button with animation */}
</div> <motion.button
</motion.nav> onClick={() => setIsOpen(!isOpen)}
className="md:hidden text-white hover:text-neon transition-colors"
aria-label="Toggle navigation menu"
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
>
<AnimatePresence mode="wait">
{isOpen ? (
<motion.div
key="close"
initial={{ rotate: -90, opacity: 0 }}
animate={{ rotate: 0, opacity: 1 }}
exit={{ rotate: 90, opacity: 0 }}
transition={{ duration: 0.2 }}
>
<X size={24} />
</motion.div>
) : (
<motion.div
key="menu"
initial={{ rotate: 90, opacity: 0 }}
animate={{ rotate: 0, opacity: 1 }}
exit={{ rotate: -90, opacity: 0 }}
transition={{ duration: 0.2 }}
>
<Menu size={24} />
</motion.div>
)}
</AnimatePresence>
</motion.button>
</div>
{/* Mobile Navigation with smooth animations */}
<AnimatePresence>
{isOpen && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.3, ease: "easeInOut" }}
className="md:hidden bg-white/5 backdrop-blur-2xl border-t border-white/20 overflow-hidden"
>
<motion.div
className="px-2 pt-2 pb-3 space-y-1"
variants={staggerContainer}
initial="hidden"
animate="visible"
>
{navItems.map((item) => (
<motion.div key={item.name} variants={staggerItem}>
<Link
to={item.path}
onClick={() => setIsOpen(false)}
className={`block px-3 py-2 rounded-md text-base font-medium transition-colors ${isActive(item.path)
? 'text-neon bg-neon/10'
: 'text-white hover:text-neon hover:bg-neon/5'
}`}
>
{item.name}
</Link>
</motion.div>
))}
<motion.div variants={staggerItem}>
<Link
to="/contact"
onClick={() => setIsOpen(false)}
className="block w-full text-center btn-neon mt-4"
>
Get Started
</Link>
</motion.div>
</motion.div>
</motion.div>
)}
</AnimatePresence>
</div>
</motion.nav>
</> </>
); );
}; };

View File

@ -1,29 +1,51 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { motion, useInView } from 'framer-motion'; import { motion, useInView } from 'framer-motion';
import { useRef } from 'react'; import React, { useRef } from 'react';
import { scrollRevealVariants } from '@/utils/animations';
type ScrollRevealProps = { interface ScrollRevealProps {
children: ReactNode; children: React.ReactNode;
width?: 'fit-content' | '100%';
delay?: number; delay?: number;
duration?: number;
direction?: 'up' | 'down' | 'left' | 'right';
className?: string; className?: string;
}; }
const ScrollReveal = ({ children, delay = 0, className = '' }: ScrollRevealProps) => { const ScrollReveal: React.FC<ScrollRevealProps> = ({
children,
width = 'fit-content',
delay = 0,
duration = 0.5,
direction = 'up',
className = ""
}) => {
const ref = useRef(null); const ref = useRef(null);
const isInView = useInView(ref, { once: true, margin: "-100px" }); const isInView = useInView(ref, { once: true, margin: "-50px 0px" }); // Trigger slightly before element is fully in view
const getDirectionOffset = () => {
switch (direction) {
case 'up': return { y: 75 };
case 'down': return { y: -75 };
case 'left': return { x: 75 };
case 'right': return { x: -75 };
default: return { y: 75 };
}
};
return ( return (
<motion.div <div ref={ref} style={{ position: 'relative', width, overflow: 'hidden' }} className={className}>
ref={ref} <motion.div
initial="hidden" variants={{
animate={isInView ? "visible" : "hidden"} hidden: { opacity: 0, ...getDirectionOffset() },
variants={scrollRevealVariants} visible: { opacity: 1, x: 0, y: 0 },
transition={{ delay: delay / 1000 }} }}
className={className} initial="hidden"
> animate={isInView ? "visible" : "hidden"}
{children} transition={{ duration, delay, ease: "easeOut" }}
</motion.div> >
{children}
</motion.div>
</div>
); );
}; };

View File

@ -30,7 +30,7 @@ const HeroSection = () => {
animate={{ scale: 1.1, opacity: 1 }} animate={{ scale: 1.1, opacity: 1 }}
transition={{ duration: 1.2, ease: easing.elegant }} transition={{ duration: 1.2, ease: easing.elegant }}
loading="eager" loading="eager"
fetchpriority="high" fetchPriority="high"
/> />
</picture> </picture>

View File

@ -82,23 +82,13 @@ const ProofSection = () => {
variants={staggerItem} variants={staggerItem}
className="text-center" className="text-center"
> >
<motion.div <div className="font-heading font-bold text-4xl lg:text-5xl text-neon mb-2">
className="font-heading font-bold text-4xl lg:text-5xl text-neon mb-2"
initial={{ scale: 0, rotate: -180 }}
animate={isStatsInView ? { scale: 1, rotate: 0 } : { scale: 0, rotate: -180 }}
transition={{
delay: index * 0.1,
duration: 0.6,
type: "spring",
stiffness: 150
}}
>
<CountUpNumber <CountUpNumber
value={stat.value} value={stat.value}
duration={2000 + index * 200} duration={2000 + index * 200}
className="inline-block" className="inline-block"
/> />
</motion.div> </div>
<motion.div <motion.div
className="text-foreground-muted text-sm lg:text-base" className="text-foreground-muted text-sm lg:text-base"
initial={{ opacity: 0, y: 10 }} initial={{ opacity: 0, y: 10 }}

View File

@ -85,71 +85,77 @@ const ServicesOverview = () => {
const Icon = service.icon; const Icon = service.icon;
return ( return (
<motion.div key={service.title} variants={staggerItem}> <motion.div key={service.title} variants={staggerItem} className="h-full">
<motion.div <motion.div
className="card-dark p-8 h-full" className="card-dark p-8 h-full relative overflow-hidden group border border-white/5 hover:border-neon/50 transition-colors duration-500"
whileHover={{ whileHover={{
y: -8, y: -10,
boxShadow: "0 0 30px rgba(51, 102, 255, 0.4)" scale: 1.02,
boxShadow: "0 20px 40px -10px rgba(51, 102, 255, 0.3)"
}} }}
transition={{ duration: 0.3 }} transition={{ duration: 0.4, ease: "easeOut" }}
> >
{/* Subtle gradient background nice touch */}
<div className="absolute inset-0 bg-gradient-to-br from-neon/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
{/* Icon */} {/* Icon */}
<motion.div <motion.div
className="w-12 h-12 bg-neon/20 rounded-xl flex items-center justify-center mb-6" className="w-12 h-12 bg-neon/10 rounded-xl flex items-center justify-center mb-6 relative z-10 group-hover:bg-neon/20 transition-colors duration-300"
whileHover={{ rotate: 360, scale: 1.1 }} whileHover={{ rotate: 360, scale: 1.1 }}
transition={{ duration: 0.6 }} transition={{ duration: 0.6 }}
> >
<Icon className="w-6 h-6 text-neon" /> <Icon className="w-6 h-6 text-neon drop-shadow-[0_0_8px_rgba(51,102,255,0.6)]" />
</motion.div> </motion.div>
{/* Content */} {/* Content */}
<h3 className="font-heading font-bold text-xl text-foreground mb-4"> <div className="relative z-10">
{service.title} <h3 className="font-heading font-bold text-xl text-foreground mb-4 group-hover:text-neon transition-colors duration-300">
</h3> {service.title}
</h3>
<p className="text-foreground-muted mb-6 leading-relaxed"> <p className="text-foreground-muted mb-6 leading-relaxed">
{service.description} {service.description}
</p> </p>
{/* Features */} {/* Features */}
<ul className="space-y-2 mb-6"> <ul className="space-y-2 mb-6">
{service.features.map((feature) => ( {service.features.map((feature) => (
<li key={feature} className="flex items-center text-sm text-foreground-muted"> <li key={feature} className="flex items-center text-sm text-foreground-muted">
<motion.div <motion.div
className="w-1.5 h-1.5 bg-neon rounded-full mr-3" className="w-1.5 h-1.5 bg-neon rounded-full mr-3 shadow-[0_0_5px_rgba(51,102,255,0.8)]"
animate={{ animate={{
scale: [1, 1.3, 1], scale: [1, 1.5, 1],
opacity: [0.7, 1, 0.7] opacity: [0.7, 1, 0.7]
}} }}
transition={{ transition={{
duration: 2, duration: 2,
repeat: Infinity, repeat: Infinity,
delay: index * 0.2 delay: index * 0.2
}} }}
/> />
{feature} {feature}
</li> </li>
))} ))}
</ul> </ul>
{/* CTA */} {/* CTA */}
<Link <Link
to="/services" to="/services"
className="inline-flex items-center text-neon font-medium hover:text-neon/80 transition-colors group" className="inline-flex items-center text-neon font-medium group-hover:translate-x-2 transition-transform duration-300"
>
Learn more
<motion.svg
className="w-4 h-4 ml-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
animate={{ x: [0, 3, 0] }}
transition={{ duration: 1.5, repeat: Infinity, ease: "easeInOut" }}
> >
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 5l7 7-7 7" /> Learn more
</motion.svg> <motion.svg
</Link> className="w-4 h-4 ml-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
animate={{ x: [0, 3, 0] }}
transition={{ duration: 1.5, repeat: Infinity, ease: "easeInOut" }}
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 5l7 7-7 7" />
</motion.svg>
</Link>
</div>
</motion.div> </motion.div>
</motion.div> </motion.div>
); );

View File

@ -0,0 +1,54 @@
import { motion } from 'framer-motion';
const TrustedBy = () => {
// Placeholder logos - in a real app these would be SVGs
const companies = [
{ name: "TechCorp", color: "bg-blue-400" },
{ name: "SecureNet", color: "bg-indigo-400" },
{ name: "CloudSystems", color: "bg-cyan-400" },
{ name: "FutureData", color: "bg-sky-400" },
{ name: "CyberGuard", color: "bg-teal-400" },
{ name: "NetWorks", color: "bg-emerald-400" },
];
// duplicate for seamless loop
const logos = [...companies, ...companies, ...companies];
return (
<section className="py-10 border-b border-white/5 bg-background-deep relative overflow-hidden">
<p className="text-center text-sm font-medium text-foreground-muted mb-8 tracking-wider uppercase relative z-10 px-4">
Trusted by innovative businesses in Corpus Christi
</p>
<div className="relative flex overflow-hidden mask-linear-fade">
{/* Gradient Masks for smooth fade out at edges */}
<div className="absolute left-0 top-0 bottom-0 w-24 bg-gradient-to-r from-background-deep to-transparent z-10"></div>
<div className="absolute right-0 top-0 bottom-0 w-24 bg-gradient-to-l from-background-deep to-transparent z-10"></div>
<motion.div
className="flex space-x-16 items-center"
animate={{ x: ["0%", "-50%"] }}
transition={{
duration: 30,
repeat: Infinity,
ease: "linear",
repeatType: "loop"
}}
>
{logos.map((company, index) => (
<div key={index} className="flex items-center space-x-2 opacity-50 grayscale hover:grayscale-0 hover:opacity-100 transition-all duration-300">
{/* Fake Logo Icon */}
<div className={`w-8 h-8 rounded-lg ${company.color}/20 flex items-center justify-center`}>
<div className={`w-4 h-4 rounded-full ${company.color}`}></div>
</div>
{/* Fake Logo Text */}
<span className="text-xl font-bold text-white tracking-tight">{company.name}</span>
</div>
))}
</motion.div>
</div>
</section>
);
};
export default TrustedBy;

View File

@ -1,5 +1,3 @@
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@600;700;800&display=swap');
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;

View File

@ -4,10 +4,19 @@ import { Shield, Users, Zap, MapPin } from 'lucide-react';
import ScrollReveal from '@/components/ScrollReveal'; import ScrollReveal from '@/components/ScrollReveal';
import CountUpNumber from '@/components/CountUpNumber'; import CountUpNumber from '@/components/CountUpNumber';
import { useEffect, useRef } from 'react'; import { useEffect, useRef } from 'react';
import { useSEO } from '@/hooks/useSEO';
const About = () => { const About = () => {
const imageRef = useRef<HTMLImageElement>(null); const imageRef = useRef<HTMLImageElement>(null);
useSEO({
title: 'About Bay Area Affiliates | IT Experts Corpus Christi Since 2010',
description: 'Local IT expertise for the Coastal Bend since 2010. 150+ businesses served, 99.9% uptime. Security-first approach with clear communication. Meet the team.',
keywords: 'about Bay Area Affiliates, IT company Corpus Christi, managed services provider Texas, local IT support Coastal Bend',
canonical: 'https://bayarea-cc.com/about',
ogImage: 'https://bayarea-cc.com/og-image.png',
});
useEffect(() => { useEffect(() => {
const handleScroll = () => { const handleScroll = () => {
if (imageRef.current) { if (imageRef.current) {
@ -66,7 +75,7 @@ const About = () => {
<div className="min-h-screen"> <div className="min-h-screen">
<Navigation /> <Navigation />
<main> <main role="main">
{/* Hero section with image background */} {/* Hero section with image background */}
<section className="relative h-screen flex items-center justify-center overflow-hidden"> <section className="relative h-screen flex items-center justify-center overflow-hidden">
{/* Background image with parallax */} {/* Background image with parallax */}
@ -78,7 +87,7 @@ const About = () => {
className="w-full h-[110%] object-cover will-change-transform" className="w-full h-[110%] object-cover will-change-transform"
style={{ transform: 'translateY(0px) scale(1.1)' }} style={{ transform: 'translateY(0px) scale(1.1)' }}
loading="eager" loading="eager"
fetchpriority="high" fetchPriority="high"
/> />
</div> </div>

View File

@ -81,7 +81,7 @@ const Blog = () => {
<div className="min-h-screen"> <div className="min-h-screen">
<Navigation /> <Navigation />
<main> <main role="main">
{/* Hero section with image background */} {/* Hero section with image background */}
<section className="relative h-screen flex items-center justify-center overflow-hidden"> <section className="relative h-screen flex items-center justify-center overflow-hidden">
{/* Background image with parallax */} {/* Background image with parallax */}
@ -93,7 +93,7 @@ const Blog = () => {
className="w-full h-[110%] object-cover will-change-transform" className="w-full h-[110%] object-cover will-change-transform"
style={{ transform: 'translateY(0px) scale(1.1)' }} style={{ transform: 'translateY(0px) scale(1.1)' }}
loading="eager" loading="eager"
fetchpriority="high" fetchPriority="high"
/> />
</div> </div>
@ -211,9 +211,8 @@ const Blog = () => {
{/* Scroll to Top Button */} {/* Scroll to Top Button */}
<button <button
onClick={scrollToTop} onClick={scrollToTop}
className={`fixed bottom-8 right-8 z-50 p-4 bg-neon text-neon-foreground rounded-full shadow-lg shadow-neon/50 transition-all duration-300 hover:scale-110 hover:shadow-neon ${ className={`fixed bottom-8 right-8 z-50 p-4 bg-neon text-neon-foreground rounded-full shadow-lg shadow-neon/50 transition-all duration-300 hover:scale-110 hover:shadow-neon ${showScrollTop ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-16 pointer-events-none'
showScrollTop ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-16 pointer-events-none' }`}
}`}
aria-label="Scroll to top" aria-label="Scroll to top"
> >
<ArrowUp className="w-6 h-6" /> <ArrowUp className="w-6 h-6" />

View File

@ -112,7 +112,7 @@ const BlogPost = () => {
<div className="min-h-screen bg-background-deep"> <div className="min-h-screen bg-background-deep">
<Navigation /> <Navigation />
<main> <main role="main">
{/* Hero section with featured image */} {/* Hero section with featured image */}
<section className="relative h-[60vh] min-h-[400px] flex items-center justify-center overflow-hidden"> <section className="relative h-[60vh] min-h-[400px] flex items-center justify-center overflow-hidden">
{/* Background image */} {/* Background image */}
@ -122,7 +122,7 @@ const BlogPost = () => {
alt={post.title} alt={post.title}
className="w-full h-full object-cover" className="w-full h-full object-cover"
loading="eager" loading="eager"
fetchpriority="high" fetchPriority="high"
/> />
<div className="absolute inset-0 bg-gradient-to-t from-background-deep via-background-deep/60 to-transparent"></div> <div className="absolute inset-0 bg-gradient-to-t from-background-deep via-background-deep/60 to-transparent"></div>
</div> </div>

View File

@ -5,8 +5,17 @@ import { Mail, Phone, MapPin, Clock, DollarSign, Headphones } from 'lucide-react
import ScrollReveal from '@/components/ScrollReveal'; import ScrollReveal from '@/components/ScrollReveal';
import { useToast } from '@/hooks/use-toast'; import { useToast } from '@/hooks/use-toast';
import { useEffect, useRef } from 'react'; import { useEffect, useRef } from 'react';
import { useSEO } from '@/hooks/useSEO';
const Contact = () => { const Contact = () => {
useSEO({
title: 'Contact Bay Area Affiliates | Free IT Consultation Corpus Christi',
description: 'Get in touch for a free IT consultation. 24-hour response, free assessment, no obligation. Serving Corpus Christi, Portland, Rockport & the Coastal Bend.',
keywords: 'contact IT support Corpus Christi, free IT consultation, Bay Area Affiliates phone, IT services quote Texas',
canonical: 'https://bayarea-cc.com/contact',
ogImage: 'https://bayarea-cc.com/og-image.png',
});
const { toast } = useToast(); const { toast } = useToast();
const imageRef = useRef<HTMLImageElement>(null); const imageRef = useRef<HTMLImageElement>(null);
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
@ -81,7 +90,7 @@ const Contact = () => {
<div className="min-h-screen"> <div className="min-h-screen">
<Navigation /> <Navigation />
<main> <main role="main">
{/* Hero section with image background */} {/* Hero section with image background */}
<section className="relative h-screen flex items-center justify-center overflow-hidden"> <section className="relative h-screen flex items-center justify-center overflow-hidden">
{/* Background image with parallax */} {/* Background image with parallax */}
@ -158,7 +167,7 @@ const Contact = () => {
required required
value={formData.name} value={formData.name}
onChange={handleChange} onChange={handleChange}
className="w-full px-4 py-3 bg-input border border-input-border rounded-lg focus:outline-none focus:ring-2 focus:ring-neon focus:border-transparent text-foreground" className="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-lg focus:outline-none focus:ring-2 focus:ring-neon focus:border-neon focus:bg-white/10 focus:shadow-[0_0_15px_rgba(51,102,255,0.3)] transition-all duration-300 text-foreground placeholder-foreground-muted/50"
placeholder="Your full name" placeholder="Your full name"
/> />
</div> </div>
@ -174,7 +183,7 @@ const Contact = () => {
required required
value={formData.email} value={formData.email}
onChange={handleChange} onChange={handleChange}
className="w-full px-4 py-3 bg-input border border-input-border rounded-lg focus:outline-none focus:ring-2 focus:ring-neon focus:border-transparent text-foreground" className="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-lg focus:outline-none focus:ring-2 focus:ring-neon focus:border-neon focus:bg-white/10 focus:shadow-[0_0_15px_rgba(51,102,255,0.3)] transition-all duration-300 text-foreground placeholder-foreground-muted/50"
placeholder="your@email.com" placeholder="your@email.com"
/> />
</div> </div>
@ -191,7 +200,7 @@ const Contact = () => {
name="company" name="company"
value={formData.company} value={formData.company}
onChange={handleChange} onChange={handleChange}
className="w-full px-4 py-3 bg-input border border-input-border rounded-lg focus:outline-none focus:ring-2 focus:ring-neon focus:border-transparent text-foreground" className="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-lg focus:outline-none focus:ring-2 focus:ring-neon focus:border-neon focus:bg-white/10 focus:shadow-[0_0_15px_rgba(51,102,255,0.3)] transition-all duration-300 text-foreground placeholder-foreground-muted/50"
placeholder="Your company name" placeholder="Your company name"
/> />
</div> </div>
@ -206,7 +215,7 @@ const Contact = () => {
name="phone" name="phone"
value={formData.phone} value={formData.phone}
onChange={handleChange} onChange={handleChange}
className="w-full px-4 py-3 bg-input border border-input-border rounded-lg focus:outline-none focus:ring-2 focus:ring-neon focus:border-transparent text-foreground" className="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-lg focus:outline-none focus:ring-2 focus:ring-neon focus:border-neon focus:bg-white/10 focus:shadow-[0_0_15px_rgba(51,102,255,0.3)] transition-all duration-300 text-foreground placeholder-foreground-muted/50"
placeholder="(361) 555-0123" placeholder="(361) 555-0123"
/> />
</div> </div>
@ -223,7 +232,7 @@ const Contact = () => {
rows={5} rows={5}
value={formData.message} value={formData.message}
onChange={handleChange} onChange={handleChange}
className="w-full px-4 py-3 bg-input border border-input-border rounded-lg focus:outline-none focus:ring-2 focus:ring-neon focus:border-transparent text-foreground resize-none" className="w-full px-4 py-3 bg-white/5 backdrop-blur-sm border border-white/10 rounded-lg focus:outline-none focus:ring-2 focus:ring-neon focus:border-neon focus:bg-white/10 focus:shadow-[0_0_15px_rgba(51,102,255,0.3)] transition-all duration-300 text-foreground placeholder-foreground-muted/50 resize-none"
placeholder="Tell us about your IT needs or challenges..." placeholder="Tell us about your IT needs or challenges..."
/> />
</div> </div>
@ -375,8 +384,8 @@ const Contact = () => {
{/* Service Area Map */} {/* Service Area Map */}
<section className="py-16 bg-background-deep"> <section className="py-16 bg-background-deep">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="w-full max-w-[95%] mx-auto px-4 sm:px-6 lg:px-8">
<ScrollReveal> <ScrollReveal width="100%">
<div className="text-center mb-8"> <div className="text-center mb-8">
<h2 className="font-heading font-bold text-3xl text-foreground mb-4"> <h2 className="font-heading font-bold text-3xl text-foreground mb-4">
Our Service Area Our Service Area

View File

@ -39,7 +39,7 @@ const DesktopHardware = () => {
return ( return (
<div className="min-h-screen"> <div className="min-h-screen">
<Navigation /> <Navigation />
<main> <main role="main">
{/* Hero Section */} {/* Hero Section */}
<section className="bg-gradient-to-br from-gray-900 via-gray-800 to-gray-600 text-white py-20"> <section className="bg-gradient-to-br from-gray-900 via-gray-800 to-gray-600 text-white py-20">
<div className="container mx-auto px-4"> <div className="container mx-auto px-4">

View File

@ -6,18 +6,48 @@ import ProcessTimeline from '@/components/home/ProcessTimeline';
import ServicesOverview from '@/components/home/ServicesOverview'; import ServicesOverview from '@/components/home/ServicesOverview';
import ProofSection from '@/components/home/ProofSection'; import ProofSection from '@/components/home/ProofSection';
import CTASection from '@/components/home/CTASection'; import CTASection from '@/components/home/CTASection';
import TrustedBy from '@/components/home/TrustedBy';
import ScrollReveal from '@/components/ScrollReveal';
import { useSEO } from '@/hooks/useSEO';
const Index = () => { const Index = () => {
useSEO({
title: 'IT Support Corpus Christi ⚡ 24/7 Managed Services | Bay Area Affiliates',
description: 'Stop IT headaches! 25+ years experience, 2-hour response time, 24/7 monitoring. Managed IT services in Corpus Christi & Coastal Bend. Free assessment. Call (361) 765-8400',
keywords: 'managed IT services corpus christi, IT support coastal bend, 24/7 IT monitoring, business computer solutions, Windows 11 migration, VPN setup, network security corpus christi',
canonical: 'https://bayarea-cc.com/',
ogImage: 'https://bayarea-cc.com/og-image.png',
});
return ( return (
<div className="min-h-screen"> <div className="min-h-screen">
<Navigation /> <Navigation />
<main id="main-content" role="main"> <main id="main-content" role="main">
<HeroSection /> <HeroSection />
<ValuePillars />
<ProcessTimeline /> <ScrollReveal delay={0.2} width="100%">
<ServicesOverview /> <TrustedBy />
<ProofSection /> </ScrollReveal>
<CTASection />
<ScrollReveal width="100%">
<ValuePillars />
</ScrollReveal>
<ScrollReveal width="100%">
<ProcessTimeline />
</ScrollReveal>
<ScrollReveal width="100%">
<ServicesOverview />
</ScrollReveal>
<ScrollReveal width="100%">
<ProofSection />
</ScrollReveal>
<ScrollReveal width="100%">
<CTASection />
</ScrollReveal>
</main> </main>
<Footer /> <Footer />
</div> </div>

View File

@ -39,7 +39,7 @@ const NetworkAttachedStorage = () => {
return ( return (
<div className="min-h-screen"> <div className="min-h-screen">
<Navigation /> <Navigation />
<main> <main role="main">
{/* Hero Section */} {/* Hero Section */}
<section className="bg-gradient-to-br from-blue-900 via-blue-800 to-blue-600 text-white py-20"> <section className="bg-gradient-to-br from-blue-900 via-blue-800 to-blue-600 text-white py-20">
<div className="container mx-auto px-4"> <div className="container mx-auto px-4">

View File

@ -39,7 +39,7 @@ const NetworkInfrastructure = () => {
return ( return (
<div className="min-h-screen"> <div className="min-h-screen">
<Navigation /> <Navigation />
<main> <main role="main">
{/* Hero Section */} {/* Hero Section */}
<section className="bg-gradient-to-br from-teal-900 via-teal-800 to-teal-600 text-white py-20"> <section className="bg-gradient-to-br from-teal-900 via-teal-800 to-teal-600 text-white py-20">
<div className="container mx-auto px-4"> <div className="container mx-auto px-4">

View File

@ -39,7 +39,7 @@ const PerformanceUpgrades = () => {
return ( return (
<div className="min-h-screen"> <div className="min-h-screen">
<Navigation /> <Navigation />
<main> <main role="main">
{/* Hero Section */} {/* Hero Section */}
<section className="bg-gradient-to-br from-purple-900 via-purple-800 to-purple-600 text-white py-20"> <section className="bg-gradient-to-br from-purple-900 via-purple-800 to-purple-600 text-white py-20">
<div className="container mx-auto px-4"> <div className="container mx-auto px-4">

View File

@ -39,7 +39,7 @@ const PrinterScannerInstallation = () => {
return ( return (
<div className="min-h-screen"> <div className="min-h-screen">
<Navigation /> <Navigation />
<main> <main role="main">
{/* Hero Section */} {/* Hero Section */}
<section className="bg-gradient-to-br from-indigo-900 via-indigo-800 to-indigo-600 text-white py-20"> <section className="bg-gradient-to-br from-indigo-900 via-indigo-800 to-indigo-600 text-white py-20">
<div className="container mx-auto px-4"> <div className="container mx-auto px-4">

View File

@ -3,11 +3,20 @@ import Footer from '@/components/Footer';
import { Monitor, Wifi, Cloud, Shield, Database, Settings, CheckCircle } from 'lucide-react'; import { Monitor, Wifi, Cloud, Shield, Database, Settings, CheckCircle } from 'lucide-react';
import ScrollReveal from '@/components/ScrollReveal'; import ScrollReveal from '@/components/ScrollReveal';
import { useLayoutEffect, useRef } from 'react'; import { useLayoutEffect, useRef } from 'react';
import { useSEO } from '@/hooks/useSEO';
const Services = () => { const Services = () => {
const pageRef = useRef<HTMLDivElement>(null); const pageRef = useRef<HTMLDivElement>(null);
const heroImageRef = useRef<HTMLImageElement>(null); const heroImageRef = useRef<HTMLImageElement>(null);
useSEO({
title: 'IT Services Corpus Christi | Managed IT, Network, Cloud | Bay Area Affiliates',
description: 'Complete IT solutions for Corpus Christi businesses. Hardware support, network infrastructure, cloud services, secure remote access, backup & Microsoft 365. Free consultation.',
keywords: 'IT services Corpus Christi, managed IT Coastal Bend, network infrastructure Texas, cloud services, VPN setup, Microsoft 365',
canonical: 'https://bayarea-cc.com/services',
ogImage: 'https://bayarea-cc.com/og-image.png',
});
useLayoutEffect(() => { useLayoutEffect(() => {
// Dynamically import GSAP only when needed to reduce initial bundle size // Dynamically import GSAP only when needed to reduce initial bundle size
let ctx: any; let ctx: any;
@ -163,7 +172,7 @@ const Services = () => {
<div ref={pageRef} className="min-h-screen"> <div ref={pageRef} className="min-h-screen">
<Navigation /> <Navigation />
<main> <main role="main">
{/* Hero section with image background */} {/* Hero section with image background */}
<section className="relative h-screen flex items-center justify-center overflow-hidden"> <section className="relative h-screen flex items-center justify-center overflow-hidden">
{/* Background image with parallax */} {/* Background image with parallax */}
@ -174,7 +183,7 @@ const Services = () => {
alt="Corpus Christi IT services data center with enterprise networking equipment and server infrastructure" alt="Corpus Christi IT services data center with enterprise networking equipment and server infrastructure"
className="w-full h-[110%] object-cover will-change-transform" className="w-full h-[110%] object-cover will-change-transform"
loading="eager" loading="eager"
fetchpriority="high" fetchPriority="high"
/> />
</div> </div>

View File

@ -39,7 +39,7 @@ const VpnSetup = () => {
return ( return (
<div className="min-h-screen"> <div className="min-h-screen">
<Navigation /> <Navigation />
<main> <main role="main">
{/* Hero Section */} {/* Hero Section */}
<section className="bg-gradient-to-br from-green-900 via-green-800 to-green-600 text-white py-20"> <section className="bg-gradient-to-br from-green-900 via-green-800 to-green-600 text-white py-20">
<div className="container mx-auto px-4"> <div className="container mx-auto px-4">

View File

@ -39,7 +39,7 @@ const WebServices = () => {
return ( return (
<div className="min-h-screen"> <div className="min-h-screen">
<Navigation /> <Navigation />
<main> <main role="main">
{/* Hero Section */} {/* Hero Section */}
<section className="bg-gradient-to-br from-emerald-900 via-emerald-800 to-emerald-600 text-white py-20"> <section className="bg-gradient-to-br from-emerald-900 via-emerald-800 to-emerald-600 text-white py-20">
<div className="container mx-auto px-4"> <div className="container mx-auto px-4">

View File

@ -39,7 +39,7 @@ const Windows11Transition = () => {
return ( return (
<div className="min-h-screen"> <div className="min-h-screen">
<Navigation /> <Navigation />
<main> <main role="main">
{/* Hero Section */} {/* Hero Section */}
<section className="bg-gradient-to-br from-blue-900 via-blue-800 to-blue-600 text-white py-20"> <section className="bg-gradient-to-br from-blue-900 via-blue-800 to-blue-600 text-white py-20">
<div className="container mx-auto px-4"> <div className="container mx-auto px-4">