diff --git a/src/components/bento/BentoCard.tsx b/src/components/bento/BentoCard.tsx new file mode 100644 index 0000000..0cde7b1 --- /dev/null +++ b/src/components/bento/BentoCard.tsx @@ -0,0 +1,25 @@ +import type { ReactNode } from 'react'; + +type BentoCardProps = { + children: ReactNode; + className?: string; + title?: string; + subtitle?: string; + id?: string; +}; + +export default function BentoCard({ children, className = '', title, subtitle, id }: BentoCardProps) { + return ( +
+
+ ); +} diff --git a/src/components/bento/BentoGrid.tsx b/src/components/bento/BentoGrid.tsx new file mode 100644 index 0000000..8680b7b --- /dev/null +++ b/src/components/bento/BentoGrid.tsx @@ -0,0 +1,16 @@ +import type { ReactNode } from 'react'; + +type BentoGridProps = { + children: ReactNode; + className?: string; +}; + +export default function BentoGrid({ children, className = '' }: BentoGridProps) { + return ( +
+ {children} +
+ ); +} diff --git a/src/components/bento/CaseStudyCard.tsx b/src/components/bento/CaseStudyCard.tsx new file mode 100644 index 0000000..21ce3d4 --- /dev/null +++ b/src/components/bento/CaseStudyCard.tsx @@ -0,0 +1,55 @@ +import SmartLink from '../SmartLink'; +import BentoCard from './BentoCard'; + +type CaseStudyCardProps = { + title: string; + description: string; + bullets: string[]; + metric?: string; + caseStudyUrl?: string; + evidenceUrl?: string; + className?: string; +}; + +export default function CaseStudyCard({ + title, + description, + bullets, + metric, + caseStudyUrl, + evidenceUrl, + className = '', +}: CaseStudyCardProps) { + return ( + +

{description}

+ {metric && ( +

+ {metric} +

+ )} + + {(caseStudyUrl || evidenceUrl) && ( +
+ {caseStudyUrl && ( + + Open Case Study + + )} + {evidenceUrl && ( + + View Evidence + + )} +
+ )} +
+ ); +} diff --git a/src/components/bento/MetricBadge.tsx b/src/components/bento/MetricBadge.tsx new file mode 100644 index 0000000..ed87f17 --- /dev/null +++ b/src/components/bento/MetricBadge.tsx @@ -0,0 +1,11 @@ +type MetricBadgeProps = { + label: string; +}; + +export default function MetricBadge({ label }: MetricBadgeProps) { + return ( + + {label} + + ); +} diff --git a/src/components/bento/ProofCard.tsx b/src/components/bento/ProofCard.tsx new file mode 100644 index 0000000..44840c3 --- /dev/null +++ b/src/components/bento/ProofCard.tsx @@ -0,0 +1,23 @@ +import BentoCard from './BentoCard'; + +type ProofCardProps = { + title: string; + items: string[]; + caption: string; + className?: string; +}; + +export default function ProofCard({ title, items, caption, className = '' }: ProofCardProps) { + return ( + + +

{caption}

+
+ ); +} diff --git a/src/components/bento/SkillClusterCard.tsx b/src/components/bento/SkillClusterCard.tsx new file mode 100644 index 0000000..7b3cb8b --- /dev/null +++ b/src/components/bento/SkillClusterCard.tsx @@ -0,0 +1,21 @@ +import BentoCard from './BentoCard'; + +type SkillClusterCardProps = { + title: string; + skills: string[]; + className?: string; +}; + +export default function SkillClusterCard({ title, skills, className = '' }: SkillClusterCardProps) { + return ( + +
+ {skills.map((skill) => ( + + {skill} + + ))} +
+
+ ); +} diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index 82bce5d..6a76f3b 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -1,15 +1,82 @@ import { useEffect } from 'react'; import { useLocation } from 'react-router-dom'; -import AboutSection from '../sections/AboutSection'; -import ContactSection from '../sections/ContactSection'; -import HeroSection from '../sections/HeroSection'; -import WorkSection from '../sections/WorkSection'; -import WritingSection from '../sections/WritingSection'; -import XRLabSection from '../sections/XRLabSection'; -import ShippedTitlesSection from '../sections/ShippedTitlesSection'; -import ProblemsSolvedSection from '../sections/ProblemsSolvedSection'; -import ParticleField from '../components/ParticleField'; +import SmartLink from '../components/SmartLink'; import { Seo } from '../components/Seo'; +import ParticleField from '../components/ParticleField'; +import BentoGrid from '../components/bento/BentoGrid'; +import BentoCard from '../components/bento/BentoCard'; +import MetricBadge from '../components/bento/MetricBadge'; +import ProofCard from '../components/bento/ProofCard'; +import CaseStudyCard from '../components/bento/CaseStudyCard'; +import SkillClusterCard from '../components/bento/SkillClusterCard'; + +const technicalFocus = [ + { + title: 'CPU/GPU Bottleneck Isolation', + body: 'Use Unity Profiler, Frame Debugger, and controlled toggles to classify bottlenecks before fixes. ATS: GPU-bound, CPU-bound, frame-time delta.', + }, + { + title: 'XR Frame Pacing', + body: 'Target 90Hz/72Hz budgets using frame-time variance tracking, spike classification, and frame-budget aware mitigation.', + }, + { + title: 'Unity Rendering / URP', + body: 'Optimise transparent passes, overdraw hotspots, and render-path setup with reproducible URP benchmark scenes.', + }, + { + title: 'ECS / DOTS Direction', + body: 'Compare manager-driven Update workflows vs ECS patterns for large agent counts and deterministic behavior under stress.', + }, + { + title: 'Object Lifecycle Optimisation', + body: 'Minimise instantiation/destruction overhead with pooling, lifecycle gates, and measured allocation discipline.', + }, + { + title: 'Tools & Deterministic Test Scenes', + body: 'Build profiler HUDs, fixed camera paths, and controlled scenario toggles for baseline vs stress comparison.', + }, + { + title: 'GC / Allocation Discipline', + body: 'Track GC alloc per frame, remove runtime churn paths, and validate memory behavior across long captures.', + }, + { + title: 'Profiling Pipelines', + body: 'Standardise capture notes, bottleneck labels, and mitigation logs so optimisation decisions are auditable.', + }, +]; + +const evidenceCards = [ + { + title: 'Profiler screenshot', + image: '/lab/SoftMaskPro_ScenarioB_Profiler.png', + note: 'SoftMaskPro worst-case profiling capture.', + }, + { + title: 'Frame Debugger screenshot', + image: '/lab/Overdraw_FrameDebugger_TransparentPass.png', + note: 'Transparent pass inspection for overdraw pressure.', + }, + { + title: 'Baseline vs stress table', + image: '/lab/Overdraw_Experiment_Summary.png', + note: 'Baseline vs overdraw stress comparison.', + }, + { + title: 'Bottleneck classification', + image: '/lab/Overdraw_CPU_RenderThread_Comparison.png', + note: 'CPU vs render thread classification evidence.', + }, + { + title: 'Mitigation notes', + image: '/lab/SoftMaskPro_Patch3_GateQueuePlayerLoopUpdate.png', + note: 'Patch-level mitigation log in context.', + }, + { + title: 'Before/after measurements', + image: '', + note: 'Evidence image pending', + }, +]; export default function HomePage() { const location = useLocation(); @@ -27,35 +94,221 @@ export default function HomePage() { return (
- {/* Particle background */} - - {/* Grid overlay */}