259 lines
9.1 KiB
TypeScript
259 lines
9.1 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { motion, Variants } from "framer-motion";
|
|
import { Globe, Smartphone, Server, Gamepad2, Hammer } from "lucide-react";
|
|
import { useState } from "react";
|
|
import MonitorCard from "@/components/MonitorCard";
|
|
import PageLayout from "@/components/PageLayout";
|
|
import { CategoryCardProps } from "@/types/index";
|
|
|
|
const containerVariants: Variants = {
|
|
hidden: { opacity: 0 },
|
|
visible: {
|
|
opacity: 1,
|
|
transition: {
|
|
staggerChildren: 0.1,
|
|
delayChildren: 0.2,
|
|
},
|
|
},
|
|
};
|
|
|
|
const itemVariants: Variants = {
|
|
hidden: { opacity: 0, y: 20 },
|
|
visible: {
|
|
opacity: 1,
|
|
y: 0,
|
|
transition: { duration: 0.6, ease: "easeOut" },
|
|
},
|
|
};
|
|
|
|
export default function Home() {
|
|
const [isHoveringMonitors, setIsHoveringMonitors] = useState(false);
|
|
|
|
return (
|
|
<PageLayout maxWidth="7xl">
|
|
<motion.div
|
|
variants={containerVariants}
|
|
initial="hidden"
|
|
animate="visible"
|
|
className="flex flex-col gap-12"
|
|
>
|
|
{/* Header Section */}
|
|
<motion.header variants={itemVariants}>
|
|
<h1 className="text-4xl font-bold tracking-tight">George W.</h1>
|
|
<p className="text-neutral-400 mt-2">
|
|
Senior Full Stack Engineer & Tech Lead
|
|
</p>
|
|
<div className="flex gap-6 text-[10px] font-mono tracking-[0.2em] uppercase mt-4">
|
|
<a
|
|
href="https://git.georgew.dev"
|
|
className="text-neutral-500 hover:text-white transition-colors"
|
|
>
|
|
Git
|
|
</a>
|
|
<a
|
|
href="https://linkedin.com/in/georgew"
|
|
className="text-neutral-500 hover:text-white transition-colors"
|
|
>
|
|
LinkedIn
|
|
</a>
|
|
</div>
|
|
</motion.header>
|
|
|
|
{/* Main Bento Grid */}
|
|
<div className="grid grid-cols-1 md:grid-cols-6 gap-6">
|
|
{/* Top Row Left: The Architect */}
|
|
<motion.div
|
|
variants={itemVariants}
|
|
className="md:col-span-4 p-8 rounded-3xl bg-neutral-900/50 border border-neutral-800 flex flex-col md:flex-row gap-8 min-h-[300px] overflow-hidden relative"
|
|
>
|
|
<div className="flex-[1.5] flex flex-col justify-between relative z-10">
|
|
<div>
|
|
<h2 className="text-3xl font-bold mb-4 tracking-tight">
|
|
The Architect
|
|
</h2>
|
|
<p className="text-base text-neutral-400 leading-relaxed max-w-lg">
|
|
Bridging the gap between rigid regulatory requirements and
|
|
fluid user experiences. I specialize in designing{" "}
|
|
<span className="text-white">distributed systems</span> and
|
|
<span className="text-white">
|
|
{" "}
|
|
cross-platform mobile apps
|
|
</span>{" "}
|
|
with a focus on automated delivery and high-integrity code.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="flex flex-wrap gap-2 mt-8">
|
|
{[
|
|
"#Architecture",
|
|
"#Regulatory Compliance",
|
|
"#Agile Leadership",
|
|
"#DevOps",
|
|
].map((tag) => (
|
|
<span
|
|
key={tag}
|
|
className="text-[10px] font-mono text-neutral-500 border border-neutral-800 px-2 py-1 rounded"
|
|
>
|
|
{tag}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="hidden md:block w-px bg-neutral-800/50 self-stretch" />
|
|
|
|
<div className="flex-1 flex flex-col justify-around py-2 relative z-10">
|
|
<div className="space-y-6">
|
|
<TechnicalFocus
|
|
label="Leadership"
|
|
color="text-blue-500"
|
|
text="Tech Lead & Scrum Master. Orchestrating sprint cycles and system design."
|
|
/>
|
|
<TechnicalFocus
|
|
label="Integrity"
|
|
color="text-purple-500"
|
|
text="Medical/Regulatory environments, QMS, and Cyber Essentials."
|
|
/>
|
|
<TechnicalFocus
|
|
label="Infrastructure"
|
|
color="text-green-500"
|
|
text="Kubernetes, GCP, and automated CI/CD pipelines."
|
|
/>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* Top Row Right: The Service Registry */}
|
|
<Link href="/lab" className="md:col-span-2 flex flex-col group">
|
|
<motion.div
|
|
variants={itemVariants}
|
|
whileHover={{ y: -5 }}
|
|
onMouseEnter={() => setIsHoveringMonitors(true)}
|
|
onMouseLeave={() => setIsHoveringMonitors(false)}
|
|
className="flex-1 p-6 rounded-3xl bg-neutral-900 border border-neutral-800 flex flex-col justify-center relative overflow-hidden min-h-[180px] hover:border-blue-500/30"
|
|
>
|
|
<MonitorCard isHovered={isHoveringMonitors} />
|
|
</motion.div>
|
|
</Link>
|
|
|
|
{/* Project Category Cards */}
|
|
<CategoryCard
|
|
href="/projects/web"
|
|
icon={<Globe className="text-blue-400 w-6 h-6 mb-4" />}
|
|
title="Web Systems"
|
|
description="Architecting distributed platforms with a focus on high-availability."
|
|
tech={["Next.js", "Python", "Node.js", "Caddy", "PostgreSQL"]}
|
|
hoverColor="hover:border-blue-500/30"
|
|
activeTechColor="group-hover:text-blue-400"
|
|
/>
|
|
|
|
<CategoryCard
|
|
href="/projects/mobile"
|
|
icon={<Smartphone className="text-purple-400 w-6 h-6 mb-4" />}
|
|
title="Mobile Apps"
|
|
description="Building fluid, cross-platform experiences using reactive state."
|
|
tech={["Android", "iOS", "Flutter", "Riverpod", "Stores"]}
|
|
hoverColor="hover:border-purple-500/30"
|
|
activeTechColor="group-hover:text-purple-400"
|
|
/>
|
|
|
|
<CategoryCard
|
|
href="/infrastructure"
|
|
icon={<Server className="text-green-400 w-6 h-6 mb-4" />}
|
|
title="Infrastructure"
|
|
description="Resilient cloud environments with automated IaC and multi-region orchestration."
|
|
tech={["Kubernetes", "Terraform", "GCP", "CI/CD", "Security"]}
|
|
hoverColor="hover:border-green-500/30"
|
|
activeTechColor="group-hover:text-green-400"
|
|
/>
|
|
|
|
{/* Bottom Row: The Forge */}
|
|
<Link href="/forge" className="md:col-span-6">
|
|
<motion.div
|
|
variants={itemVariants}
|
|
className="p-8 rounded-3xl bg-neutral-900/50 border border-neutral-800 flex items-center gap-6 group hover:border-orange-500/30 transition-colors cursor-pointer"
|
|
>
|
|
<div className="p-4 bg-orange-500/10 rounded-2xl border border-orange-500/20 group-hover:border-orange-500/40 transition-colors">
|
|
<Hammer className="text-orange-500 w-8 h-8 group-hover:rotate-12 transition-transform" />
|
|
</div>
|
|
<div>
|
|
<div className="flex items-center gap-2 mb-0.5">
|
|
<h3 className="font-bold text-xl tracking-tight">
|
|
The Forge
|
|
</h3>
|
|
<span className="w-1.5 h-1.5 rounded-full bg-orange-500 animate-pulse" />
|
|
</div>
|
|
<p className="text-sm text-neutral-500 leading-tight">
|
|
A space where I demonstrate what I am currently working on and
|
|
any future projects.
|
|
</p>
|
|
</div>
|
|
</motion.div>
|
|
</Link>
|
|
</div>
|
|
</motion.div>
|
|
</PageLayout>
|
|
);
|
|
}
|
|
|
|
function TechnicalFocus({
|
|
label,
|
|
color,
|
|
text,
|
|
}: {
|
|
label: string;
|
|
color: string;
|
|
text: string;
|
|
}) {
|
|
return (
|
|
<section>
|
|
<h4
|
|
className={`text-[12px] font-mono ${color} uppercase tracking-[0.2em] mb-2`}
|
|
>
|
|
{label}
|
|
</h4>
|
|
<p className="text-xs text-neutral-300 leading-tight">{text}</p>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
function CategoryCard({
|
|
href,
|
|
icon,
|
|
title,
|
|
description,
|
|
tech,
|
|
hoverColor,
|
|
activeTechColor,
|
|
}: CategoryCardProps) {
|
|
return (
|
|
<Link href={href} className="group md:col-span-2">
|
|
<motion.div
|
|
variants={itemVariants}
|
|
whileHover={{ y: -5 }}
|
|
className={`p-6 rounded-3xl bg-neutral-900 border border-neutral-800 h-full flex flex-col justify-between min-h-[260px] relative transition-colors ${hoverColor}`}
|
|
>
|
|
<div>
|
|
{icon}
|
|
<h3 className="font-bold text-xl mb-2">{title}</h3>
|
|
<p className="text-sm text-neutral-500 leading-relaxed">
|
|
{description}
|
|
</p>
|
|
</div>
|
|
<div className="flex flex-wrap gap-2 mt-6">
|
|
{tech.map((t: string) => (
|
|
<span
|
|
key={t}
|
|
className={`text-[9px] font-mono text-neutral-600 border border-neutral-800 px-2 py-1 rounded-md uppercase ${activeTechColor} group-hover:border-current/20 transition-all`}
|
|
>
|
|
{t}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</motion.div>
|
|
</Link>
|
|
);
|
|
}
|