Initial commit from v0

This commit is contained in:
v0
2026-03-20 00:11:55 +00:00
commit a0a04d3f87
87 changed files with 8419 additions and 0 deletions
+142
View File
@@ -0,0 +1,142 @@
"use client"
import { useRef, useState } from "react"
import { Globe, Cloud, Wrench, ArrowUpRight } from "lucide-react"
const services = [
{
icon: Globe,
title: "Web Development",
description: "Expert website design and maintenance for WordPress, Squarespace, Wix, Shopify, eCommerce, custom frontend code and more.",
features: ["WordPress", "Squarespace", "Shopify", "Custom Code", "eCommerce", "Maintenance"],
number: "01"
},
{
icon: Cloud,
title: "Cloud Hosting",
description: "Fast, easy hosting for WordPress, game servers and more, proudly hosted here in New Zealand by Cloudrite.",
features: ["NZ Hosted", "WordPress Hosting", "Game Servers", "Fast & Secure", "24/7 Uptime", "Easy Setup"],
number: "02"
},
{
icon: Wrench,
title: "I.T Support & Repairs",
description: "Our tech experts can help you with all of your I.T problems, from emails and cloud to printers and full computer repairs.",
features: ["Email Setup", "Cloud Solutions", "Printer Support", "Computer Repairs", "Network Setup", "Remote Support"],
number: "03"
}
]
function ServiceCard({ service, index }: { service: typeof services[0]; index: number }) {
const [isHovered, setIsHovered] = useState(false)
const cardRef = useRef<HTMLDivElement>(null)
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 })
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
if (cardRef.current) {
const rect = cardRef.current.getBoundingClientRect()
setMousePosition({
x: e.clientX - rect.left,
y: e.clientY - rect.top,
})
}
}
const Icon = service.icon
return (
<div
ref={cardRef}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
onMouseMove={handleMouseMove}
className="group relative bg-card border border-border rounded-2xl p-8 lg:p-10 transition-all duration-500 hover:border-primary/50 overflow-hidden"
style={{
animationDelay: `${index * 150}ms`,
}}
>
{/* Hover glow effect */}
<div
className="absolute w-64 h-64 rounded-full bg-primary/20 blur-[100px] transition-opacity duration-500 pointer-events-none"
style={{
left: mousePosition.x - 128,
top: mousePosition.y - 128,
opacity: isHovered ? 1 : 0,
}}
/>
{/* Number */}
<span className="absolute top-6 right-6 text-6xl font-bold text-border/50 transition-colors duration-300 group-hover:text-primary/20">
{service.number}
</span>
{/* Icon */}
<div className="relative z-10 mb-6">
<div className="w-14 h-14 rounded-xl bg-primary/10 flex items-center justify-center transition-all duration-300 group-hover:bg-primary/20 group-hover:scale-110">
<Icon className="w-7 h-7 text-primary" />
</div>
</div>
{/* Content */}
<div className="relative z-10">
<h3 className="text-2xl font-bold mb-4 flex items-center gap-3">
{service.title}
<ArrowUpRight className="w-5 h-5 opacity-0 -translate-x-2 transition-all duration-300 group-hover:opacity-100 group-hover:translate-x-0 text-primary" />
</h3>
<p className="text-muted-foreground mb-6 leading-relaxed">
{service.description}
</p>
{/* Features */}
<div className="flex flex-wrap gap-2">
{service.features.map((feature, i) => (
<span
key={feature}
className="px-3 py-1 text-xs font-medium bg-secondary text-secondary-foreground rounded-full transition-all duration-300 hover:bg-primary hover:text-primary-foreground cursor-default"
style={{
transitionDelay: `${i * 30}ms`,
}}
>
{feature}
</span>
))}
</div>
</div>
{/* Bottom border animation */}
<div className="absolute bottom-0 left-0 right-0 h-1 bg-primary scale-x-0 group-hover:scale-x-100 transition-transform duration-500 origin-left" />
</div>
)
}
export function Services() {
return (
<section id="services" className="relative py-32 overflow-hidden">
{/* Background */}
<div className="absolute inset-0 bg-gradient-to-b from-background via-card/50 to-background" />
<div className="relative z-10 mx-auto max-w-7xl px-6 lg:px-8">
{/* Section Header */}
<div className="text-center mb-20">
<div className="inline-flex items-center gap-2 px-4 py-2 mb-6 border border-border rounded-full bg-card/50">
<span className="text-sm text-muted-foreground">What We Do</span>
</div>
<h2 className="text-4xl md:text-5xl lg:text-6xl font-bold tracking-tight mb-6">
<span className="text-balance">Your Complete I.T Partner</span>
</h2>
<p className="max-w-2xl mx-auto text-lg text-muted-foreground">
We handle everything tech so you can focus on running your business.
From building your online presence to keeping your systems running smoothly.
</p>
</div>
{/* Services Grid */}
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{services.map((service, index) => (
<ServiceCard key={service.title} service={service} index={index} />
))}
</div>
</div>
</section>
)
}