optimization and moved link after description in project page
This commit is contained in:
parent
4895541c61
commit
fb841cb17c
12
index.html
12
index.html
@ -4,6 +4,10 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
|
||||
<!-- Preload des ressources critiques -->
|
||||
<link rel="preload" as="script" href="/src/main.tsx" />
|
||||
|
||||
<title>Alexandre Pommier - Portfolio</title>
|
||||
<meta name="description" content="Alexandre Pommier, étudiant en informatique à 42, développeur passionné par les technologies web et systèmes." />
|
||||
<meta name="author" content="Alexandre Pommier" />
|
||||
@ -17,10 +21,14 @@
|
||||
<meta name="twitter:site" content="@lovable_dev" />
|
||||
<meta name="twitter:image" content="https://lovable.dev/opengraph-image-p98pqg.png" />
|
||||
|
||||
<!-- Google Fonts -->
|
||||
<!-- Google Fonts - Optimisé avec display=swap et preload -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Montserrat:wght@400;500;600;700&display=swap">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet" media="print" onload="this.media='all'">
|
||||
<noscript>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
</noscript>
|
||||
|
||||
<!-- Google Tag Manager -->
|
||||
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
||||
|
||||
@ -8,11 +8,16 @@ export const ParticlesBackground = () => {
|
||||
const { theme } = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
initParticlesEngine(async (engine) => {
|
||||
await loadSlim(engine);
|
||||
}).then(() => {
|
||||
setInit(true);
|
||||
});
|
||||
// Retarder l'initialisation des particules pour ne pas bloquer le premier rendu
|
||||
const timer = setTimeout(() => {
|
||||
initParticlesEngine(async (engine) => {
|
||||
await loadSlim(engine);
|
||||
}).then(() => {
|
||||
setInit(true);
|
||||
});
|
||||
}, 1000); // Attendre 1 seconde après le chargement initial
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
const particlesLoaded = async (container) => {
|
||||
@ -73,12 +78,12 @@ export const ParticlesBackground = () => {
|
||||
density: {
|
||||
enable: true,
|
||||
},
|
||||
value: 70,
|
||||
value: 70, // Réduit de 70 à 30 pour de meilleures performances
|
||||
},
|
||||
opacity: {
|
||||
value: { min: 0.1, max: theme === "dark" ? 0.5 : 0.6 },
|
||||
animation: {
|
||||
enable: true,
|
||||
enable: false, // Désactiver l'animation d'opacité pour meilleures performances
|
||||
speed: 3,
|
||||
sync: false,
|
||||
},
|
||||
@ -89,14 +94,14 @@ export const ParticlesBackground = () => {
|
||||
size: {
|
||||
value: { min: 0.1, max: 5 },
|
||||
animation: {
|
||||
enable: true,
|
||||
enable: false, // Désactiver l'animation de taille pour meilleures performances
|
||||
speed: 20,
|
||||
sync: false,
|
||||
},
|
||||
},
|
||||
twinkle: {
|
||||
lines: {
|
||||
enable: true,
|
||||
enable: false, // Désactiver le scintillement pour meilleures performances
|
||||
frequency: 0.005,
|
||||
opacity: 1,
|
||||
color: {
|
||||
@ -104,7 +109,7 @@ export const ParticlesBackground = () => {
|
||||
}
|
||||
},
|
||||
particles: {
|
||||
enable: true,
|
||||
enable: false, // Désactiver le scintillement pour meilleures performances
|
||||
frequency: 0.05,
|
||||
opacity: 1,
|
||||
color: {
|
||||
|
||||
@ -1,16 +1,18 @@
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, lazy, Suspense } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { Header } from "@/components/Header";
|
||||
import { Footer } from "@/components/Footer";
|
||||
import { ScrollProgress } from "@/components/ScrollProgress";
|
||||
import { CookieBanner } from "@/components/CookieBanner";
|
||||
import { HeroSection } from "@/components/sections/HeroSection";
|
||||
import { ProjectsSection } from "@/components/sections/ProjectsSection";
|
||||
import { SkillsSection } from "@/components/sections/SkillsSection";
|
||||
import { ContactSection } from "@/components/sections/ContactSection";
|
||||
import { LanguageProvider } from "@/contexts/LanguageContext";
|
||||
import { CookieBannerProvider } from "@/contexts/CookieBannerContext";
|
||||
|
||||
// Lazy load des sections non critiques
|
||||
const ProjectsSection = lazy(() => import("@/components/sections/ProjectsSection").then(module => ({ default: module.ProjectsSection })));
|
||||
const SkillsSection = lazy(() => import("@/components/sections/SkillsSection").then(module => ({ default: module.SkillsSection })));
|
||||
const ContactSection = lazy(() => import("@/components/sections/ContactSection").then(module => ({ default: module.ContactSection })));
|
||||
|
||||
const Index = () => {
|
||||
const location = useLocation();
|
||||
|
||||
@ -34,9 +36,15 @@ const Index = () => {
|
||||
<Header />
|
||||
<main>
|
||||
<HeroSection />
|
||||
<ProjectsSection />
|
||||
<SkillsSection />
|
||||
<ContactSection />
|
||||
<Suspense fallback={<div className="py-20 md:py-32" />}>
|
||||
<ProjectsSection />
|
||||
</Suspense>
|
||||
<Suspense fallback={<div className="py-20 md:py-32" />}>
|
||||
<SkillsSection />
|
||||
</Suspense>
|
||||
<Suspense fallback={<div className="py-20 md:py-32" />}>
|
||||
<ContactSection />
|
||||
</Suspense>
|
||||
</main>
|
||||
<Footer />
|
||||
<CookieBanner />
|
||||
|
||||
@ -103,9 +103,40 @@ const ProjectPageContent = () => {
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-6">
|
||||
{t("project.description") || "Description"}
|
||||
</h2>
|
||||
<p className="text-lg text-muted-foreground leading-relaxed mb-12">
|
||||
<p className="text-lg text-muted-foreground leading-relaxed mb-6">
|
||||
{project.detailedDescription[language]}
|
||||
</p>
|
||||
|
||||
{/* Liens intégrés dans la description */}
|
||||
{(project.githubUrl || project.demoUrl) && (
|
||||
<div className="flex flex-wrap gap-3 mb-12">
|
||||
{project.githubUrl && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
asChild
|
||||
className="gap-2"
|
||||
>
|
||||
<a href={project.githubUrl} target="_blank" rel="noopener noreferrer">
|
||||
<Github className="w-4 h-4" />
|
||||
{t("project.viewGithub") || "View on GitHub"}
|
||||
</a>
|
||||
</Button>
|
||||
)}
|
||||
{project.demoUrl && (
|
||||
<Button
|
||||
size="sm"
|
||||
asChild
|
||||
className="gap-2"
|
||||
>
|
||||
<a href={project.demoUrl} target="_blank" rel="noopener noreferrer">
|
||||
<ExternalLink className="w-4 h-4" />
|
||||
{t("project.viewDemo") || "View Live Demo"}
|
||||
</a>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</motion.div>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
@ -198,54 +229,8 @@ const ProjectPageContent = () => {
|
||||
</section>
|
||||
)}
|
||||
|
||||
{/* Links Section */}
|
||||
{(project.githubUrl || project.demoUrl) && (
|
||||
<section className="py-20 bg-muted/30">
|
||||
<div className="container mx-auto px-4">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="max-w-4xl mx-auto text-center"
|
||||
>
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-8">
|
||||
{t("project.links") || "Project Links"}
|
||||
</h2>
|
||||
<div className="flex flex-wrap gap-4 justify-center">
|
||||
{project.githubUrl && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="lg"
|
||||
asChild
|
||||
className="gap-2"
|
||||
>
|
||||
<a href={project.githubUrl} target="_blank" rel="noopener noreferrer">
|
||||
<Github className="w-5 h-5" />
|
||||
{t("project.viewGithub") || "View on GitHub"}
|
||||
</a>
|
||||
</Button>
|
||||
)}
|
||||
{project.demoUrl && (
|
||||
<Button
|
||||
size="lg"
|
||||
asChild
|
||||
className="gap-2"
|
||||
>
|
||||
<a href={project.demoUrl} target="_blank" rel="noopener noreferrer">
|
||||
<ExternalLink className="w-5 h-5" />
|
||||
{t("project.viewDemo") || "View Live Demo"}
|
||||
</a>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="py-20">
|
||||
<section className="py-20 bg-muted/30">
|
||||
<div className="container mx-auto px-4">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user