diff --git a/app/components/ProjectThumbnail.tsx b/app/components/ProjectThumbnail.tsx
new file mode 100644
index 0000000..d81f92c
--- /dev/null
+++ b/app/components/ProjectThumbnail.tsx
@@ -0,0 +1,241 @@
+"use client";
+
+import { useMemo } from "react";
+import {
+ Terminal,
+ Smartphone,
+ Globe,
+ Code,
+ LayoutDashboard,
+ MessageSquare,
+ Cloud,
+ Wrench,
+ Cpu,
+ Shield,
+ Boxes,
+ type LucideIcon,
+} from "lucide-react";
+
+interface ProjectThumbnailProps {
+ title: string;
+ category?: string;
+ tags?: string[];
+ slug?: string;
+ size?: "card" | "hero";
+}
+
+const categoryThemes: Record<
+ string,
+ {
+ icon: LucideIcon;
+ gradient: string;
+ darkGradient: string;
+ iconColor: string;
+ darkIconColor: string;
+ pattern: "dots" | "grid" | "diagonal" | "circuit" | "waves" | "terminal";
+ }
+> = {
+ "Web Development": {
+ icon: Code,
+ gradient: "from-liquid-sky/20 via-liquid-blue/10 to-liquid-lavender/20",
+ darkGradient: "dark:from-liquid-sky/10 dark:via-liquid-blue/5 dark:to-liquid-lavender/10",
+ iconColor: "text-blue-500",
+ darkIconColor: "dark:text-blue-400",
+ pattern: "circuit",
+ },
+ "Mobile Development": {
+ icon: Smartphone,
+ gradient: "from-liquid-mint/20 via-liquid-teal/10 to-liquid-sky/20",
+ darkGradient: "dark:from-liquid-mint/10 dark:via-liquid-teal/5 dark:to-liquid-sky/10",
+ iconColor: "text-emerald-500",
+ darkIconColor: "dark:text-emerald-400",
+ pattern: "waves",
+ },
+ "Web Application": {
+ icon: Globe,
+ gradient: "from-liquid-lavender/20 via-liquid-purple/10 to-liquid-pink/20",
+ darkGradient: "dark:from-liquid-lavender/10 dark:via-liquid-purple/5 dark:to-liquid-pink/10",
+ iconColor: "text-violet-500",
+ darkIconColor: "dark:text-violet-400",
+ pattern: "dots",
+ },
+ "Backend Development": {
+ icon: Cpu,
+ gradient: "from-liquid-amber/20 via-liquid-yellow/10 to-liquid-peach/20",
+ darkGradient: "dark:from-liquid-amber/10 dark:via-liquid-yellow/5 dark:to-liquid-peach/10",
+ iconColor: "text-amber-500",
+ darkIconColor: "dark:text-amber-400",
+ pattern: "grid",
+ },
+ "Full-Stack Development": {
+ icon: Boxes,
+ gradient: "from-liquid-teal/20 via-liquid-mint/10 to-liquid-lavender/20",
+ darkGradient: "dark:from-liquid-teal/10 dark:via-liquid-mint/5 dark:to-liquid-lavender/10",
+ iconColor: "text-teal-500",
+ darkIconColor: "dark:text-teal-400",
+ pattern: "grid",
+ },
+ DevOps: {
+ icon: Shield,
+ gradient: "from-liquid-coral/20 via-liquid-rose/10 to-liquid-peach/20",
+ darkGradient: "dark:from-liquid-coral/10 dark:via-liquid-rose/5 dark:to-liquid-peach/10",
+ iconColor: "text-red-500",
+ darkIconColor: "dark:text-red-400",
+ pattern: "diagonal",
+ },
+ default: {
+ icon: Wrench,
+ gradient: "from-liquid-peach/20 via-liquid-rose/10 to-liquid-lavender/20",
+ darkGradient: "dark:from-liquid-peach/10 dark:via-liquid-rose/5 dark:to-liquid-lavender/10",
+ iconColor: "text-stone-400",
+ darkIconColor: "dark:text-stone-500",
+ pattern: "dots",
+ },
+};
+
+const slugIcons: Record
= {
+ "kernel-panic-404-interactive-terminal": Terminal,
+ "portfolio-website": LayoutDashboard,
+ "real-time-chat-application": MessageSquare,
+ "weather-forecast-app": Cloud,
+ "clarity": Smartphone,
+ "e-commerce-platform-api": Boxes,
+ "task-management-dashboard": LayoutDashboard,
+};
+
+function PatternOverlay({ pattern }: { pattern: string }) {
+ const patternMap: Record = {
+ dots: (
+
+ ),
+ grid: (
+
+ ),
+ diagonal: (
+
+ ),
+ circuit: (
+
+ ),
+ waves: (
+
+ ),
+ terminal: (
+
+ ),
+ };
+
+ return patternMap[pattern] || patternMap.dots;
+}
+
+export default function ProjectThumbnail({
+ title,
+ category,
+ tags,
+ slug,
+ size = "card",
+}: ProjectThumbnailProps) {
+ const theme = useMemo(() => {
+ if (slug && slugIcons[slug]) {
+ const matchedTheme = categoryThemes[category || ""] || categoryThemes.default;
+ return { ...matchedTheme, icon: slugIcons[slug] };
+ }
+ return categoryThemes[category || ""] || categoryThemes.default;
+ }, [category, slug]);
+
+ const Icon = theme.icon;
+
+ const isHero = size === "hero";
+
+ const displayTags = tags?.slice(0, 3) ?? [];
+
+ const sizeClasses = isHero
+ ? ""
+ : "";
+
+ return (
+
+
+
+
+
+
+
+
+
+ {title}
+
+
+ {displayTags.length > 0 && (
+
+ {displayTags.map((tag) => (
+
+ {tag}
+
+ ))}
+
+ )}
+
+
+ );
+}
\ No newline at end of file
diff --git a/app/components/Projects.tsx b/app/components/Projects.tsx
index d6de5bc..daf0179 100644
--- a/app/components/Projects.tsx
+++ b/app/components/Projects.tsx
@@ -7,6 +7,7 @@ import Link from "next/link";
import Image from "next/image";
import { useLocale, useTranslations } from "next-intl";
import { Skeleton } from "boneyard-js/react";
+import ProjectThumbnail from "./ProjectThumbnail";
interface Project {
id: number;
@@ -86,9 +87,13 @@ const Projects = () => {
className="object-cover transition-transform duration-700 group-hover:scale-105"
/>
) : (
-
- {project.title.charAt(0)}
-
+
)}
{/* Overlay on Hover */}