Skip to content

Commit 8daf28c

Browse files
hshakericlaude
andcommitted
Improve code quality, SEO, and accessibility
- Split index.tsx into reusable section components for maintainability - Add comprehensive SEO metadata (Open Graph, Twitter Cards, meta tags) - Add accessibility improvements (skip-to-content, focus indicators, ARIA) - Add custom 404 page for better UX - Downgrade React 19 RC to stable React 18.3.1 - Remove unused files (duplicate tailwind.config.js, api/hello.ts, fonts) - Remove --legacy-peer-deps from deploy workflow 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent f3d2ce5 commit 8daf28c

17 files changed

Lines changed: 510 additions & 355 deletions

.github/workflows/deploy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
node-version: '18'
2121

2222
- name: Install dependencies
23-
run: npm install --legacy-peer-deps
23+
run: npm install
2424

2525
- name: Build
2626
run: npm run build

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
"framer-motion": "^11.11.11",
1616
"lucide-react": "^0.456.0",
1717
"next": "15.0.3",
18-
"react": "19.0.0-rc-66855b96-20241106",
19-
"react-dom": "19.0.0-rc-66855b96-20241106",
18+
"react": "^18.3.1",
19+
"react-dom": "^18.3.1",
2020
"tailwind-merge": "^2.5.4"
2121
},
2222
"devDependencies": {
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import Image from "next/image";
2+
import Link from "next/link";
3+
import { Card, CardContent } from "@/components/ui/card";
4+
import { Github, GraduationCap, Mail, MapPin, Moon, Sun, Book } from "lucide-react";
5+
6+
interface HeaderCardProps {
7+
theme: string;
8+
onToggleTheme: () => void;
9+
}
10+
11+
export function HeaderCard({ theme, onToggleTheme }: HeaderCardProps) {
12+
return (
13+
<Card className="dark:bg-gray-800 dark:border-gray-700">
14+
<CardContent className="py-6">
15+
<div className="flex flex-col items-center">
16+
<h1 className="text-2xl font-bold dark:text-white mb-4">Shakeri Lab</h1>
17+
18+
<div className="w-[100px] mb-4">
19+
<Image
20+
src="/dynamo-lab-logo.png"
21+
alt="Shakeri Lab Logo"
22+
width={100}
23+
height={100}
24+
className="h-auto w-full"
25+
priority
26+
/>
27+
</div>
28+
29+
<p className="text-sm text-gray-600 dark:text-gray-300 text-center mb-6 max-w-md">
30+
Advancing Machine Intelligence for Dynamical Systems and Control in Biomedical Applications
31+
</p>
32+
33+
<div className="flex justify-center items-center gap-6 pt-2">
34+
<Link
35+
href="mailto:hs9hd@virginia.edu"
36+
className="hover:text-primary transition-colors"
37+
title="hs9hd at virginia dot edu"
38+
>
39+
<Mail className="h-5 w-5" />
40+
<span className="sr-only">Email</span>
41+
</Link>
42+
<Link
43+
href="https://www.google.com/maps/place/1919+Ivy+Rd,+Charlottesville,+VA+22903"
44+
className="hover:text-primary transition-colors"
45+
target="_blank"
46+
rel="noopener noreferrer"
47+
title="1919 Ivy Rd, Charlottesville, VA 22903"
48+
>
49+
<MapPin className="h-5 w-5" />
50+
<span className="sr-only">Location</span>
51+
</Link>
52+
<Link
53+
href="https://shakeri-lab.github.io/dl-course-site/"
54+
className="hover:text-primary transition-colors"
55+
target="_blank"
56+
rel="noopener noreferrer"
57+
title="Deep Learning Course Website"
58+
>
59+
<Book className="h-5 w-5" />
60+
<span className="sr-only">Deep Learning Course</span>
61+
</Link>
62+
<Link
63+
href="https://scholar.google.com/citations?user=zFIIhGMAAAAJ&hl=en&oi=ao"
64+
className="hover:text-primary transition-colors"
65+
target="_blank"
66+
rel="noopener noreferrer"
67+
title="Google Scholar Profile"
68+
>
69+
<GraduationCap className="h-5 w-5" />
70+
<span className="sr-only">Google Scholar</span>
71+
</Link>
72+
<Link
73+
href="https://github.com/Shakeri-Lab"
74+
className="hover:text-primary transition-colors"
75+
target="_blank"
76+
rel="noopener noreferrer"
77+
title="GitHub Organization"
78+
>
79+
<Github className="h-5 w-5" />
80+
<span className="sr-only">GitHub</span>
81+
</Link>
82+
<button
83+
onClick={onToggleTheme}
84+
className="p-1 rounded-md hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 dark:focus:ring-offset-gray-800"
85+
aria-label={theme === "dark" ? "Switch to light mode" : "Switch to dark mode"}
86+
>
87+
{theme === "dark" ?
88+
<Sun className="h-5 w-5 text-yellow-500" /> :
89+
<Moon className="h-5 w-5 text-gray-500" />
90+
}
91+
</button>
92+
</div>
93+
</div>
94+
</CardContent>
95+
</Card>
96+
);
97+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
2+
3+
export function JoinCard() {
4+
return (
5+
<Card className="dark:bg-gray-800 dark:border-gray-700">
6+
<CardHeader>
7+
<CardTitle className="text-base dark:text-white">Join Our Team</CardTitle>
8+
</CardHeader>
9+
<CardContent>
10+
<p className="text-sm dark:text-gray-300">
11+
We are always looking for passionate students interested in machine learning and control systems.
12+
Reach out to learn about our open PhD positions!
13+
</p>
14+
</CardContent>
15+
</Card>
16+
);
17+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import Link from "next/link";
2+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
3+
import { motion } from "framer-motion";
4+
import { news } from "@/data/news";
5+
6+
export function NewsCard() {
7+
return (
8+
<Card className="dark:bg-gray-800 dark:border-gray-700">
9+
<CardHeader>
10+
<CardTitle className="text-base dark:text-white">News</CardTitle>
11+
</CardHeader>
12+
<CardContent className="relative">
13+
<div className="h-[1350px] overflow-y-auto pr-2 space-y-4 scrollbar-thin">
14+
{news.map((item, index) => (
15+
<motion.div
16+
key={index}
17+
initial={{ opacity: 0, y: 20 }}
18+
animate={{ opacity: 1, y: 0 }}
19+
transition={{ duration: 0.3, delay: index * 0.1 }}
20+
className="pb-4 border-b border-gray-100 dark:border-gray-700 last:border-0"
21+
>
22+
<p className="text-xs text-muted-foreground dark:text-gray-400">{item.date}</p>
23+
<h3 className="text-sm font-semibold dark:text-white">{item.title}</h3>
24+
<p className="text-sm dark:text-gray-300">{item.content}</p>
25+
{item.links && item.links.length > 0 && (
26+
<div className="mt-2 space-x-4">
27+
{item.links.map((link, linkIndex) => (
28+
<Link
29+
key={linkIndex}
30+
href={link.url}
31+
className="text-sm text-primary hover:underline inline-flex items-center gap-1"
32+
target="_blank"
33+
rel="noopener noreferrer"
34+
>
35+
{link.text}
36+
</Link>
37+
))}
38+
</div>
39+
)}
40+
</motion.div>
41+
))}
42+
</div>
43+
44+
{/* Scroll indicator */}
45+
<div className="absolute bottom-0 left-0 right-0 h-16 bg-gradient-to-t from-white dark:from-gray-800 to-transparent pointer-events-none flex items-end justify-center pb-2">
46+
<motion.div
47+
animate={{ y: [0, 5, 0] }}
48+
transition={{ duration: 2, repeat: Infinity }}
49+
className="text-gray-400 text-sm flex items-center gap-1"
50+
>
51+
Scroll for more
52+
<svg
53+
className="w-4 h-4"
54+
fill="none"
55+
strokeWidth="2"
56+
stroke="currentColor"
57+
viewBox="0 0 24 24"
58+
aria-hidden="true"
59+
>
60+
<path d="M19 14l-7 7m0 0l-7-7m7 7V3" />
61+
</svg>
62+
</motion.div>
63+
</div>
64+
</CardContent>
65+
</Card>
66+
);
67+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
2+
3+
const projects = [
4+
{
5+
title: "Smart Artificial Pancreas Systems",
6+
description: (
7+
<>
8+
In collaboration with the <strong className="dark:text-white">UVA Center of Diabetes</strong>, we are pioneering &quot;trainable&quot; artificial pancreas systems that leverage
9+
machine learning to personalize diabetes management for individuals with <strong className="dark:text-white">Type 1 Diabetes</strong>. By harnessing vast amounts of continuous
10+
glucose monitoring (CGM) and insulin delivery data, we&apos;re developing smarter, fully automated closed-loop control algorithms. Our goal is to improve
11+
patient outcomes and enhance quality of life by providing more precise and adaptive insulin delivery.
12+
</>
13+
),
14+
},
15+
{
16+
title: "Single-Cell Signaling Dynamics",
17+
description: (
18+
<>
19+
Our team is creating novel learning frameworks to analyze how individual cells respond to different stimuli. By focusing on signaling molecules
20+
and transcription factors, we aim to uncover how cells make heterogeneous and context-dependent decisions. We integrate high-dimensional single-cell
21+
measurements with live-cell trajectory data using advanced techniques like <strong>stochastic flow matching</strong> and <strong>spectral operator analysis</strong>.
22+
This research advances our understanding of cellular behavior at the single-cell level, potentially leading to new therapeutic strategies in precision medicine.
23+
</>
24+
),
25+
},
26+
{
27+
title: "Explainable AI for Glaucoma Risk Assessment",
28+
description: (
29+
<>
30+
We are developing <strong>GUIDE</strong> (Glaucoma Understanding and Integrated Data Evaluation), an explainable AI framework that uses <strong>foundation models</strong>
31+
to integrate clinical data, imaging, electronic health records, and social determinants of health. Our goal is to provide personalized glaucoma risk assessments,
32+
enhance fairness, and reduce health disparities through transparent and robust multimodal models. By employing <strong>hierarchical fusion models</strong> and focusing
33+
on <strong>contextual transparency</strong>, we aim to transform glaucoma management and improve patient outcomes.
34+
</>
35+
),
36+
},
37+
{
38+
title: "Operator-Theoretic Methods in Dynamical Systems",
39+
description: (
40+
<>
41+
Employing operator theory, particularly within the <strong>Koopman framework</strong>, we analyze the spectral characteristics of complex dynamical systems.
42+
This work advances reduced-order modeling and innovative control strategies, improving <strong>Model Predictive Control (MPC)</strong> and model-based learning
43+
for high-dimensional, nonlinear systems. Our approach addresses challenges like instabilities from continuous spectra and sensitivity to initial conditions,
44+
enhancing the performance of <strong>model-based reinforcement learning</strong> and <strong>physics-informed machine learning (ML)</strong> methods.
45+
</>
46+
),
47+
},
48+
{
49+
title: "Complex Networks and Graph Data Analysis",
50+
description: (
51+
<>
52+
We investigate the dynamics of complex networks to understand how topological features influence processes such as information spread, disease transmission,
53+
and network robustness. By leveraging <strong>machine learning</strong>, <strong>dynamical systems theory</strong>, and <strong>reinforcement learning</strong>,
54+
we design and optimize network architectures for desired functionalities in communication networks, power grids, and social systems. Our research enhances the
55+
capabilities of <strong>Graph Neural Networks (GNNs)</strong> by incorporating high-order structures, capturing nuanced relationships, and improving community detection.
56+
</>
57+
),
58+
},
59+
];
60+
61+
export function ProjectsCard() {
62+
return (
63+
<Card className="dark:bg-gray-800 dark:border-gray-700">
64+
<CardHeader>
65+
<CardTitle className="dark:text-white">Current Projects</CardTitle>
66+
</CardHeader>
67+
<CardContent className="space-y-8">
68+
{projects.map((project, index) => (
69+
<div key={index}>
70+
<h3 className="font-semibold mb-2 text-zinc-700 dark:text-zinc-300">{project.title}</h3>
71+
<p className="text-sm dark:text-gray-300">{project.description}</p>
72+
</div>
73+
))}
74+
</CardContent>
75+
</Card>
76+
);
77+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
2+
3+
export function ResearchCard() {
4+
return (
5+
<Card className="dark:bg-gray-800 dark:border-gray-700">
6+
<CardHeader>
7+
<CardTitle className="dark:text-white">Research Overview</CardTitle>
8+
</CardHeader>
9+
<CardContent className="space-y-4">
10+
<p className="text-sm dark:text-gray-300">
11+
At Shakeri Lab, we develop intelligent algorithms to control and understand complex dynamical systems in biomedical applications.
12+
Our interdisciplinary approach bridges machine learning, control theory, and data science to tackle challenges ranging from cellular dynamics to human health.
13+
</p>
14+
<p className="text-sm dark:text-gray-300">
15+
While our primary focus is on biomedical applications, we also explore intelligent control and data analysis techniques in areas like traffic optimization
16+
and change-point detection in temporal multispectral images. These projects showcase the versatility of our methods and their applicability to various complex systems.
17+
</p>
18+
</CardContent>
19+
</Card>
20+
);
21+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import Link from "next/link";
2+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
3+
import { team } from "@/data/team";
4+
5+
export function TeamCard() {
6+
return (
7+
<Card className="dark:bg-gray-800 dark:border-gray-700">
8+
<CardHeader>
9+
<CardTitle className="text-base dark:text-white">Team</CardTitle>
10+
</CardHeader>
11+
<CardContent>
12+
<div className="space-y-4">
13+
<div>
14+
<h3 className="font-semibold text-sm text-zinc-700 dark:text-zinc-300">Principal Investigator</h3>
15+
<Link
16+
href={team.pi.link}
17+
className="text-sm text-primary hover:underline"
18+
target="_blank"
19+
rel="noopener noreferrer"
20+
>
21+
{team.pi.name}
22+
</Link>
23+
</div>
24+
<div>
25+
<h3 className="font-semibold text-sm text-zinc-700 dark:text-zinc-300">Current Members</h3>
26+
<ul className="space-y-2">
27+
{team.currentMembers.map((member, index) => (
28+
<li key={index} className="text-sm dark:text-gray-300">
29+
{member.link ? (
30+
<Link
31+
href={member.link}
32+
className="text-primary hover:underline"
33+
target="_blank"
34+
rel="noopener noreferrer"
35+
>
36+
{member.name}
37+
</Link>
38+
) : (
39+
member.name
40+
)} - {member.title}
41+
</li>
42+
))}
43+
</ul>
44+
</div>
45+
<div>
46+
<h3 className="font-semibold text-sm text-zinc-700 dark:text-zinc-300">Alumni</h3>
47+
<ul className="space-y-2">
48+
{team.alumni.map((member, index) => (
49+
<li key={index} className="text-sm dark:text-gray-300">
50+
{member.link ? (
51+
<Link
52+
href={member.link}
53+
className="text-primary hover:underline"
54+
target="_blank"
55+
rel="noopener noreferrer"
56+
>
57+
{member.name}
58+
</Link>
59+
) : (
60+
member.name
61+
)} - {member.title}
62+
</li>
63+
))}
64+
</ul>
65+
</div>
66+
</div>
67+
</CardContent>
68+
</Card>
69+
);
70+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Card, CardContent } from "@/components/ui/card";
2+
3+
export function VideoCard() {
4+
return (
5+
<Card className="dark:bg-gray-800 dark:border-gray-700">
6+
<CardContent className="aspect-video">
7+
<iframe
8+
width="100%"
9+
height="100%"
10+
src="https://www.youtube.com/embed/6c3mOsUm3cI"
11+
title="Shakeri Lab Introduction Video"
12+
frameBorder="0"
13+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
14+
allowFullScreen
15+
className="rounded-md"
16+
loading="lazy"
17+
/>
18+
</CardContent>
19+
</Card>
20+
);
21+
}

0 commit comments

Comments
 (0)