Update links and refactor components

This commit is contained in:
jessy-david-dev
2026-01-27 16:41:48 +01:00
parent cccabd840e
commit bc1aefc70b
10 changed files with 1818 additions and 2935 deletions
+2 -5
View File
@@ -7,7 +7,7 @@ import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
const socials = [ const socials = [
{ name: "GitHub", href: "https://github.com/jessydavid-dev", icon: Github }, { name: "GitHub", href: "https://github.com/jessy-david-dev", icon: Github },
{ {
name: "LinkedIn", name: "LinkedIn",
href: "https://linkedin.com/in/jessy-david", href: "https://linkedin.com/in/jessy-david",
@@ -55,10 +55,7 @@ export default function Footer() {
> >
{/* Logo */} {/* Logo */}
<motion.div variants={itemVariants}> <motion.div variants={itemVariants}>
<Link <Link href="/" className="inline-flex items-center gap-3 group">
href="/"
className="inline-flex items-center gap-3 group"
>
<motion.div <motion.div
whileHover={{ scale: 1.05 }} whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }} whileTap={{ scale: 0.95 }}
+5 -13
View File
@@ -106,9 +106,7 @@ export default function NavBar() {
</div> </div>
{/* Nom avec effet de soulignement au hover */} {/* Nom avec effet de soulignement au hover */}
<div> <div>
<span className="text-xl font-bold text-white"> <span className="text-xl font-bold text-white">Jessy David</span>
Jessy David
</span>
<span className="absolute -bottom-1 left-0 w-0 h-0.5 bg-linear-to-r from-blue-500 to-purple-500 group-hover:w-full transition-all duration-300" /> <span className="absolute -bottom-1 left-0 w-0 h-0.5 bg-linear-to-r from-blue-500 to-purple-500 group-hover:w-full transition-all duration-300" />
</div> </div>
</SmoothLink> </SmoothLink>
@@ -116,8 +114,7 @@ export default function NavBar() {
{/* Navigation pc - cachée sur mobile */} {/* Navigation pc - cachée sur mobile */}
<div className="hidden md:flex items-center gap-1"> <div className="hidden md:flex items-center gap-1">
{navLinks.map((link) => { {navLinks.map((link) => {
const isActive = const isActive = activeSection === link.href.replace("#", "");
activeSection === link.href.replace("#", "");
const Icon = link.icon; const Icon = link.icon;
return ( return (
<SmoothLink <SmoothLink
@@ -227,8 +224,7 @@ export default function NavBar() {
{/* Boucle sur les liens avec animation décalée */} {/* Boucle sur les liens avec animation décalée */}
{navLinks.map((link, index) => { {navLinks.map((link, index) => {
const isActive = const isActive =
activeSection === activeSection === link.href.replace("#", "");
link.href.replace("#", "");
const Icon = link.icon; const Icon = link.icon;
return ( return (
<motion.div <motion.div
@@ -261,15 +257,11 @@ export default function NavBar() {
> >
<Icon <Icon
className={`w-5 h-5 ${ className={`w-5 h-5 ${
isActive isActive ? "text-white" : "text-blue-400"
? "text-white"
: "text-blue-400"
}`} }`}
/> />
</div> </div>
<span> <span>{link.label}</span>
{link.label}
</span>
</div> </div>
{/* Indicateur de section active */} {/* Indicateur de section active */}
{isActive && ( {isActive && (
+16 -45
View File
@@ -18,23 +18,15 @@ export default function About() {
const isInView = useInView(ref, { once: false, amount: 0.2 }); const isInView = useInView(ref, { once: false, amount: 0.2 });
return ( return (
<section <section id="about" className="py-20 bg-sky-50 relative overflow-hidden">
id="about"
className="py-20 bg-sky-50 relative overflow-hidden"
>
{/* Grid Background subtil */} {/* Grid Background subtil */}
<div className="absolute inset-0 bg-grid-slate-400/50 mask-[linear-gradient(to_bottom,white,transparent)]"></div> <div className="absolute inset-0 bg-grid-slate-400/50 mask-[linear-gradient(to_bottom,white,transparent)]"></div>
<div <div ref={ref} className="container mx-auto px-4 max-w-7xl relative z-10">
ref={ref}
className="container mx-auto px-4 max-w-7xl relative z-10"
>
{/* Header */} {/* Header */}
<motion.div <motion.div
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={ animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }
}
transition={{ duration: 0.6 }} transition={{ duration: 0.6 }}
className="text-center mb-16" className="text-center mb-16"
> >
@@ -42,8 +34,8 @@ export default function About() {
À propos de moi À propos de moi
</h2> </h2>
<p className="text-xl text-slate-600 max-w-2xl mx-auto"> <p className="text-xl text-slate-600 max-w-2xl mx-auto">
Développeur web créatif, combinant frontend et backend Développeur web créatif, combinant frontend et backend pour des
pour des solutions digitales impactantes solutions digitales impactantes
</p> </p>
</motion.div> </motion.div>
@@ -52,11 +44,7 @@ export default function About() {
{/* Large card - Présentation */} {/* Large card - Présentation */}
<motion.div <motion.div
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={ animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
isInView
? { opacity: 1, y: 0 }
: { opacity: 0, y: 20 }
}
transition={{ duration: 0.5, delay: 0.1 }} transition={{ duration: 0.5, delay: 0.1 }}
className="md:col-span-8 bg-linear-to-r from-blue-500 to-purple-600 rounded-3xl p-8 text-white shadow-2xl" className="md:col-span-8 bg-linear-to-r from-blue-500 to-purple-600 rounded-3xl p-8 text-white shadow-2xl"
> >
@@ -65,26 +53,21 @@ export default function About() {
Créateur d&apos;expériences digitales Créateur d&apos;expériences digitales
</h3> </h3>
<p className="text-lg text-blue-50 leading-relaxed mb-4"> <p className="text-lg text-blue-50 leading-relaxed mb-4">
Passionné par le développement web, je crée des Passionné par le développement web, je crée des applications
applications modernes, performantes et élégantes. modernes, performantes et élégantes. Mon objectif est de
Mon objectif est de transformer des idées en transformer des idées en solutions digitales innovantes.
solutions digitales innovantes.
</p> </p>
<p className="text-lg text-blue-50 leading-relaxed"> <p className="text-lg text-blue-50 leading-relaxed">
Avec une expertise en développement full-stack, je Avec une expertise en développement full-stack, je maîtrise aussi
maîtrise aussi bien le front-end que le back-end, me bien le front-end que le back-end, me permettant de concevoir des
permettant de concevoir des projets de A à Z. projets de A à Z.
</p> </p>
</motion.div> </motion.div>
{/* Small cards - Stats/Features */} {/* Small cards - Stats/Features */}
<motion.div <motion.div
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={ animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
isInView
? { opacity: 1, y: 0 }
: { opacity: 0, y: 20 }
}
transition={{ duration: 0.5, delay: 0.2 }} transition={{ duration: 0.5, delay: 0.2 }}
className="md:col-span-4 bg-white rounded-3xl p-6 shadow-lg border border-slate-200" className="md:col-span-4 bg-white rounded-3xl p-6 shadow-lg border border-slate-200"
> >
@@ -99,11 +82,7 @@ export default function About() {
<motion.div <motion.div
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={ animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
isInView
? { opacity: 1, y: 0 }
: { opacity: 0, y: 20 }
}
transition={{ duration: 0.5, delay: 0.3 }} transition={{ duration: 0.5, delay: 0.3 }}
className="md:col-span-4 bg-white rounded-3xl p-6 shadow-lg border border-slate-200" className="md:col-span-4 bg-white rounded-3xl p-6 shadow-lg border border-slate-200"
> >
@@ -118,11 +97,7 @@ export default function About() {
<motion.div <motion.div
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={ animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
isInView
? { opacity: 1, y: 0 }
: { opacity: 0, y: 20 }
}
transition={{ duration: 0.5, delay: 0.4 }} transition={{ duration: 0.5, delay: 0.4 }}
className="md:col-span-4 bg-white rounded-3xl p-6 shadow-lg border border-slate-200" className="md:col-span-4 bg-white rounded-3xl p-6 shadow-lg border border-slate-200"
> >
@@ -138,11 +113,7 @@ export default function About() {
{/* Technologies grid */} {/* Technologies grid */}
<motion.div <motion.div
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={ animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
isInView
? { opacity: 1, y: 0 }
: { opacity: 0, y: 20 }
}
transition={{ duration: 0.5, delay: 0.5 }} transition={{ duration: 0.5, delay: 0.5 }}
className="md:col-span-4 bg-slate-900 rounded-3xl p-8 shadow-2xl" className="md:col-span-4 bg-slate-900 rounded-3xl p-8 shadow-2xl"
> >
+14 -48
View File
@@ -25,7 +25,7 @@ const contactMethods = [
icon: Github, icon: Github,
label: "GitHub", label: "GitHub",
value: "@jessydavid", value: "@jessydavid",
href: "https://github.com/jessydavid-dev", href: "https://github.com/jessy-david-dev",
color: "from-slate-700 to-slate-900", color: "from-slate-700 to-slate-900",
}, },
{ {
@@ -92,9 +92,7 @@ export default function Contact() {
} catch (err) { } catch (err) {
console.error("Erreur:", err); console.error("Erreur:", err);
setError( setError(
err instanceof Error err instanceof Error ? err.message : "Impossible d'envoyer le message.",
? err.message
: "Impossible d'envoyer le message."
); );
setCaptchaToken(""); setCaptchaToken("");
} finally { } finally {
@@ -121,16 +119,11 @@ export default function Contact() {
<div className="absolute top-20 left-10 w-96 h-96 bg-blue-500/10 rounded-full blur-3xl"></div> <div className="absolute top-20 left-10 w-96 h-96 bg-blue-500/10 rounded-full blur-3xl"></div>
<div className="absolute bottom-20 right-10 w-96 h-96 bg-purple-500/10 rounded-full blur-3xl"></div> <div className="absolute bottom-20 right-10 w-96 h-96 bg-purple-500/10 rounded-full blur-3xl"></div>
<div <div ref={ref} className="container mx-auto px-4 max-w-7xl relative z-10">
ref={ref}
className="container mx-auto px-4 max-w-7xl relative z-10"
>
{/* Header */} {/* Header */}
<motion.div <motion.div
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={ animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }
}
transition={{ duration: 0.6 }} transition={{ duration: 0.6 }}
className="text-center mb-16" className="text-center mb-16"
> >
@@ -144,8 +137,7 @@ export default function Contact() {
Contactez-moi Contactez-moi
</h2> </h2>
<p className="text-xl text-slate-400 max-w-2xl mx-auto"> <p className="text-xl text-slate-400 max-w-2xl mx-auto">
Un projet en tête ? Une question ? N&apos;hésitez pas à Un projet en tête ? Une question ? N&apos;hésitez pas à me contacter
me contacter
</p> </p>
</motion.div> </motion.div>
@@ -153,11 +145,7 @@ export default function Contact() {
{/* Colonne de gauche - Méthodes de contact */} {/* Colonne de gauche - Méthodes de contact */}
<motion.div <motion.div
initial={{ opacity: 0, x: -50 }} initial={{ opacity: 0, x: -50 }}
animate={ animate={isInView ? { opacity: 1, x: 0 } : { opacity: 0, x: -50 }}
isInView
? { opacity: 1, x: 0 }
: { opacity: 0, x: -50 }
}
transition={{ duration: 0.6, delay: 0.2 }} transition={{ duration: 0.6, delay: 0.2 }}
className="space-y-6" className="space-y-6"
> >
@@ -171,9 +159,7 @@ export default function Contact() {
rel="noopener noreferrer" rel="noopener noreferrer"
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={ animate={
isInView isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }
? { opacity: 1, y: 0 }
: { opacity: 0, y: 20 }
} }
transition={{ transition={{
duration: 0.5, duration: 0.5,
@@ -206,11 +192,7 @@ export default function Contact() {
{/* Informations complémentaires */} {/* Informations complémentaires */}
<motion.div <motion.div
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={ animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
isInView
? { opacity: 1, y: 0 }
: { opacity: 0, y: 20 }
}
transition={{ duration: 0.5, delay: 0.6 }} transition={{ duration: 0.5, delay: 0.6 }}
className="bg-linear-to-br from-blue-500/10 to-purple-500/10 backdrop-blur-sm border border-blue-500/20 rounded-2xl p-6" className="bg-linear-to-br from-blue-500/10 to-purple-500/10 backdrop-blur-sm border border-blue-500/20 rounded-2xl p-6"
> >
@@ -226,8 +208,7 @@ export default function Contact() {
Disponibilité Disponibilité
</h3> </h3>
<p className="text-slate-400"> <p className="text-slate-400">
Actuellement disponible pour vos Actuellement disponible pour vos projets.
projets.
</p> </p>
</div> </div>
</div> </div>
@@ -237,11 +218,7 @@ export default function Contact() {
{/* Colonne de droite - Formulaire de contact */} {/* Colonne de droite - Formulaire de contact */}
<motion.div <motion.div
initial={{ opacity: 0, x: 50 }} initial={{ opacity: 0, x: 50 }}
animate={ animate={isInView ? { opacity: 1, x: 0 } : { opacity: 0, x: 50 }}
isInView
? { opacity: 1, x: 0 }
: { opacity: 0, x: 50 }
}
transition={{ duration: 0.6, delay: 0.2 }} transition={{ duration: 0.6, delay: 0.2 }}
> >
<div className="bg-slate-800/50 backdrop-blur-sm border border-slate-700 rounded-2xl p-8"> <div className="bg-slate-800/50 backdrop-blur-sm border border-slate-700 rounded-2xl p-8">
@@ -303,14 +280,8 @@ export default function Contact() {
{/* Cloudflare Turnstile */} {/* Cloudflare Turnstile */}
<div className="flex justify-center"> <div className="flex justify-center">
<Turnstile <Turnstile
siteKey={ siteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY || ""}
process.env onSuccess={(token) => setCaptchaToken(token)}
.NEXT_PUBLIC_TURNSTILE_SITE_KEY ||
""
}
onSuccess={(token) =>
setCaptchaToken(token)
}
onError={() => setCaptchaToken("")} onError={() => setCaptchaToken("")}
onExpire={() => setCaptchaToken("")} onExpire={() => setCaptchaToken("")}
options={{ options={{
@@ -341,19 +312,14 @@ export default function Contact() {
> >
<CheckCircle2 className="w-5 h-5 shrink-0" /> <CheckCircle2 className="w-5 h-5 shrink-0" />
<span> <span>
Message envoyé avec succès ! Je vous Message envoyé avec succès ! Je vous répondrai bientôt.
répondrai bientôt.
</span> </span>
</motion.div> </motion.div>
)} )}
<button <button
type="submit" type="submit"
disabled={ disabled={isSubmitting || isSubmitted || !captchaToken}
isSubmitting ||
isSubmitted ||
!captchaToken
}
className="w-full relative group disabled:opacity-50 disabled:cursor-not-allowed" className="w-full relative group disabled:opacity-50 disabled:cursor-not-allowed"
> >
<div className="absolute inset-0 bg-linear-to-r from-blue-600 to-purple-600 rounded-lg opacity-100 group-hover:opacity-0 transition-opacity duration-300"></div> <div className="absolute inset-0 bg-linear-to-r from-blue-600 to-purple-600 rounded-lg opacity-100 group-hover:opacity-0 transition-opacity duration-300"></div>
+15 -43
View File
@@ -12,14 +12,14 @@ const projects = [
"Portfolio moderne et interactif avec animations fluides et design épuré.", "Portfolio moderne et interactif avec animations fluides et design épuré.",
tags: ["Next.js", "TypeScript", "TailwindCSS"], tags: ["Next.js", "TypeScript", "TailwindCSS"],
link: "/", link: "/",
github: "https://github.com/jessydavid-dev/jessy-david.dev", github: "https://github.com/jessy-david-dev/jessy-david.dev",
}, },
{ {
title: "ultralion.xyz", title: "ultralion.xyz",
description: description:
"Portfolio professionnel et moderne pour UltraLion avec design épuré et optimisé.", "Portfolio professionnel et moderne pour UltraLion avec design épuré et optimisé.",
tags: ["Next.js", "TypeScript", "TailwindCSS"], tags: ["Next.js", "TypeScript", "TailwindCSS"],
link: "https://ultralion.xyz", link: "https://v1.jessy-david.dev",
}, },
{ {
title: "Radio Box", title: "Radio Box",
@@ -37,8 +37,7 @@ const projects = [
}, },
{ {
title: "bôba là", title: "bôba là",
description: description: "Application web de fidélité client avec système de points.",
"Application web de fidélité client avec système de points.",
tags: ["Next.js", "TypeScript", "TailwindCSS"], tags: ["Next.js", "TypeScript", "TailwindCSS"],
link: "https://fidelite.boba-la.fr", link: "https://fidelite.boba-la.fr",
collaborators: [ collaborators: [
@@ -79,16 +78,11 @@ export default function Projects() {
id="projects" id="projects"
className="py-20 bg-slate-50 relative overflow-hidden" className="py-20 bg-slate-50 relative overflow-hidden"
> >
<div <div ref={ref} className="container mx-auto px-4 max-w-6xl relative z-10">
ref={ref}
className="container mx-auto px-4 max-w-6xl relative z-10"
>
{/* Header */} {/* Header */}
<motion.div <motion.div
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={ animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }
}
transition={{ duration: 0.6 }} transition={{ duration: 0.6 }}
className="text-center mb-16" className="text-center mb-16"
> >
@@ -108,11 +102,7 @@ export default function Projects() {
className="grid md:grid-cols-2 gap-6" className="grid md:grid-cols-2 gap-6"
> >
{projects.map((project, index) => ( {projects.map((project, index) => (
<motion.div <motion.div key={index} variants={itemVariants} className="group">
key={index}
variants={itemVariants}
className="group"
>
<div className="h-full bg-white rounded-xl border border-slate-200 hover:border-slate-900 transition-all duration-300 hover:shadow-lg overflow-hidden"> <div className="h-full bg-white rounded-xl border border-slate-200 hover:border-slate-900 transition-all duration-300 hover:shadow-lg overflow-hidden">
{/* Card content */} {/* Card content */}
<div className="p-6"> <div className="p-6">
@@ -143,42 +133,28 @@ export default function Projects() {
project.collaborators.length > 0 && ( project.collaborators.length > 0 && (
<div className="mb-6 pb-6 border-b border-slate-100"> <div className="mb-6 pb-6 border-b border-slate-100">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
{project.collaborators.map( {project.collaborators.map((collab, idx) => (
(collab, idx) => (
<a <a
key={idx} key={idx}
href={ href={collab.github}
collab.github
}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="group/collab flex items-center gap-2 text-sm text-slate-600 hover:text-slate-900 transition-colors" className="group/collab flex items-center gap-2 text-sm text-slate-600 hover:text-slate-900 transition-colors"
> >
<div className="w-6 h-6 rounded-full overflow-hidden border border-slate-200 group-hover/collab:border-slate-900 transition-colors"> <div className="w-6 h-6 rounded-full overflow-hidden border border-slate-200 group-hover/collab:border-slate-900 transition-colors">
<Image <Image
src={ src={collab.avatar}
collab.avatar alt={collab.name}
} width={24}
alt={ height={24}
collab.name
}
width={
24
}
height={
24
}
className="w-full h-full object-cover" className="w-full h-full object-cover"
/> />
</div> </div>
<span className="text-xs font-medium"> <span className="text-xs font-medium">
{ {collab.name}
collab.name
}
</span> </span>
</a> </a>
) ))}
)}
</div> </div>
</div> </div>
)} )}
@@ -187,11 +163,7 @@ export default function Projects() {
<div className="flex gap-3"> <div className="flex gap-3">
<a <a
href={project.link} href={project.link}
target={ target={project.link.startsWith("/") ? "_self" : "_blank"}
project.link.startsWith("/")
? "_self"
: "_blank"
}
rel={ rel={
project.link.startsWith("/") project.link.startsWith("/")
? "" ? ""
+12 -39
View File
@@ -35,14 +35,7 @@ const skills = {
category: "Outils", category: "Outils",
icon: Wrench, icon: Wrench,
color: "from-orange-500 to-red-500", color: "from-orange-500 to-red-500",
items: [ items: ["Github", "Docker", "VS Code", "Linux", "Cloudflare", "Proxmox"],
"Github",
"Docker",
"VS Code",
"Linux",
"Cloudflare",
"Proxmox",
],
}, },
}; };
@@ -70,24 +63,16 @@ export default function Skills() {
}; };
return ( return (
<section <section id="skills" className="py-20 bg-white relative overflow-hidden">
id="skills"
className="py-20 bg-white relative overflow-hidden"
>
{/* Decorative blobs */} {/* Decorative blobs */}
<div className="absolute top-0 left-0 w-96 h-96 bg-blue-500/5 rounded-full blur-3xl"></div> <div className="absolute top-0 left-0 w-96 h-96 bg-blue-500/5 rounded-full blur-3xl"></div>
<div className="absolute bottom-0 right-0 w-96 h-96 bg-purple-500/5 rounded-full blur-3xl"></div> <div className="absolute bottom-0 right-0 w-96 h-96 bg-purple-500/5 rounded-full blur-3xl"></div>
<div <div ref={ref} className="container mx-auto px-4 max-w-7xl relative z-10">
ref={ref}
className="container mx-auto px-4 max-w-7xl relative z-10"
>
{/* Header */} {/* Header */}
<motion.div <motion.div
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={ animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }
}
transition={{ duration: 0.6 }} transition={{ duration: 0.6 }}
className="text-center mb-16" className="text-center mb-16"
> >
@@ -101,8 +86,8 @@ export default function Skills() {
Compétences & Technologies Compétences & Technologies
</h2> </h2>
<p className="text-xl text-slate-600 max-w-2xl mx-auto"> <p className="text-xl text-slate-600 max-w-2xl mx-auto">
Un ensemble de technologies modernes maîtrisées pour Un ensemble de technologies modernes maîtrisées pour créer des
créer des applications web performantes et innovantes applications web performantes et innovantes
</p> </p>
</motion.div> </motion.div>
@@ -114,10 +99,7 @@ export default function Skills() {
className="grid grid-cols-1 md:grid-cols-12 gap-4 md:gap-6" className="grid grid-cols-1 md:grid-cols-12 gap-4 md:gap-6"
> >
{/* Frontend - Large card */} {/* Frontend - Large card */}
<motion.div <motion.div variants={itemVariants} className="md:col-span-7 group">
variants={itemVariants}
className="md:col-span-7 group"
>
<div className="relative h-full bg-linear-to-br from-blue-500 to-cyan-500 rounded-3xl p-8 overflow-hidden shadow-xl hover:shadow-2xl transition-all duration-300 hover:-translate-y-1"> <div className="relative h-full bg-linear-to-br from-blue-500 to-cyan-500 rounded-3xl p-8 overflow-hidden shadow-xl hover:shadow-2xl transition-all duration-300 hover:-translate-y-1">
{/* Decorative circles */} {/* Decorative circles */}
<div className="absolute -top-10 -right-10 w-40 h-40 bg-white/10 rounded-full blur-2xl"></div> <div className="absolute -top-10 -right-10 w-40 h-40 bg-white/10 rounded-full blur-2xl"></div>
@@ -147,10 +129,7 @@ export default function Skills() {
</motion.div> </motion.div>
{/* Backend - Medium card */} {/* Backend - Medium card */}
<motion.div <motion.div variants={itemVariants} className="md:col-span-5 group">
variants={itemVariants}
className="md:col-span-5 group"
>
<div className="relative h-full bg-linear-to-br from-purple-500 to-pink-500 rounded-3xl p-8 overflow-hidden shadow-xl hover:shadow-2xl transition-all duration-300 hover:-translate-y-1"> <div className="relative h-full bg-linear-to-br from-purple-500 to-pink-500 rounded-3xl p-8 overflow-hidden shadow-xl hover:shadow-2xl transition-all duration-300 hover:-translate-y-1">
<div className="absolute -top-10 -right-10 w-40 h-40 bg-white/10 rounded-full blur-2xl"></div> <div className="absolute -top-10 -right-10 w-40 h-40 bg-white/10 rounded-full blur-2xl"></div>
@@ -178,10 +157,7 @@ export default function Skills() {
</motion.div> </motion.div>
{/* Tools - Medium card */} {/* Tools - Medium card */}
<motion.div <motion.div variants={itemVariants} className="md:col-span-5 group">
variants={itemVariants}
className="md:col-span-5 group"
>
<div className="relative h-full bg-linear-to-br from-orange-500 to-red-500 rounded-3xl p-8 overflow-hidden shadow-xl hover:shadow-2xl transition-all duration-300 hover:-translate-y-1"> <div className="relative h-full bg-linear-to-br from-orange-500 to-red-500 rounded-3xl p-8 overflow-hidden shadow-xl hover:shadow-2xl transition-all duration-300 hover:-translate-y-1">
<div className="absolute -top-10 -left-10 w-40 h-40 bg-white/10 rounded-full blur-2xl"></div> <div className="absolute -top-10 -left-10 w-40 h-40 bg-white/10 rounded-full blur-2xl"></div>
@@ -209,10 +185,7 @@ export default function Skills() {
</motion.div> </motion.div>
{/* Additional info card */} {/* Additional info card */}
<motion.div <motion.div variants={itemVariants} className="md:col-span-7 group">
variants={itemVariants}
className="md:col-span-7 group"
>
<div className="relative h-full bg-slate-900 rounded-3xl p-8 overflow-hidden shadow-xl hover:shadow-2xl transition-all duration-300 hover:-translate-y-1"> <div className="relative h-full bg-slate-900 rounded-3xl p-8 overflow-hidden shadow-xl hover:shadow-2xl transition-all duration-300 hover:-translate-y-1">
<div className="absolute top-0 right-0 w-64 h-64 bg-blue-500/10 rounded-full blur-3xl"></div> <div className="absolute top-0 right-0 w-64 h-64 bg-blue-500/10 rounded-full blur-3xl"></div>
<div className="absolute bottom-0 left-0 w-64 h-64 bg-purple-500/10 rounded-full blur-3xl"></div> <div className="absolute bottom-0 left-0 w-64 h-64 bg-purple-500/10 rounded-full blur-3xl"></div>
@@ -229,8 +202,8 @@ export default function Skills() {
</div> </div>
<p className="text-slate-300 text-lg leading-relaxed mb-6"> <p className="text-slate-300 text-lg leading-relaxed mb-6">
Une expertise complète du développement web Une expertise complète du développement web moderne, du design
moderne, du design à la mise en production. à la mise en production.
</p> </p>
<div className="grid grid-cols-2 gap-3 mb-6"> <div className="grid grid-cols-2 gap-3 mb-6">
+3 -3
View File
@@ -1,11 +1,11 @@
export const siteConfig = { export const siteConfig = {
name: "Jessy David", name: "Jessy David",
description: "Développeur Web Full-Stack | React, Next.js, Node.js", description: "Développeur Web Full-Stack | React, Next.js, Node.js",
url: "https://jessydavid.dev", url: "https://jessy-david.dev",
email: "contact@jessydavid.dev", email: "contact@jessy-david.dev",
location: "France", location: "France",
socials: { socials: {
github: "https://github.com/jessydavid-dev", github: "https://github.com/jessy-david-dev",
linkedin: "https://linkedin.com/in/jessy-david", linkedin: "https://linkedin.com/in/jessy-david",
}, },
}; };
+40 -16
View File
@@ -2,6 +2,30 @@
"name": "jessy-david.dev", "name": "jessy-david.dev",
"version": "1.0.0", "version": "1.0.0",
"private": true, "private": true,
"description": "Site personnel et portfolio de Jessy David, développé avec Next.js, TypeScript et Tailwind CSS.",
"license": "MIT",
"author": {
"name": "Jessy David",
"email": "contact@jessy-david.dev",
"url": "https://jessy-david.dev"
},
"homepage": "https://jessy-david.dev",
"repository": {
"type": "git",
"url": "https://github.com/jessy-david-dev/jessy-david.dev"
},
"bugs": {
"url": "https://github.com/jessy-david-dev/jessy-david.dev/issues"
},
"keywords": [
"portfolio",
"nextjs",
"react",
"typescript",
"tailwindcss",
"web developer",
"frontend"
],
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
"build": "next build", "build": "next build",
@@ -9,23 +33,23 @@
"lint": "eslint" "lint": "eslint"
}, },
"dependencies": { "dependencies": {
"@marsidev/react-turnstile": "^1.3.1", "@marsidev/react-turnstile": "^1.4.1",
"framer-motion": "^12.23.24", "framer-motion": "^12.29.2",
"lucide-react": "^0.554.0", "lucide-react": "^0.563.0",
"next": "16.0.3", "next": "16.1.5",
"nodemailer": "^7.0.10", "nodemailer": "^7.0.13",
"react": "19.2.0", "react": "19.2.4",
"react-dom": "19.2.0" "react-dom": "19.2.4"
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/postcss": "^4", "@tailwindcss/postcss": "^4.1.18",
"@types/node": "^20", "@types/node": "^25.0.10",
"@types/nodemailer": "^7.0.4", "@types/nodemailer": "^7.0.9",
"@types/react": "^19", "@types/react": "^19.2.10",
"@types/react-dom": "^19", "@types/react-dom": "^19.2.3",
"eslint": "^9", "eslint": "^9.39.2",
"eslint-config-next": "16.0.3", "eslint-config-next": "16.1.5",
"tailwindcss": "^4", "tailwindcss": "^4.1.18",
"typescript": "^5" "typescript": "^5.9.3"
} }
} }
+461 -1473
View File
File diff suppressed because it is too large Load Diff