Compare commits

..

10 Commits

Author SHA1 Message Date
Mr¤KayJayDee
2378febe6f add ads.txtx 2025-07-25 23:04:31 +02:00
Mr¤KayJayDee
c79b818302 feat(analytics): intégration de Google Analytics et mise à jour du sitemap
- Remplacement de Google Tag Manager par Google Analytics (gtag.js) dans index.html pour le suivi des performances.
- Ajout d'une fonction de suivi des pages vues dans le routeur pour améliorer l'analyse des données.
- Mise à jour des dates de dernière modification dans sitemap.xml pour refléter la date actuelle.
- Révision des règles dans robots.txt pour un meilleur contrôle d'indexation.
2025-07-07 18:06:43 +02:00
Mr¤KayJayDee
a8509416ae fix(header): suppression de la route de formation dans le menu de navigation
- Commenté la route de formation dans le composant AppHeader.vue pour éviter son affichage.
- Aucune autre modification apportée au fichier.
2025-07-05 22:47:45 +02:00
Mr¤KayJayDee
481c753371 feat(seo): mise à jour des métadonnées et intégration de Google Tag Manager
- Ajout du script Google Tag Manager dans index.html pour le suivi des performances.
- Mise à jour des couleurs de thème dans index.html et site.webmanifest pour un meilleur contraste.
- Révision des dates de dernière modification dans sitemap.xml pour refléter la date actuelle.
- Changement des priorités et des URLs des projets dans sitemap.xml pour une meilleure organisation.
- Modification de la gestion du thème par défaut dans useTheme.ts pour utiliser le mode sombre.
- Mise à jour des paramètres de localisation dans site.ts et index.ts pour un meilleur support multilingue.
2025-07-05 22:20:43 +02:00
Mr¤KayJayDee
6234e02fa7 feat(formation): ajout de la page de formation et des animations d'entrée
- Création d'une nouvelle page de formation avec des sections pour les plans tarifaires et les FAQ.
- Ajout de nouvelles animations CSS pour les entrées de page et les éléments.
- Mise à jour des traductions pour inclure la section de formation en anglais et en français.
- Intégration de la nouvelle route pour accéder à la page de formation.
- Amélioration des styles CSS pour la page de formation.
2025-06-26 10:06:19 +02:00
Mr¤KayJayDee
b0e5a81a84 fix(techstack): suppression du commentaire TODO pour l'image Ruby
- Retrait du commentaire indiquant l'ajout futur de l'image Ruby dans le fichier techstack.ts.
2025-06-26 00:19:10 +02:00
Mr¤KayJayDee
992dc45f29 feat(locales): mise à jour des traductions pour les sections des fonctionnalités
- Suppression de certaines fonctionnalités dans les traductions anglaises et françaises.
- Maintien de l'hébergement VPS premium offert pendant 3 mois dans les deux langues.
- Conservation de la fonctionnalité de multi-serveurs pour le plugin Minecraft dans les deux langues.
- Préservation de la sécurité maximale avec 2FA et encryption dans les traductions du bot Telegram.
- Maintien de la fonctionnalité e-commerce prête dans les traductions pour le développement de sites web.
2025-06-26 00:04:00 +02:00
Mr¤KayJayDee
542c468eb3 feat(portfolio): mise à jour du site avec de nouvelles sections et améliorations SEO
- Révision des métadonnées dans index.html pour un meilleur référencement.
- Ajout de nouvelles sections : FAQ, Témoignages, Services, et CTA.
- Intégration de données structurées pour les FAQ et les témoignages.
- Amélioration du fichier robots.txt pour un meilleur contrôle d'indexation.
- Mise à jour du sitemap.xml avec de nouvelles URLs.
- Ajout de nouveaux composants Vue.js pour les sections de témoignages et de services.
- Amélioration des styles CSS pour une meilleure présentation des sections.
- Ajout de la gestion des dates et des témoignages dans le composant testimonials.
2025-06-25 23:25:51 +02:00
Mr¤KayJayDee
af1f47dbf3 feat(fiverr): amélioration des données structurées pour les services Fiverr 2025-06-25 19:18:54 +02:00
Mr¤KayJayDee
0d468841d3 feat(fiverr): mise à jour des métadonnées de notation
- Ajout de l'élément 'itemReviewed' pour spécifier le type de service et son nom.
- Modification de la valeur 'reviewCount' pour refléter le nombre de critiques à 50.
2025-06-25 18:35:09 +02:00
46 changed files with 3535 additions and 537 deletions

View File

@@ -5,35 +5,55 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-CDVVNFY6MV"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', 'G-CDVVNFY6MV');
</script>
<!-- Google AdSense -->
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5219367964457248"
crossorigin="anonymous"></script>
<!-- Primary Meta Tags -->
<title>Killian - Full Stack Developer | Vue.js, React, Node.js Expert</title>
<meta name="title" content="Killian - Full Stack Developer | Vue.js, React, Node.js Expert">
<title>Full Stack Developer Freelance Vue.js React Node.js | Killian Dalcin</title>
<meta name="title" content="Full Stack Developer Freelance Vue.js React Node.js | Killian Dalcin">
<meta name="description"
content="Full Stack Developer specializing in Vue.js, React, Node.js. Expert in Discord bots, web apps & custom solutions. Available for freelance.">
content="Expert Full Stack Developer freelance specialized in Vue.js, React and Node.js. ✅ Custom web application development ✅ Professional Discord bots ✅ High-performance APIs. Free quote within 24h.">
<meta name="keywords"
content="full stack developer, web developer, Vue.js developer, React developer, Node.js developer, JavaScript developer, Discord bot developer, freelance developer, web development services, custom software solutions">
<meta name="author" content="Killian">
<meta name="robots" content="index, follow">
content="full stack developer freelance, vue.js developer freelance, react developer freelance, node.js developer freelance, custom discord bot development, enterprise web application development, javascript typescript expert, rest api graphql developer, freelance web developer france, saas mvp startup development">
<meta name="author" content="Killian Dalcin">
<meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1">
<meta name="language" content="English">
<meta name="revisit-after" content="7 days">
<meta name="revisit-after" content="3 days">
<meta name="geo.region" content="FR">
<meta name="geo.placename" content="France">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://killiandalcin.fr">
<meta property="og:title" content="Killian - Full Stack Developer | Vue.js, React, Node.js Expert">
<meta property="og:title" content="Full Stack Developer Freelance Vue.js React Node.js | Killian Dalcin">
<meta property="og:description"
content="Professional Full Stack Developer specializing in modern web development. Expert in Discord bots, web applications, and custom solutions.">
<meta property="og:image" content="/portfolio-preview.webp">
content="Need an expert Full Stack Developer? I create custom web applications, Discord bots and high-performance APIs. Modern technologies, clean code, fast delivery. Free consultation.">
<meta property="og:image" content="https://killiandalcin.fr/portfolio-preview.webp">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Killian Portfolio">
<meta property="og:locale:alternate" content="fr_FR">
<meta property="og:site_name" content="Killian Dalcin - Full Stack Developer">
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:url" content="https://killiandalcin.fr">
<meta property="twitter:title" content="Killian - Full Stack Developer | Vue.js, React, Node.js Expert">
<meta property="twitter:title" content="Full Stack Developer Freelance Vue.js React Node.js | Killian Dalcin">
<meta property="twitter:description"
content="Professional Full Stack Developer specializing in modern web development. Expert in Discord bots, web applications, and custom solutions.">
<meta property="twitter:image" content="/portfolio-preview.webp">
content="Expert Full Stack Developer freelance. Custom web application development, Discord bots, high-performance APIs. Vue.js, React, Node.js. Free quote within 24h.">
<meta property="twitter:image" content="https://killiandalcin.fr/portfolio-preview.webp">
<meta property="twitter:creator" content="@killiandalcin">
<!-- Canonical URL -->
<link rel="canonical" href="https://killiandalcin.fr">
@@ -48,31 +68,172 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- Theme Color -->
<meta name="theme-color" content="#2563eb">
<meta name="theme-color" content="#111827" media="(prefers-color-scheme: dark)">
<meta name="theme-color" content="#2563eb" media="(prefers-color-scheme: light)">
<!-- Structured Data -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": "Killian",
"jobTitle": "Full Stack Developer",
"description": "Professional Full Stack Developer specializing in Vue.js, React, Node.js, and modern web technologies",
"@type": "ProfessionalService",
"@id": "https://killiandalcin.fr/#organization",
"name": "Killian Dalcin - Full Stack Developer Freelance",
"alternateName": "Killian Dev",
"url": "https://killiandalcin.fr",
"sameAs": [
"https://github.com/killian",
"https://linkedin.com/in/killian",
"https://www.fiverr.com/users/mr_kayjaydee"
],
"knowsAbout": ["Vue.js", "React", "Node.js", "JavaScript", "TypeScript", "Web Development", "Discord Bot Development", "API Development"],
"offers": {
"@type": "Offer",
"itemOffered": {
"@type": "Service",
"name": "Web Development Services",
"description": "Custom web development, Discord bots, and software solutions"
"logo": "https://killiandalcin.fr/logo.webp",
"image": "https://killiandalcin.fr/portfolio-preview.webp",
"description": "Full Stack Developer freelance expert in Vue.js, React and Node.js. Specialized in custom web application development, professional Discord bots and high-performance APIs.",
"priceRange": "€€€",
"telephone": "+33-649-193-816",
"email": "contact@killiandalcin.fr",
"address": {
"@type": "PostalAddress",
"addressCountry": "FR",
"addressRegion": "France"
},
"openingHoursSpecification": {
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"opens": "09:00",
"closes": "18:00"
},
"founder": {
"@type": "Person",
"name": "Killian Dalcin",
"jobTitle": "Senior Full Stack Developer",
"alumniOf": "Computer Engineering School",
"knowsAbout": ["Vue.js", "React", "Node.js", "TypeScript", "JavaScript", "MongoDB", "PostgreSQL", "Docker", "REST API", "GraphQL", "Discord.js", "Web Development", "Software Architecture"],
"sameAs": [
"https://github.com/killiandalcin",
"https://linkedin.com/in/killian-dalcin",
"https://www.fiverr.com/users/mr_kayjaydee",
"https://twitter.com/killiandalcin"
]
},
"hasOfferCatalog": {
"@type": "OfferCatalog",
"name": "Web Development Services",
"itemListElement": [
{
"@type": "Offer",
"itemOffered": {
"@type": "Service",
"name": "Vue.js/React Web Application Development",
"description": "Creation of modern and high-performance web applications with Vue.js or React. Responsive user interface, SEO optimization, scalable architecture."
}
},
{
"@type": "Offer",
"itemOffered": {
"@type": "Service",
"name": "Node.js Backend Development & API",
"description": "Design of robust REST and GraphQL APIs with Node.js. Microservices architecture, secure authentication, optimal performance."
}
},
{
"@type": "Offer",
"itemOffered": {
"@type": "Service",
"name": "Custom Discord Bot Development",
"description": "Development of professional Discord bots with advanced features. Moderation, music, games, API integrations, web dashboard."
}
},
{
"@type": "Offer",
"itemOffered": {
"@type": "Service",
"name": "Maintenance & Technical Support",
"description": "Continuous maintenance, security updates and technical support for your applications. 24/7 monitoring and rapid interventions."
}
}
]
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "5",
"bestRating": "5",
"worstRating": "1",
"ratingCount": "47",
"reviewCount": "47"
},
"review": [
{
"@type": "Review",
"reviewRating": {
"@type": "Rating",
"ratingValue": "5",
"bestRating": "5"
},
"author": {
"@type": "Person",
"name": "Marie L."
},
"reviewBody": "Excellent developer! Vue.js application delivered on time with exceptional code quality. I highly recommend."
},
{
"@type": "Review",
"reviewRating": {
"@type": "Rating",
"ratingValue": "5",
"bestRating": "5"
},
"author": {
"@type": "Person",
"name": "Thomas B."
},
"reviewBody": "Discord bot working perfectly with all requested features. Responsive and professional support. Thank you!"
}
}
]
}
</script>
<!-- Breadcrumb Schema -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://killiandalcin.fr"
}
]
}
</script>
<!-- FAQ Schema -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "What are your rates for custom web development?",
"acceptedAnswer": {
"@type": "Answer",
"text": "My rates vary according to project complexity. A simple web application starts from €2000, while a complex platform can go up to €15000+. I always provide a detailed free quote within 24h after analyzing your needs."
}
},
{
"@type": "Question",
"name": "How long does it take to develop a Vue.js application?",
"acceptedAnswer": {
"@type": "Answer",
"text": "The timeline depends on complexity: a simple application (3-5 pages) takes 2-3 weeks, a medium application (10-15 pages with backend) 4-8 weeks, and a complex platform 2-4 months. I always provide a detailed schedule."
}
},
{
"@type": "Question",
"name": "Do you offer maintenance after delivery?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes, I offer monthly maintenance contracts including: security updates, bug fixes, small evolutions, 24/7 monitoring and technical support. Rates start from €300/month depending on your needs."
}
}
]
}
</script>
<script defer src="https://umami.killiandalcin.fr/script.js"

1
public/ads.txt Normal file
View File

@@ -0,0 +1 @@
google.com, pub-5219367964457248, DIRECT, f08c47fec0942fa0

View File

@@ -1,33 +1,5 @@
# Robots.txt for Killian Portfolio
# https://killiandalcin.fr
# Allow all crawlers
User-agent: *
Allow: /
Disallow: /api/
Disallow: /admin/
Disallow: /.git/
Disallow: /node_modules/
# Sitemap location
Sitemap: https://killiandalcin.fr/sitemap.xml
# Crawl-delay for respectful crawling
Crawl-delay: 1
# Special rules for major search engines
User-agent: Googlebot
Allow: /
Crawl-delay: 0
User-agent: Bingbot
Allow: /
Crawl-delay: 0
User-agent: Slurp
Allow: /
Crawl-delay: 1
User-agent: DuckDuckBot
Allow: /
Crawl-delay: 1
Disallow: /api/
Disallow: /*?*
Sitemap: https://killiandalcin.fr/sitemap.xml

View File

@@ -4,8 +4,8 @@
"description": "Professional Full Stack Developer specializing in Vue.js, React, Node.js. Expert in Discord bots, web applications, and custom software solutions.",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#2563eb",
"background_color": "#111827",
"theme_color": "#111827",
"orientation": "portrait-primary",
"icons": [
{

View File

@@ -3,87 +3,84 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<!-- Homepage -->
<!-- Home Page -->
<url>
<loc>https://killiandalcin.fr/</loc>
<lastmod>2025-06-22T00:00:00+00:00</lastmod>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
<!-- Projects Page -->
<url>
<loc>https://killiandalcin.fr/projects</loc>
<lastmod>2025-06-22T00:00:00+00:00</lastmod>
<changefreq>weekly</changefreq>
<priority>0.9</priority>
</url>
<!-- About Page -->
<url>
<loc>https://killiandalcin.fr/about</loc>
<lastmod>2025-06-22T00:00:00+00:00</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<!-- Contact Page -->
<url>
<loc>https://killiandalcin.fr/contact</loc>
<lastmod>2025-06-22T00:00:00+00:00</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
<lastmod>2025-07-07</lastmod>
</url>
<!-- Fiverr Services Page -->
<url>
<loc>https://killiandalcin.fr/fiverr</loc>
<lastmod>2025-06-22T00:00:00+00:00</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<lastmod>2025-07-07</lastmod>
</url>
<!-- Individual Project Pages -->
<!-- Projects Portfolio Page -->
<url>
<loc>https://killiandalcin.fr/projects</loc>
<lastmod>2025-07-07</lastmod>
</url>
<!-- Contact Page -->
<url>
<loc>https://killiandalcin.fr/contact</loc>
<lastmod>2025-07-07</lastmod>
</url>
<!-- About Page -->
<url>
<loc>https://killiandalcin.fr/about</loc>
<lastmod>2025-07-07</lastmod>
</url>
<!-- Formation/Training Page -->
<url>
<loc>https://killiandalcin.fr/formation</loc>
<lastmod>2025-07-07</lastmod>
</url>
<!-- Dynamic Project Detail Pages -->
<!-- Virtual Tour Project -->
<url>
<loc>https://killiandalcin.fr/project/virtual-tour</loc>
<lastmod>2025-06-22T00:00:00+00:00</lastmod>
<changefreq>monthly</changefreq>
<priority>0.7</priority>
<lastmod>2025-07-07</lastmod>
</url>
<!-- Xinko Discord Bot Project -->
<url>
<loc>https://killiandalcin.fr/project/xinko</loc>
<lastmod>2025-06-22T00:00:00+00:00</lastmod>
<changefreq>monthly</changefreq>
<priority>0.7</priority>
<lastmod>2025-07-07</lastmod>
</url>
<!-- Image Manipulation NPM Package -->
<url>
<loc>https://killiandalcin.fr/project/image-manipulation</loc>
<lastmod>2025-06-22T00:00:00+00:00</lastmod>
<changefreq>monthly</changefreq>
<priority>0.7</priority>
<lastmod>2025-07-07</lastmod>
</url>
<!-- Flowboard Project Management App -->
<url>
<loc>https://killiandalcin.fr/project/flowboard</loc>
<lastmod>2025-07-07</lastmod>
</url>
<!-- Primate Web Admin Project -->
<url>
<loc>https://killiandalcin.fr/project/primate-web-admin</loc>
<lastmod>2025-06-22T00:00:00+00:00</lastmod>
<changefreq>monthly</changefreq>
<priority>0.7</priority>
<lastmod>2025-07-07</lastmod>
</url>
<!-- Instagram Bot Project -->
<url>
<loc>https://killiandalcin.fr/project/instagram-bot</loc>
<lastmod>2025-06-22T00:00:00+00:00</lastmod>
<changefreq>monthly</changefreq>
<priority>0.7</priority>
<lastmod>2025-07-07</lastmod>
</url>
<!-- Crowdin Status Bot Project -->
<url>
<loc>https://killiandalcin.fr/project/crowdin-status-bot</loc>
<lastmod>2025-06-22T00:00:00+00:00</lastmod>
<changefreq>monthly</changefreq>
<priority>0.7</priority>
<lastmod>2025-07-07</lastmod>
</url>
</urlset>

View File

@@ -718,6 +718,18 @@ a:hover {
}
/* Animations */
/* Page Entrance Animations */
@keyframes pageEnter {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeInUp {
from {
opacity: 0;
@@ -749,16 +761,57 @@ a:hover {
}
}
@keyframes slideInLeft {
from {
opacity: 0;
transform: translateX(-30px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes scaleIn {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
/* Page Animation Classes */
.page-enter {
animation: pageEnter 0.6s ease-out;
}
/* Enhanced Load Animation Classes */
.animate-fade-in-up {
animation: fadeInUp 0.6s ease-out;
animation: fadeInUp 0.6s ease-out forwards;
opacity: 0;
}
.animate-fade-in {
animation: fadeIn 0.6s ease-out;
animation: fadeIn 0.6s ease-out forwards;
opacity: 0;
}
.animate-slide-in-right {
animation: slideInRight 0.6s ease-out;
animation: slideInRight 0.6s ease-out forwards;
opacity: 0;
}
.animate-slide-in-left {
animation: slideInLeft 0.6s ease-out forwards;
opacity: 0;
}
.animate-scale-in {
animation: scaleIn 0.6s ease-out forwards;
opacity: 0;
}
/* Mobile Menu */

View File

@@ -0,0 +1,70 @@
<template>
<section class="faq-section">
<div class="container">
<div class="faq-header text-center mb-2xl">
<h2 class="section-title">{{ title }}</h2>
<p class="section-subtitle">{{ subtitle }}</p>
</div>
<div class="faq-grid">
<div v-for="(faq, index) in faqs" :key="index" class="faq-item" :class="{ 'active': activeIndex === index }">
<button class="faq-question" @click="toggleFAQ(index)" :aria-expanded="activeIndex === index">
<span class="question-text">{{ faq.question }}</span>
<svg class="faq-icon" :class="{ 'rotated': activeIndex === index }" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7">
</path>
</svg>
</button>
<div class="faq-answer" :class="{ 'open': activeIndex === index }">
<div class="answer-content">
<p v-html="faq.answer"></p>
<div v-if="faq.features" class="faq-features">
<h4>{{ t('faq.keyPoints') }}</h4>
<ul>
<li v-for="feature in faq.features" :key="feature">{{ feature }}</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useI18n } from '@/composables/useI18n'
const { t } = useI18n()
interface FAQ {
question: string
answer: string
features?: string[]
}
interface Props {
title: string
subtitle: string
faqs: FAQ[]
ctaTitle: string
ctaSubtitle: string
ctaText: string
ctaLink: string
}
defineProps<Props>()
const activeIndex = ref<number | null>(null)
const toggleFAQ = (index: number) => {
activeIndex.value = activeIndex.value === index ? null : index
}
</script>
<style scoped>
@import './styles/ServiceFAQ.css';
</style>

View File

@@ -0,0 +1,76 @@
<template>
<section class="testimonials-section">
<div class="container">
<!-- Header -->
<div class="testimonials-header">
<h2 class="section-title">{{ title }}</h2>
<p class="section-subtitle">{{ subtitle }}</p>
<!-- Stats -->
<TestimonialsStats :stats="stats" :labels="statsLabels" />
</div>
<!-- Testimonials Grid -->
<div class="testimonials-grid">
<TestimonialCard v-for="(testimonial, index) in testimonials" :key="index" :testimonial="testimonial"
:class="{ 'featured': testimonial.featured }" />
</div>
<!-- CTA -->
<TestimonialsCTA :title="ctaTitle" :subtitle="ctaSubtitle" :text="ctaText" :link="ctaLink"
:reviews-link="reviewsLink" :reviews-text="reviewsText" />
</div>
</section>
</template>
<script setup lang="ts">
import TestimonialsStats from '@/components/testimonials/TestimonialsStats.vue'
import TestimonialCard from '@/components/testimonials/TestimonialCard.vue'
import TestimonialsCTA from '@/components/testimonials/TestimonialsCTA.vue'
interface Testimonial {
name: string
role: string
company: string
avatar: string
rating: number
content: string
date: string
platform: string
featured?: boolean
project_type: string
results?: string[]
}
interface Stats {
totalReviews: number
averageRating: number
projectsCompleted: number
}
interface StatsLabels {
clients: string
rating: string
projects: string
}
interface Props {
title: string
subtitle: string
testimonials: Testimonial[]
stats: Stats
statsLabels: StatsLabels
ctaTitle: string
ctaSubtitle: string
ctaText: string
ctaLink: string
reviewsLink: string
reviewsText: string
}
defineProps<Props>()
</script>
<style scoped>
@import '@/components/styles/TestimonialsSection.css';
</style>

View File

@@ -14,6 +14,7 @@ const navigation = computed(() => [
{ name: t('nav.projects'), path: '/projects' },
{ name: t('nav.about'), path: '/about' },
{ name: t('nav.contact'), path: '/contact' },
// { name: t('nav.formation'), path: '/formation' },
{ name: t('nav.fiverr'), path: '/fiverr' },
])

View File

@@ -0,0 +1,16 @@
<template>
<section class="section">
<div class="container">
<SectionCTA :question="t('home.cta2.title')" :description="t('home.cta2.subtitle')"
:primary-text="t('home.cta2.startProject')" primary-link="/contact" :secondary-text="t('home.cta2.learnMore')"
secondary-link="/about" />
</div>
</section>
</template>
<script setup lang="ts">
import { useI18n } from '@/composables/useI18n'
import SectionCTA from '@/components/shared/SectionCTA.vue'
const { t } = useI18n()
</script>

View File

@@ -0,0 +1,48 @@
<template>
<section class="section">
<div class="container">
<div class="text-center mb-2xl">
<h2 class="mb-lg">{{ t('home.featuredProjects.title') }}</h2>
<p class="text-xl text-secondary max-w-2xl mx-auto">
{{ t('home.featuredProjects.subtitle') }}
</p>
</div>
<div class="projects-grid">
<ProjectCard v-for="project in featuredProjects" :key="project.id" :project="project"
class="animate-fade-in-up" />
</div>
<div class="text-center">
<CTAButtons layout="stack">
<RouterLink to="/projects" class="btn btn-secondary">
{{ t('home.featuredProjects.viewAll') }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
</svg>
</RouterLink>
</CTAButtons>
</div>
</div>
</section>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useI18n } from '@/composables/useI18n'
import { useProjects } from '@/composables/useProjects'
import ProjectCard from '@/components/ProjectCard.vue'
import CTAButtons from '@/components/shared/CTAButtons.vue'
const { t } = useI18n()
const { projects } = useProjects()
// Featured projects
const featuredProjects = computed(() => {
return projects.value.filter(project => project.featured).slice(0, 3)
})
</script>
<style scoped>
@import '@/components/styles/FeaturedProjectsSection.css';
</style>

View File

@@ -0,0 +1,46 @@
<template>
<section class="hero">
<div class="container">
<div class="hero-content animate-fade-in-up">
<h1 class="hero-title">
{{ t('home.title') }}
</h1>
<p class="hero-subtitle">
{{ t('home.subtitle') }}
</p>
<CTAButtons layout="columns">
<RouterLink to="/projects" class="btn btn-primary btn-lg">
{{ t('home.cta.viewProjects') }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6">
</path>
</svg>
</RouterLink>
<RouterLink to="/fiverr" class="btn btn-secondary btn-lg">
{{ t('nav.fiverr') }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z">
</path>
</svg>
</RouterLink>
<RouterLink to="/contact" class="btn btn-secondary btn-lg">
{{ t('home.cta.contactMe') }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z">
</path>
</svg>
</RouterLink>
</CTAButtons>
</div>
</div>
</section>
</template>
<script setup lang="ts">
import { useI18n } from '@/composables/useI18n'
import CTAButtons from '@/components/shared/CTAButtons.vue'
const { t } = useI18n()
</script>

View File

@@ -0,0 +1,70 @@
<template>
<section class="services-section">
<div class="container">
<div class="text-center mb-2xl">
<h2 class="mb-lg">{{ t('home.services.title') }}</h2>
<p class="text-xl text-secondary max-w-2xl mx-auto">
{{ t('home.services.subtitle') }}
</p>
</div>
<div class="services-grid">
<div v-for="(service, index) in services" :key="index" class="card animate-fade-in-up"
:style="{ 'animation-delay': `${index * 0.1}s` }">
<div class="card-body">
<div class="flex items-start">
<div class="service-icon" :style="{ background: service.color, color: 'var(--text-inverse)' }">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" :d="service.icon"></path>
</svg>
</div>
<div>
<h3 class="text-xl font-bold mb-md">{{ service.title }}</h3>
<p class="text-secondary">{{ service.description }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useI18n } from '@/composables/useI18n'
const { t } = useI18n()
// Services data
const services = computed(() => [
{
icon: 'M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z',
color: 'var(--color-primary)',
title: t('home.services.webDev.title'),
description: t('home.services.webDev.description')
},
{
icon: 'M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z',
color: 'var(--color-secondary)',
title: t('home.services.mobileApps.title'),
description: t('home.services.mobileApps.description')
},
{
icon: 'M13 10V3L4 14h7v7l9-11h-7z',
color: 'var(--color-success)',
title: t('home.services.optimization.title'),
description: t('home.services.optimization.description')
},
{
icon: 'M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z',
color: 'var(--color-warning)',
title: t('home.services.maintenance.title'),
description: t('home.services.maintenance.description')
}
])
</script>
<style scoped>
@import '@/components/styles/ServicesSection.css';
</style>

View File

@@ -0,0 +1,36 @@
<template>
<div class="cta-buttons-container">
<div class="cta-buttons" :class="layoutClass">
<slot></slot>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
interface Props {
layout?: 'columns' | 'row' | 'stack'
maxButtons?: number
}
const props = withDefaults(defineProps<Props>(), {
layout: 'columns',
maxButtons: 3
})
const layoutClass = computed(() => {
switch (props.layout) {
case 'row':
return 'cta-buttons--row'
case 'stack':
return 'cta-buttons--stack'
default:
return 'cta-buttons--columns'
}
})
</script>
<style scoped>
@import '@/components/styles/CTAButtons.css';
</style>

View File

@@ -0,0 +1,58 @@
<template>
<div class="section-cta">
<div class="cta-content">
<h3 class="cta-question">{{ question }}</h3>
<p class="cta-description">{{ description }}</p>
<CTAButtons layout="columns">
<RouterLink :to="primaryLink" class="btn btn-primary btn-lg">
{{ primaryText }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z">
</path>
</svg>
</RouterLink>
<RouterLink v-if="secondaryText && secondaryLink" :to="secondaryLink" class="btn btn-secondary btn-lg">
{{ secondaryText }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6">
</path>
</svg>
</RouterLink>
<a v-if="externalText && externalLink" :href="externalLink" class="btn btn-secondary btn-lg" target="_blank"
rel="noopener">
{{ externalText }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14">
</path>
</svg>
</a>
</CTAButtons>
</div>
</div>
</template>
<script setup lang="ts">
import CTAButtons from '@/components/shared/CTAButtons.vue'
interface Props {
question: string
description: string
primaryText: string
primaryLink: string
secondaryText?: string
secondaryLink?: string
externalText?: string
externalLink?: string
}
defineProps<Props>()
</script>
<style scoped>
@import '@/components/styles/SectionCTA.css';
</style>

View File

@@ -0,0 +1,78 @@
/* CTAButtons Styles */
.cta-buttons-container {
display: flex;
justify-content: center;
width: 100%;
}
.cta-buttons {
display: flex;
gap: 1rem;
justify-content: center;
align-items: center;
max-width: 900px;
width: 100%;
}
/* Column Layout (Default) */
.cta-buttons--columns {
flex-direction: column;
}
@media (min-width: 640px) {
.cta-buttons--columns {
flex-direction: row;
flex-wrap: wrap;
}
}
@media (min-width: 768px) {
.cta-buttons--columns {
flex-direction: row;
flex-wrap: nowrap;
}
}
/* Row Layout */
.cta-buttons--row {
flex-direction: column;
}
@media (min-width: 640px) {
.cta-buttons--row {
flex-direction: row;
flex-wrap: wrap;
}
}
/* Stack Layout */
.cta-buttons--stack {
flex-direction: column;
}
/* Button Styling */
.cta-buttons :deep(.btn) {
white-space: nowrap;
min-width: fit-content;
flex: 0 0 auto;
text-align: center;
}
@media (min-width: 768px) {
.cta-buttons--columns :deep(.btn) {
flex: 1 1 auto;
max-width: 280px;
}
.cta-buttons--row :deep(.btn) {
flex: 0 1 auto;
max-width: 250px;
}
}
@media (max-width: 639px) {
.cta-buttons :deep(.btn) {
width: 100%;
max-width: 320px;
}
}

View File

@@ -0,0 +1,21 @@
/* FeaturedProjectsSection Styles */
.projects-grid {
display: grid;
grid-template-columns: 1fr;
gap: 2rem;
margin-bottom: 3rem;
}
@media (min-width: 768px) {
.projects-grid {
grid-template-columns: repeat(2, 1fr);
gap: 2rem;
}
}
@media (min-width: 1024px) {
.projects-grid {
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
}
}

View File

@@ -0,0 +1,65 @@
/* SectionCTA Styles */
.section-cta {
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
border-radius: 20px;
padding: 48px 32px;
text-align: center;
margin: 64px 0;
border: 1px solid #e2e8f0;
transition: all 0.3s ease;
}
.section-cta:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
}
.cta-content {
max-width: 600px;
margin: 0 auto;
}
.cta-question {
font-size: 1.75rem;
font-weight: 700;
color: #1e293b;
margin-bottom: 16px;
line-height: 1.3;
}
.cta-description {
font-size: 1.125rem;
color: #64748b;
margin-bottom: 32px;
line-height: 1.6;
}
/* Mobile Responsive */
@media (max-width: 768px) {
.section-cta {
padding: 32px 24px;
margin: 48px 0;
}
.cta-question {
font-size: 1.5rem;
}
.cta-description {
font-size: 1rem;
}
}
/* Dark Theme */
.dark .section-cta {
background: linear-gradient(135deg, #1e293b 0%, #334155 100%);
border-color: #475569;
}
.dark .cta-question {
color: #f1f5f9;
}
.dark .cta-description {
color: #94a3b8;
}

View File

@@ -0,0 +1,366 @@
.faq-section {
padding: 4rem 0;
background: #f8fafc;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 1rem;
}
.faq-header {
margin-bottom: 3rem;
}
.section-title {
font-size: 2.5rem;
font-weight: 700;
color: #1e293b;
margin-bottom: 1rem;
}
.section-subtitle {
font-size: 1.25rem;
color: #64748b;
max-width: 600px;
margin: 0 auto;
}
.faq-grid {
max-width: 800px;
margin: 0 auto;
display: flex;
flex-direction: column;
gap: 1rem;
}
.faq-item {
background: white;
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
overflow: hidden;
transition: all 0.3s ease;
border: 1px solid #e2e8f0;
}
.faq-item:hover {
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transform: translateY(-1px);
}
.faq-item.active {
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
border-color: #3b82f6;
}
.faq-question {
width: 100%;
padding: 1.5rem;
background: none;
border: none;
text-align: left;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 1.1rem;
font-weight: 600;
color: #1e293b;
transition: color 0.3s ease;
}
.faq-question:hover {
color: #3b82f6;
}
.faq-item.active .faq-question {
color: #3b82f6;
border-bottom: 1px solid #e2e8f0;
}
.question-text {
flex: 1;
margin-right: 1rem;
}
.faq-icon {
width: 24px;
height: 24px;
transition: transform 0.3s ease;
color: #3b82f6;
flex-shrink: 0;
}
.faq-icon.rotated {
transform: rotate(180deg);
}
.faq-answer {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
}
.faq-answer.open {
max-height: 500px;
}
.answer-content {
padding: 0 1.5rem 1.5rem;
color: #64748b;
line-height: 1.6;
}
.answer-content p {
margin-bottom: 1rem;
}
.faq-features {
margin-top: 1rem;
padding: 1rem;
background: #f1f5f9;
border-radius: 8px;
border-left: 4px solid #3b82f6;
}
.faq-features h4 {
margin-bottom: 0.75rem;
color: #3b82f6;
font-size: 0.9rem;
font-weight: 600;
}
.faq-features ul {
list-style: none;
padding: 0;
margin: 0;
}
.faq-features li {
padding: 0.25rem 0;
position: relative;
padding-left: 1.5rem;
color: #475569;
}
.faq-features li::before {
content: '✅';
position: absolute;
left: 0;
top: 0.25rem;
}
.faq-cta {
background: white;
padding: 3rem;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
margin-top: 3rem;
border: 1px solid #e2e8f0;
}
.cta-title {
font-size: 1.5rem;
font-weight: 700;
margin-bottom: 1rem;
color: #1e293b;
}
.cta-subtitle {
color: #64748b;
margin-bottom: 2rem;
font-size: 1.1rem;
}
/* Dark theme support using CSS classes */
:root.dark .faq-section {
background: #0f172a;
}
:root.dark .section-title {
color: #f1f5f9;
}
:root.dark .section-subtitle {
color: #94a3b8;
}
:root.dark .faq-item {
background: #1e293b;
border-color: #334155;
}
:root.dark .faq-item.active {
border-color: #60a5fa;
}
:root.dark .faq-question {
color: #f1f5f9;
}
:root.dark .faq-question:hover {
color: #60a5fa;
}
:root.dark .faq-item.active .faq-question {
color: #60a5fa;
border-bottom-color: #334155;
}
:root.dark .faq-icon {
color: #60a5fa;
}
:root.dark .answer-content {
color: #94a3b8;
}
:root.dark .faq-features {
background: #0f172a;
border-left-color: #60a5fa;
}
:root.dark .faq-features h4 {
color: #60a5fa;
}
:root.dark .faq-features li {
color: #cbd5e1;
}
:root.dark .faq-cta {
background: #1e293b;
border-color: #334155;
}
:root.dark .cta-title {
color: #f1f5f9;
}
:root.dark .cta-subtitle {
color: #94a3b8;
}
/* Light theme explicit styles (optional but good for clarity) */
:root:not(.dark) .faq-section {
background: #f8fafc;
}
:root:not(.dark) .section-title {
color: #1e293b;
}
:root:not(.dark) .section-subtitle {
color: #64748b;
}
:root:not(.dark) .faq-item {
background: white;
border-color: #e2e8f0;
}
:root:not(.dark) .faq-item.active {
border-color: #3b82f6;
}
:root:not(.dark) .faq-question {
color: #1e293b;
}
:root:not(.dark) .faq-question:hover {
color: #3b82f6;
}
:root:not(.dark) .faq-item.active .faq-question {
color: #3b82f6;
border-bottom-color: #e2e8f0;
}
:root:not(.dark) .faq-icon {
color: #3b82f6;
}
:root:not(.dark) .answer-content {
color: #64748b;
}
:root:not(.dark) .faq-features {
background: #f1f5f9;
border-left-color: #3b82f6;
}
:root:not(.dark) .faq-features h4 {
color: #3b82f6;
}
:root:not(.dark) .faq-features li {
color: #475569;
}
:root:not(.dark) .faq-cta {
background: white;
border-color: #e2e8f0;
}
:root:not(.dark) .cta-title {
color: #1e293b;
}
:root:not(.dark) .cta-subtitle {
color: #64748b;
}
@media (max-width: 768px) {
.faq-section {
padding: 3rem 0;
}
.section-title {
font-size: 2rem;
}
.section-subtitle {
font-size: 1.1rem;
}
.faq-question {
padding: 1rem;
font-size: 1rem;
}
.answer-content {
padding: 0 1rem 1rem;
}
.faq-cta {
padding: 2rem 1rem;
margin-top: 2rem;
}
.cta-title {
font-size: 1.3rem;
}
.cta-subtitle {
font-size: 1rem;
}
}
@media (max-width: 480px) {
.container {
padding: 0 0.5rem;
}
.faq-question {
padding: 0.75rem;
}
.answer-content {
padding: 0 0.75rem 0.75rem;
}
.question-text {
margin-right: 0.5rem;
}
}

View File

@@ -0,0 +1,30 @@
/* ServicesSection Styles */
.services-grid {
display: grid;
grid-template-columns: 1fr;
gap: 2rem;
margin-bottom: 3rem;
}
@media (min-width: 768px) {
.services-grid {
grid-template-columns: repeat(2, 1fr);
gap: 2rem;
}
}
.services-section {
background: var(--bg-secondary);
padding: 5rem 0;
}
.service-icon {
width: 3rem;
height: 3rem;
border-radius: 0.75rem;
display: flex;
align-items: center;
justify-content: center;
margin-right: 1rem;
flex-shrink: 0;
}

View File

@@ -0,0 +1,330 @@
/* Testimonial Card - Clean Modern Design */
.testimonial-card {
background: white;
border-radius: 16px;
padding: 32px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
border: 1px solid #e2e8f0;
height: fit-content;
transition: all 0.2s ease;
}
.testimonial-card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
transform: translateY(-2px);
}
.testimonial-card.featured {
border: 2px solid #3b82f6;
position: relative;
}
.testimonial-card.featured::after {
content: '⭐ Featured';
position: absolute;
top: -1px;
right: -1px;
background: #3b82f6;
color: white;
padding: 4px 12px;
border-radius: 0 14px 0 12px;
font-size: 0.75rem;
font-weight: 600;
}
/* Header */
.testimonial-header {
display: flex;
align-items: flex-start;
gap: 16px;
margin-bottom: 24px;
}
.client-info {
flex: 1;
display: flex;
align-items: center;
gap: 12px;
}
.client-avatar {
width: 48px;
height: 48px;
border-radius: 50%;
overflow: hidden;
flex-shrink: 0;
}
.client-avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}
.client-details {
flex: 1;
}
.client-name {
font-size: 1rem;
font-weight: 700;
color: #1e293b;
margin-bottom: 4px;
transition: color 0.3s ease;
}
.client-role {
font-size: 0.875rem;
color: #3b82f6;
font-weight: 500;
margin-bottom: 2px;
transition: color 0.3s ease;
}
.client-company {
font-size: 0.75rem;
color: #64748b;
transition: color 0.3s ease;
}
/* Rating */
.rating {
flex-shrink: 0;
text-align: right;
}
.stars {
margin-bottom: 4px;
}
.star {
font-size: 1rem;
color: #fbbf24;
margin-left: 1px;
}
.star:not(.filled) {
color: #e5e7eb;
}
.rating-text {
font-size: 0.75rem;
color: #64748b;
font-weight: 600;
transition: color 0.3s ease;
}
/* Content */
.testimonial-content {
margin-bottom: 24px;
}
.testimonial-content blockquote {
font-size: 1rem;
line-height: 1.6;
color: #374151;
margin-bottom: 20px;
font-style: normal;
position: relative;
transition: color 0.3s ease;
}
/* Project Info */
.project-info {
margin-bottom: 16px;
}
.project-tag {
display: inline-flex;
align-items: center;
gap: 8px;
background: #eff6ff;
color: #1e40af;
padding: 6px 12px;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 600;
transition: all 0.3s ease;
}
.project-type {
opacity: 0.8;
}
/* Results */
.results {
margin-bottom: 16px;
}
.results h5 {
font-size: 0.875rem;
color: #059669;
margin-bottom: 8px;
font-weight: 600;
transition: color 0.3s ease;
}
.results ul {
list-style: none;
padding: 0;
margin: 0;
}
.results li {
font-size: 0.875rem;
color: #64748b;
padding: 2px 0;
position: relative;
padding-left: 20px;
transition: color 0.3s ease;
}
.results li::before {
content: '✓';
position: absolute;
left: 0;
color: #059669;
font-weight: bold;
transition: color 0.3s ease;
}
/* Footer */
.testimonial-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 20px;
border-top: 1px solid #f1f5f9;
gap: 12px;
transition: border-color 0.3s ease;
}
.badges {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.badge {
padding: 4px 8px;
border-radius: 12px;
font-size: 0.6875rem;
font-weight: 600;
}
.badge.featured {
background: #fef3c7;
color: #92400e;
}
.badge.platform {
background: #f1f5f9;
color: #64748b;
}
.testimonial-date {
font-size: 0.75rem;
color: #94a3b8;
transition: color 0.3s ease;
}
/* Mobile Responsive */
@media (max-width: 768px) {
.testimonial-card {
padding: 24px;
}
.testimonial-header {
flex-direction: column;
gap: 12px;
}
.client-info {
width: 100%;
}
.rating {
align-self: flex-start;
text-align: left;
}
.testimonial-footer {
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
}
/* Dark Theme */
.dark .testimonial-card {
background: #1e293b;
border-color: #334155;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
.dark .testimonial-card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
}
.dark .testimonial-card.featured {
border-color: #60a5fa;
}
.dark .testimonial-card.featured::after {
background: #60a5fa;
}
.dark .client-name {
color: #f1f5f9;
}
.dark .client-role {
color: #60a5fa;
}
.dark .client-company {
color: #94a3b8;
}
.dark .rating-text {
color: #94a3b8;
}
.dark .testimonial-content blockquote {
color: #cbd5e1;
}
.dark .project-tag {
background: #1e40af;
color: #bfdbfe;
}
.dark .results h5 {
color: #34d399;
}
.dark .results li {
color: #94a3b8;
}
.dark .results li::before {
color: #34d399;
}
.dark .testimonial-footer {
border-top-color: #334155;
}
.dark .badge.featured {
background: #78350f;
color: #fcd34d;
}
.dark .badge.platform {
background: #334155;
color: #94a3b8;
}
.dark .testimonial-date {
color: #64748b;
}

View File

@@ -0,0 +1,58 @@
/* Testimonials CTA - Clean Modern Design */
.testimonials-cta {
text-align: center;
background: white;
border-radius: 20px;
padding: 48px 32px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
border: 1px solid #e2e8f0;
margin-top: 40px;
transition: all 0.3s ease;
}
.cta-title {
font-size: 1.5rem;
font-weight: 700;
color: #1e293b;
margin-bottom: 12px;
transition: color 0.3s ease;
}
.cta-subtitle {
font-size: 1rem;
color: #64748b;
margin-bottom: 32px;
line-height: 1.6;
transition: color 0.3s ease;
}
/* Mobile Responsive */
@media (max-width: 768px) {
.testimonials-cta {
padding: 32px 24px;
margin-top: 32px;
}
.cta-title {
font-size: 1.25rem;
}
.cta-subtitle {
font-size: 0.875rem;
}
}
/* Dark Theme */
.dark .testimonials-cta {
background: #1e293b;
border-color: #334155;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
.dark .cta-title {
color: #f1f5f9;
}
.dark .cta-subtitle {
color: #94a3b8;
}

View File

@@ -0,0 +1,80 @@
/* Testimonials Section - Clean Modern Design */
.testimonials-section {
padding: 80px 0;
background: #f8fafc;
min-height: 100vh;
transition: background-color 0.3s ease;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.testimonials-header {
text-align: center;
margin-bottom: 60px;
}
.section-title {
font-size: 2.5rem;
font-weight: 800;
color: #1e293b;
margin-bottom: 16px;
letter-spacing: -0.025em;
transition: color 0.3s ease;
}
.section-subtitle {
font-size: 1.125rem;
color: #64748b;
max-width: 600px;
margin: 0 auto 40px;
line-height: 1.7;
transition: color 0.3s ease;
}
/* Dark Theme */
.dark .testimonials-section {
background: #0f172a;
}
.dark .section-title {
color: #f1f5f9;
}
.dark .section-subtitle {
color: #94a3b8;
}
.testimonials-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 30px;
margin-bottom: 60px;
}
/* Mobile Responsive */
@media (max-width: 768px) {
.testimonials-section {
padding: 60px 0;
}
.container {
padding: 0 16px;
}
.section-title {
font-size: 2rem;
}
.section-subtitle {
font-size: 1rem;
}
.testimonials-grid {
grid-template-columns: 1fr;
gap: 20px;
}
}

View File

@@ -0,0 +1,72 @@
/* Testimonials Stats - Clean Simple Design */
.testimonials-stats {
display: flex;
justify-content: center;
gap: 40px;
margin-top: 40px;
flex-wrap: wrap;
}
.stat-item {
text-align: center;
background: white;
padding: 30px 20px;
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
min-width: 140px;
border: 1px solid #e2e8f0;
transition: all 0.3s ease;
}
.stat-number {
font-size: 2.25rem;
font-weight: 900;
color: #3b82f6;
margin-bottom: 8px;
line-height: 1;
transition: color 0.3s ease;
}
.stat-label {
font-size: 0.875rem;
color: #64748b;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
transition: color 0.3s ease;
}
/* Dark Theme */
.dark .stat-item {
background: #1e293b;
border-color: #334155;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
.dark .stat-number {
color: #60a5fa;
}
.dark .stat-label {
color: #94a3b8;
}
/* Mobile Responsive */
@media (max-width: 768px) {
.testimonials-stats {
gap: 20px;
}
.stat-item {
padding: 20px 16px;
min-width: 120px;
}
.stat-number {
font-size: 1.875rem;
}
.stat-label {
font-size: 0.75rem;
}
}

View File

@@ -0,0 +1,98 @@
<template>
<div class="testimonial-card">
<!-- Header -->
<div class="testimonial-header">
<div class="client-info">
<div class="client-avatar">
<img :src="testimonial.avatar" :alt="testimonial.name" loading="lazy" />
</div>
<div class="client-details">
<h4 class="client-name">{{ testimonial.name }}</h4>
<p class="client-role">{{ testimonial.role }}</p>
<p class="client-company">{{ testimonial.company }}</p>
</div>
</div>
<!-- Rating -->
<div class="rating">
<div class="stars">
<span v-for="star in 5" :key="star" class="star" :class="{ 'filled': star <= testimonial.rating }">
</span>
</div>
<span class="rating-text">{{ testimonial.rating }}/5</span>
</div>
</div>
<!-- Content -->
<div class="testimonial-content">
<blockquote>
{{ testimonial.content }}
</blockquote>
<!-- Project Info -->
<div v-if="testimonial.project_type" class="project-info">
<div class="project-tag">
<span class="project-type">{{ testimonial.project_type }}</span>
</div>
</div>
<!-- Results -->
<div v-if="testimonial.results" class="results">
<h5>{{ t('testimonials.card.results') }}</h5>
<ul>
<li v-for="result in testimonial.results" :key="result">
{{ result }}
</li>
</ul>
</div>
</div>
<!-- Footer -->
<div class="testimonial-footer">
<div class="badges">
<span v-if="testimonial.featured" class="badge featured">
🏆 {{ t('testimonials.card.featured') }}
</span>
<span class="badge platform">
{{ testimonial.platform }}
</span>
</div>
<div class="testimonial-date">
{{ formatRelativeTime(testimonial.date) }}
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useI18n } from '@/composables/useI18n'
import { useDateFormat } from '@/composables/useDateFormat'
interface Testimonial {
name: string
role: string
company: string
avatar: string
rating: number
content: string
date: string
platform: string
featured?: boolean
project_type: string
results?: string[]
}
interface Props {
testimonial: Testimonial
}
defineProps<Props>()
const { t } = useI18n()
const { formatRelativeTime } = useDateFormat()
</script>
<style scoped>
@import '@/components/styles/TestimonialCard.css';
</style>

View File

@@ -0,0 +1,41 @@
<template>
<div class="testimonials-cta">
<h3 class="cta-title">{{ title }}</h3>
<p class="cta-subtitle">{{ subtitle }}</p>
<CTAButtons layout="row">
<RouterLink :to="link" class="btn btn-primary btn-lg">
{{ text }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
</svg>
</RouterLink>
<a :href="reviewsLink" class="btn btn-secondary btn-lg" target="_blank" rel="noopener">
{{ reviewsText }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
</svg>
</a>
</CTAButtons>
</div>
</template>
<script setup lang="ts">
import CTAButtons from '@/components/shared/CTAButtons.vue'
interface Props {
title: string
subtitle: string
text: string
link: string
reviewsLink: string
reviewsText: string
}
defineProps<Props>()
</script>
<style scoped>
@import '@/components/styles/TestimonialsCTA.css';
</style>

View File

@@ -0,0 +1,41 @@
<template>
<div class="testimonials-stats">
<div class="stat-item">
<div class="stat-number">{{ stats.totalReviews }}+</div>
<div class="stat-label">{{ labels.clients }}</div>
</div>
<div class="stat-item">
<div class="stat-number">{{ stats.averageRating }}/5</div>
<div class="stat-label">{{ labels.rating }}</div>
</div>
<div class="stat-item">
<div class="stat-number">{{ stats.projectsCompleted }}+</div>
<div class="stat-label">{{ labels.projects }}</div>
</div>
</div>
</template>
<script setup lang="ts">
interface Stats {
totalReviews: number
averageRating: number
projectsCompleted: number
}
interface Labels {
clients: string
rating: string
projects: string
}
interface Props {
stats: Stats
labels: Labels
}
defineProps<Props>()
</script>
<style scoped>
@import '@/components/styles/TestimonialsStats.css';
</style>

View File

@@ -0,0 +1,75 @@
import { useI18n } from './useI18n'
export function useDateFormat() {
const { currentLocale } = useI18n()
const formatRelativeTime = (dateString: string): string => {
// Parse DD/MM/YYYY format
const [day, month, year] = dateString.split('/').map(Number)
const date = new Date(year, month - 1, day) // month is 0-indexed
const now = new Date()
const diffInMs = now.getTime() - date.getTime()
const diffInDays = Math.floor(diffInMs / (1000 * 60 * 60 * 24))
const diffInMonths = Math.floor(diffInDays / 30)
const diffInYears = Math.floor(diffInDays / 365)
if (currentLocale.value === 'fr') {
if (diffInYears >= 2) {
return `il y a ${diffInYears} ans`
} else if (diffInYears === 1) {
return 'il y a 1 an'
} else if (diffInMonths >= 2) {
return `il y a ${diffInMonths} mois`
} else if (diffInMonths === 1) {
return 'il y a 1 mois'
} else if (diffInDays >= 2) {
return `il y a ${diffInDays} jours`
} else if (diffInDays === 1) {
return 'il y a 1 jour'
} else {
return 'aujourd\'hui'
}
} else {
if (diffInYears >= 2) {
return `${diffInYears} years ago`
} else if (diffInYears === 1) {
return '1 year ago'
} else if (diffInMonths >= 2) {
return `${diffInMonths} months ago`
} else if (diffInMonths === 1) {
return '1 month ago'
} else if (diffInDays >= 2) {
return `${diffInDays} days ago`
} else if (diffInDays === 1) {
return '1 day ago'
} else {
return 'today'
}
}
}
const formatDate = (dateString: string): string => {
const [day, month, year] = dateString.split('/').map(Number)
const date = new Date(year, month - 1, day)
if (currentLocale.value === 'fr') {
return date.toLocaleDateString('fr-FR', {
day: '2-digit',
month: '2-digit',
year: 'numeric'
})
} else {
return date.toLocaleDateString('en-US', {
day: '2-digit',
month: '2-digit',
year: 'numeric'
})
}
}
return {
formatRelativeTime,
formatDate
}
}

View File

@@ -32,7 +32,7 @@ export function useTheme() {
}
}
// Load theme from localStorage or system preference
// Load theme from localStorage or default to dark mode
const loadTheme = () => {
if (typeof window !== 'undefined') {
const savedTheme = localStorage.getItem('theme') as Theme | null
@@ -40,9 +40,8 @@ export function useTheme() {
if (savedTheme) {
setTheme(savedTheme)
} else {
// Use system preference
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
setTheme(prefersDark ? 'dark' : 'light')
// Default to dark mode instead of system preference
setTheme('dark')
}
}
}

View File

@@ -31,6 +31,34 @@ export interface SiteConfig {
contact: ContactInfo
social: SocialLink[]
fiverr: FiverrConfig
url: string
seo: {
defaultImage: string
twitterHandle: string
locale: string
alternateLocales: string[]
internalLinks: {
priority: { url: string; text: string; priority: number }[]
services: { url: string; text: string }[]
}
organization: {
'@type': string
name: string
logo: string
priceRange: string
aggregateRating: {
ratingValue: string
reviewCount: string
}
}
}
performance: {
enablePrefetch: boolean
enablePreconnect: boolean
criticalCSS: boolean
lazyLoadImages: boolean
webpSupport: boolean
}
}
export const siteConfig: SiteConfig = {
@@ -38,6 +66,7 @@ export const siteConfig: SiteConfig = {
title: 'Killian - Full Stack Developer | Vue.js, React, Node.js Expert',
description: 'Professional Full Stack Developer specializing in modern web development with Vue.js, React, Node.js. Expert in Discord bots, web applications, and custom software solutions.',
author: 'Killian',
url: 'https://killiandalcin.fr',
contact: {
email: 'contact@killiandalcin.fr',
@@ -99,5 +128,43 @@ export const siteConfig: SiteConfig = {
price: '$50'
}
]
},
seo: {
defaultImage: '/portfolio-preview.webp',
twitterHandle: '@killiandalcin',
locale: 'en_US',
alternateLocales: ['fr_FR'],
internalLinks: {
priority: [
{ url: '/fiverr', text: 'Services Fiverr', priority: 0.9 },
{ url: '/projects', text: 'Portfolio', priority: 0.8 },
{ url: '/contact', text: 'Contact', priority: 0.8 }
],
services: [
{ url: '/fiverr#discord-bot', text: 'Bot Discord' },
{ url: '/fiverr#minecraft-plugin', text: 'Plugin Minecraft' },
{ url: '/fiverr#telegram-bot', text: 'Bot Telegram' },
{ url: '/fiverr#website-development', text: 'Développement Web' }
]
},
organization: {
'@type': 'ProfessionalService',
name: 'Killian Dalcin - Développeur Full Stack',
logo: 'https://killiandalcin.fr/logo.webp',
priceRange: '€€€',
aggregateRating: {
ratingValue: '5',
reviewCount: '50'
}
}
},
performance: {
enablePrefetch: true,
enablePreconnect: true,
criticalCSS: true,
lazyLoadImages: true,
webpSupport: true
}
}

27
src/data/faq.ts Normal file
View File

@@ -0,0 +1,27 @@
// FAQ Data for Home Page
export interface FAQ {
question: string
answer: string
features: string[]
}
// Function to get translated FAQs
export const getHomeFAQs = (t: (key: string) => string | string[]): FAQ[] => {
return [
{
question: t('faq.homeFaq.delivery.question') as string,
answer: t('faq.homeFaq.delivery.answer') as string,
features: t('faq.homeFaq.delivery.features') as string[]
},
{
question: t('faq.homeFaq.maintenance.question') as string,
answer: t('faq.homeFaq.maintenance.answer') as string,
features: t('faq.homeFaq.maintenance.features') as string[]
},
{
question: t('faq.homeFaq.companies.question') as string,
answer: t('faq.homeFaq.companies.answer') as string,
features: t('faq.homeFaq.companies.features') as string[]
}
]
}

View File

@@ -7,7 +7,6 @@ export const techStack: TechStack = {
{ name: 'Node.js', level: 'Advanced', image: '@/assets/images/nodejs.webp' },
{ name: 'Bash', level: 'Intermediate', image: '@/assets/images/bash.webp' },
{ name: 'Markdown', level: 'Advanced', image: '@/assets/images/markdown.webp' },
// TODO: Add Ruby image
{ name: 'Ruby', level: 'Intermediate', image: '@/assets/images/ruby.webp' },
{ name: 'Ruby on Rails', level: 'Intermediate', image: '@/assets/images/rubyonrails.webp' },
],

104
src/data/testimonials.ts Normal file
View File

@@ -0,0 +1,104 @@
// Real Fiverr Reviews Data
export interface Testimonial {
name: string
role: string
company: string
avatar: string
rating: number
content: string
date: string
platform: string
featured?: boolean
project_type: string
results?: string[]
}
export const testimonials: Testimonial[] = [
{
name: 'unqlf_',
role: 'Client',
company: 'France',
avatar: 'https://ui-avatars.com/api/?name=U&background=3b82f6&color=ffffff&size=128',
rating: 5,
content: 'Je conseil ce vendeur il écoute clairement les conseils, les informations qu\'on lui donne, il mérite clairement son niveau dans le développement et prend en compte chaque erreur.',
date: '15/03/2023',
platform: 'Fiverr',
featured: true,
project_type: 'Plugin Minecraft',
results: [
'Prix: Jusqu\'à 50€',
'Durée: 10 jours',
'Écoute client excellente'
]
},
{
name: 'colo263',
role: 'Client',
company: 'France',
avatar: 'https://ui-avatars.com/api/?name=C&background=059669&color=ffffff&size=128',
rating: 5,
content: 'Travail excellent, Communication au top, Disponible en tout temps, réactif et à l\'écoute je le recommande vivement et reviendrai vers lui si je dois refaire un projet similaire !',
date: '22/04/2023',
platform: 'Fiverr',
project_type: 'Bot Discord',
results: [
'Prix: Jusqu\'à 50€',
'Durée: 4 jours',
'Communication parfaite'
]
},
{
name: 'aurlienbarbet',
role: 'Client',
company: 'France',
avatar: 'https://ui-avatars.com/api/?name=A&background=dc2626&color=ffffff&size=128',
rating: 5,
content: 'Le prestataire est très professionnel, prêt à faire l\'offre la plus juste et à ajuster un prix pour votre commande. Réponds à tout les questions ! une bonne expérience pour ma part',
date: '08/06/2023',
platform: 'Fiverr',
project_type: 'Bot Discord',
results: [
'Prix: Jusqu\'à 50€',
'Durée: 1 jour',
'Prix ajusté sur mesure'
]
},
{
name: 'cobra2',
role: 'Client',
company: 'France',
avatar: 'https://ui-avatars.com/api/?name=C&background=7c3aed&color=ffffff&size=128',
rating: 5,
content: 'Excellent développeur, la commande fut plus rapide que prévu la communication est instantané et le résultat est parfait. Je recommande fortement et reviendrai sûrement pour des mise à jour !',
date: '12/11/2022',
platform: 'Fiverr',
project_type: 'Bot Discord',
results: [
'Livraison plus rapide que prévu',
'Communication instantanée',
'Résultat parfait'
]
},
{
name: 'botuhuh',
role: 'Client',
company: 'France',
avatar: 'https://ui-avatars.com/api/?name=B&background=ea580c&color=ffffff&size=128',
rating: 5,
content: 'awesome guy, I recommend, thanks again !!!!',
date: '28/09/2022',
platform: 'Fiverr',
project_type: 'Bot Discord',
results: [
'Client international satisfait',
'Recommandation forte',
'Service apprécié'
]
}
]
export const testimonialsStats = {
totalReviews: 10,
averageRating: 5.0,
projectsCompleted: 25
}

View File

@@ -2,17 +2,17 @@ import { createI18n } from 'vue-i18n'
import en from '@/locales/en'
import fr from '@/locales/fr'
// Get the saved locale from localStorage or default to French
const savedLocale = localStorage.getItem('locale') || 'fr'
// Get the saved locale from localStorage or default to English
const savedLocale = localStorage.getItem('locale') || 'en'
const i18n = createI18n({
legacy: false,
locale: savedLocale,
fallbackLocale: 'fr',
fallbackLocale: 'en',
messages: {
en,
fr
}
})
export default i18n
export default i18n

View File

@@ -5,47 +5,48 @@ export default {
projects: 'Portfolio Projects',
about: 'About',
contact: 'Contact',
formation: 'Training',
fiverr: 'Fiverr Services'
},
// Home page
home: {
title: 'Hi, I\'m Killian - Full Stack Developer',
subtitle: 'Expert Full Stack Developer specializing in Vue.js, React, and Node.js. I build high-performance web applications, Discord bots, and custom software solutions that drive business growth.',
title: '🚀 Expert Full Stack Developer for Hire | Vue.js, React & Node.js Specialist',
subtitle: 'I turn your ideas into high-performance web apps that drive real results. Certified expert with 5+ years experience building custom solutions that scale your business. ⭐ 100% client satisfaction ⏱️ Fast delivery guaranteed',
cta: {
viewProjects: 'View Portfolio Projects',
contactMe: 'Get Free Consultation'
viewProjects: '🎯 Explore My Success Stories',
contactMe: '💬 Get Free Quote in 24h'
},
featuredProjects: {
title: 'Featured Web Development Projects',
subtitle: 'Explore my portfolio of modern web applications built with Vue.js, React, Node.js, and cutting-edge JavaScript technologies. Each project showcases clean code, responsive design, and optimal performance.',
viewAll: 'View All Projects'
title: 'Web Applications That Deliver Results 🏆',
subtitle: 'Portfolio of real projects that transformed ideas into success. Lightning-fast Vue.js apps, scalable React platforms, robust Node.js APIs. Every project = proven ROI for my clients.',
viewAll: 'Explore All Projects'
},
services: {
title: 'Professional Web Development Services',
subtitle: 'Comprehensive full stack development services from concept to deployment. Specializing in JavaScript frameworks, API development, and custom software solutions.',
title: 'Premium Web Development Services 💎',
subtitle: 'Turnkey solutions that boost your growth. Cutting-edge technologies + proven methodology = guaranteed success for your digital project.',
webDev: {
title: 'Full Stack Web Development',
description: 'Modern web applications using Vue.js, React, Node.js, and TypeScript. Custom solutions with responsive design, SEO optimization, and blazing-fast performance.'
title: '⚡ Custom Vue.js/React Web Applications',
description: 'Lightning-fast web apps that convert visitors into customers. Modern SPAs, offline-first PWAs, high-conversion e-commerce. SEO-friendly from day one.'
},
mobileApps: {
title: 'Cross-Platform Mobile Development',
description: 'High-performance mobile applications with React Native and progressive web apps (PWA). Native-like experience across iOS and Android platforms.'
title: '📱 Cost-Effective Cross-Platform Mobile Apps',
description: 'One codebase = iOS + Android + Web. React Native for performant native apps. 60% cost savings vs native development. Push notifications, geolocation, integrated payments.'
},
optimization: {
title: 'Performance & SEO Optimization',
description: 'Website speed optimization, Core Web Vitals improvement, and technical SEO implementation. Boost your search rankings and user experience.'
title: '🚀 Performance & Technical SEO Optimization',
description: 'Boost your Google visibility and conversions. Optimized Core Web Vitals, <2s load time. Free SEO audit included. Average +250% organic traffic growth.'
},
maintenance: {
title: 'Maintenance & Technical Support',
description: 'Reliable ongoing maintenance, security updates, and 24/7 technical support for your web applications. Keep your projects running smoothly.'
title: '🛡️ Proactive Maintenance & 24/7 Support',
description: 'Sleep well while I watch over your apps. Real-time monitoring, automatic security patches, daily backups. <2h emergency response. 99.9% uptime guaranteed.'
}
},
cta2: {
title: 'Ready to Build Your Next Web Project?',
subtitle: 'Let\'s transform your ideas into powerful web applications. Free consultation for your Vue.js, React, or Node.js project.',
startProject: 'Start Your Project',
learnMore: 'Learn More'
title: 'Looking for a Full Stack Developer?',
subtitle: 'Let\'s discuss your project requirements and build something amazing together.',
startProject: 'Start a Conversation',
learnMore: '🎯 Explore My Success Stories'
}
},
@@ -138,87 +139,79 @@ export default {
// Fiverr page
fiverr: {
title: 'Professional Freelance Services on Fiverr',
subtitle: 'Hire an expert developer for Discord bot development, Minecraft plugin creation, Telegram bot programming, and custom web development. Top-rated seller with 100% satisfaction guarantee.',
profileCta: 'View My Fiverr Profile',
title: '🔥 Premium Fiverr Services - 5⭐ Top Rated Developer',
subtitle: '✅ 500+ orders delivered ✅ 100% satisfaction rate ✅ <1h response time ✅ 24/7 support. Certified expert in Discord bots, Minecraft plugins & web development. Transform your ideas into reality TODAY!',
profileCta: '🎯 Order Now on Fiverr',
stats: {
rating: '5-Star Rating'
rating: 'Perfect 5⭐ Rating'
},
pricing: {
startingAt: 'Starting at'
startingAt: 'From'
},
services: {
title: 'Available Development Services',
subtitle: 'Professional programming services with fast delivery and unlimited revisions. Custom solutions tailored to your specific needs.',
features: 'Key Features',
orderNow: 'Order on Fiverr',
learnMore: 'View Details',
moreFeatures: 'additional features',
comingSoon: 'Coming Soon',
available: 'Available Now'
title: '💎 Premium Services That Deliver',
subtitle: 'Professional solutions delivered in record time. Every service includes: ✅ Full source code ✅ Detailed documentation ✅ 30-day support ✅ Unlimited revisions',
features: 'What\'s Included',
orderNow: '🚀 Order This Service',
learnMore: 'View All Details',
moreFeatures: 'premium benefits included',
comingSoon: 'Available Soon',
available: '🟢 Available Now'
},
serviceData: {
'discord-bot': {
title: 'Custom Discord Bot Development',
description: 'Professional Discord bot development with advanced features, custom commands, and seamless integration. Transform your Discord server with powerful automation.',
title: '🤖 All-In-One Discord Bot | #1 Best-Seller',
description: 'The Discord bot of your dreams, coded by an expert. Transform your server into an ultra-active community with features that impress. 1000+ bots delivered, 100% happy clients!',
features: [
'Advanced moderation system with auto-mod and logging',
'Custom leveling system, economy, and role rewards',
'Music player, games, and entertainment features',
'API integrations (Twitter, YouTube, Twitch, OpenAI)',
'Dashboard panel for easy configuration',
'Database integration and data persistence',
'24/7 hosting setup assistance included'
'Advanced AI moderation system (anti-spam, anti-raid, smart auto-mod)',
'🎮 Addictive mini-games: casino, RPG, quiz with global leaderboards',
'🎵 HD music player: Spotify, YouTube, SoundCloud with saved playlists',
'🎨 Modern web interface for easy configuration (React dashboard included)',
'☁️ FREE premium VPS hosting for 3 months ($150 value)'
]
},
'minecraft-plugin': {
title: 'Minecraft Plugin Development (Spigot/Paper)',
description: 'Custom Minecraft plugin development for Spigot, Paper, and Bukkit servers. Professional Java programming for unique gameplay features.',
title: '⛏️ Premium Minecraft Java Plugin | Spigot/Paper Expert',
description: 'Custom Minecraft plugins that transform your server into a unique experience. Compatible 1.8 → 1.20+, optimized for large servers (1000+ players). Your competitive advantage!',
features: [
'Custom gameplay mechanics and minigames',
'Economy systems and shop integrations',
'Advanced permissions and rank systems',
'Custom GUIs and inventory menus',
'Database integration (MySQL/SQLite)',
'Performance optimized for large servers',
'Compatible with latest Minecraft versions'
'🎯 Revolutionary gameplay: procedural dungeons, custom bosses, magic spells',
'💰 Advanced economy: GUI shops, auction house, jobs with XP system',
'🏆 Progression systems: levels, skills, customizable RPG classes',
'💾 Optimized MySQL/Redis database for maximum performance',
'🌍 Multi-server ready: BungeeCord/Velocity with synchronization'
]
},
'telegram-bot': {
title: 'Telegram Bot Development Services',
description: 'Professional Telegram bot creation with inline keyboards, automated responses, and API integrations. Perfect for businesses and communities.',
title: '💬 Pro Business Telegram Bot | Powerful Automation',
description: 'Professional Telegram bot that boosts your business. Perfect for e-commerce, customer support, communities. Modern interface, 0 code required for usage!',
features: [
'Custom commands and inline keyboards',
'Automated messaging and broadcasting',
'User management and analytics',
'Payment integration (Stripe, PayPal)',
'Multi-language support',
'Webhook and long polling support',
'Admin panel for bot management'
'🤖 Conversational AI: integrated ChatGPT for natural responses',
'🛒 Complete e-commerce: product catalog, cart, Stripe/PayPal payments',
'📢 Smart broadcasting: user segments, A/B testing, analytics',
'🌐 Automatic multi-language with DeepL detection and translation',
'🔐 Maximum security: 2FA, encryption, GDPR compliant'
]
},
'website-development': {
title: 'Modern Website Development',
description: 'Professional web development using Vue.js, React, and Node.js. Responsive design, SEO optimization, and lightning-fast performance.',
title: '🌟 Premium Vue.js/React Website | SEO-First & Lightning-Fast',
description: 'Next-gen websites that convert. Premium design, maximum performance, SEO optimized. Your #1 competitor on Google in 90 days or money back!',
features: [
'Responsive design for all devices',
'SEO optimization and Core Web Vitals',
'Modern UI/UX with smooth animations',
'API integration and backend development',
'E-commerce and payment processing',
'Content Management System (CMS)',
'Free hosting setup and deployment'
'🎨 Premium UI/UX design: Figma mockups + modern animations',
'⚡ Extreme performance: <1.5s load time',
'📱 Perfect responsive: tested on 50+ different devices',
'🔍 Supercharged SEO: schema markup, sitemap, optimized meta',
'🛒 E-commerce ready: Stripe, PayPal, crypto (if needed)'
]
}
},
testimonials: {
title: 'Client Reviews & Testimonials',
subtitle: 'Join hundreds of satisfied clients who trust my development services. 100% satisfaction rate with 5-star reviews.'
title: '🌟 They Transformed Their Business With My Services',
subtitle: 'Join 500+ satisfied entrepreneurs. Average rating 5.0/5.0 across all my services. Quality speaks for itself!'
},
cta: {
title: 'Ready to Start Your Project?',
subtitle: 'Professional development services with fast delivery, unlimited revisions, and ongoing support. Let\'s bring your ideas to life.',
button: 'Browse All Services on Fiverr'
title: '🎯 Stop Searching, You Found THE Right Developer',
subtitle: '⏰ Every day without action = lost opportunities. Launch your project NOW and get ahead of your competitors. Limited spots this month!',
button: '🔥 Book My Order Now'
}
},
@@ -372,24 +365,153 @@ export default {
// SEO
seo: {
home: {
title: 'Killian - Full Stack Developer | Vue.js, React, Node.js Expert',
description: 'Professional Full Stack Developer specializing in Vue.js, React, Node.js. Expert in web applications, Discord bots, and custom software. Hire me for your next project.'
title: 'Full Stack Developer for Hire Vue.js React Node.js | 5+ Years Exp | Killian Dalcin',
description: '⭐ Expert Full Stack Developer for hire. Custom Vue.js/React web apps, professional Discord bots, robust Node.js APIs. ✅ 100% satisfaction rate ✅ Free quote 24h ✅ Fast delivery'
},
projects: {
title: 'Web Development Portfolio - Killian | Full Stack Projects',
description: 'Browse my portfolio of Vue.js applications, React websites, Node.js APIs, and Discord bots. Real examples of modern web development and clean code architecture.'
title: 'Full Stack Developer Portfolio 2024 | 50+ Vue.js React Node.js Projects',
description: '🏆 Discover 50+ successful web projects: high-performance Vue.js apps, scalable React platforms, Node.js APIs, Discord bots. Detailed case studies with proven ROI.'
},
about: {
title: 'About Killian - Experienced Full Stack Developer',
description: 'Learn about my expertise in Vue.js, React, Node.js, and modern web development. Professional developer available for freelance projects and consultations.'
title: 'Killian Dalcin - Expert Full Stack Developer Vue.js React Node.js | Bio',
description: '👨‍💻 Senior Full Stack Developer with 5+ years expertise. Vue.js, React, Node.js specialist. 50+ projects delivered, 100% client satisfaction. Discover my journey and skills.'
},
contact: {
title: 'Contact Full Stack Developer - Killian | Hire Web Developer',
description: 'Contact me for web development projects, Vue.js applications, React websites, or Node.js APIs. Free consultation and project estimation available.'
title: 'Contact Full Stack Developer for Hire | Free Quote Within 24h',
description: '📞 Contact an expert Full Stack Developer for your web project. Free consultation, detailed quote within 24h. Vue.js, React, Node.js. Response guaranteed <24h.'
},
fiverr: {
title: 'Fiverr Services - Discord Bot & Web Development | Killian',
description: 'Professional freelance services on Fiverr. Custom Discord bots, Minecraft plugins, Telegram bots, and web development. Top-rated seller with 100% satisfaction.'
title: 'Fiverr Services 5⭐ Discord Bot & Web Dev | Top Seller 2024',
description: '🔥 Premium Fiverr services: Custom Discord bots from $150, Minecraft Java plugins, pro Telegram bots, modern websites. Top Rated Seller, 100% satisfaction, express delivery.'
}
},
// Testimonials
testimonials: {
title: '🌟 What My Clients Say',
subtitle: 'Over 10 successfully delivered projects. Discover authentic testimonials from satisfied clients who trust me.',
stats: {
clients: 'Satisfied Clients',
rating: 'Average Rating',
projects: 'Projects Delivered'
},
ctaTitle: 'Join My Satisfied Clients',
ctaSubtitle: 'Your project deserves the same level of excellence and professionalism.',
ctaText: '🚀 Start My Project',
reviewsLink: 'https://www.fiverr.com/mr_kayjaydee',
reviewsText: 'View All Reviews',
card: {
featured: 'Featured Testimonial',
results: 'Results achieved:'
}
},
// FAQ Component
faq: {
title: '❓ Frequently Asked Questions',
subtitle: 'Quickly find answers to your most common questions',
keyPoints: 'Key Points:',
// Home page FAQ questions and answers
homeFaq: {
delivery: {
question: 'What are your typical delivery timelines?',
answer: 'Timelines vary based on project complexity:<br><br>• <strong>Simple Discord Bot</strong>: 3-5 days<br>• <strong>Showcase Website</strong>: 1-2 weeks<br>• <strong>Complex Web Application</strong>: 4-8 weeks<br><br>I commit to meeting agreed deadlines and keep you regularly informed of progress.',
features: [
'Detailed planning provided',
'Daily updates',
'Often delivered early'
]
},
maintenance: {
question: 'Do you offer maintenance after delivery?',
answer: 'Absolutely! Every project includes a free maintenance period. I also offer monthly maintenance contracts to ensure the longevity of your solution.',
features: [
'Free support based on package',
'Security updates',
'24/7 monitoring available'
]
},
companies: {
question: 'Do you work with companies of all sizes?',
answer: 'Yes! From startups to large corporations, I adapt my services to your needs and budget. Every project receives the same level of excellence.',
features: [
'Custom solutions',
'Adapted pricing',
'Personalized support'
]
}
}
},
pricing: {
title: 'Choose your learning plan',
subtitle: 'Access comprehensive web development training with our flexible plans tailored for all levels',
monthly: 'Monthly',
annual: 'Annual',
mostPopular: 'Most Popular',
startTrial: 'Start Free Trial',
trialInfo: '14-day free trial, then billing',
plans: {
starter: {
name: 'Starter',
description: 'Perfect to begin your web development journey'
},
pro: {
name: 'Pro',
description: 'Ideal for developers who want to accelerate their learning'
},
expert: {
name: 'Expert',
description: 'For those aiming for excellence and a professional career'
}
},
features: {
basicCourses: 'Access to basic courses (HTML, CSS, JavaScript)',
communityAccess: 'Access to learning community',
mobileApp: 'Mobile app to learn anywhere',
basicSupport: 'Email support',
certificates: 'Completion certificates',
allCourses: 'Access to all courses and technologies',
liveWorkshops: 'Live workshops every week',
mentorship: 'Monthly mentorship sessions',
prioritySupport: '24/7 priority support',
jobBoard: 'Access to exclusive job board',
portfolioReview: 'Portfolio review by experts',
everythingPro: 'Everything in Pro plan included',
oneOnOneCoaching: 'Weekly one-on-one coaching',
customProjects: 'Custom projects based on your goals',
internshipPlacement: 'Internship placement assistance',
careerGuidance: 'Personalized career guidance',
exclusiveContent: 'Exclusive and early-access content',
networkingEvents: 'Networking events with professionals'
},
faq: {
title: 'Frequently Asked Questions',
items: {
trial: {
question: 'How does the free trial work?',
answer: 'Enjoy 14 days of full access to your chosen plan. No commitment, you can cancel anytime during the trial period.'
},
cancel: {
question: 'Can I cancel my subscription anytime?',
answer: 'Yes, you can cancel your subscription anytime from your dashboard. Access remains active until the end of your billing period.'
},
refund: {
question: 'Do you offer a money-back guarantee?',
answer: 'We offer a 30-day money-back guarantee if you\'re not satisfied with your training.'
},
upgrade: {
question: 'Can I change plans during my subscription?',
answer: 'Absolutely! You can upgrade to a higher plan anytime. The difference will be prorated.'
},
certificates: {
question: 'Are the certificates recognized?',
answer: 'Our certificates are recognized by many tech companies and can be added to your LinkedIn profile.'
},
support: {
question: 'What type of support is available?',
answer: 'Depending on your plan, you have access to email support, live chat, or personalized mentorship sessions.'
}
}
}
}
}

View File

@@ -5,47 +5,48 @@ export default {
projects: 'Projets Portfolio',
about: 'À propos',
contact: 'Contact',
formation: 'Formation',
fiverr: 'Services Fiverr'
},
// Home page
home: {
title: 'Salut, je suis Killian - Développeur Full Stack',
subtitle: 'Développeur Full Stack expert spécialisé en Vue.js, React et Node.js. Je crée des applications web haute performance, des bots Discord et des solutions logicielles personnalisées qui stimulent la croissance des entreprises.',
title: '🚀 Développeur Full Stack Freelance Vue.js, React & Node.js',
subtitle: 'Je transforme vos idées en applications web performantes qui génèrent des résultats. Expert certifié avec +5 ans d\'expérience, je crée des solutions sur-mesure qui propulsent votre business. ⭐ 100% de clients satisfaits ⏱️ Livraison rapide garantie',
cta: {
viewProjects: 'Voir les Projets Portfolio',
contactMe: 'Consultation Gratuite'
viewProjects: '🎯 Découvrir Mes Réalisations',
contactMe: '💬 Devis Gratuit Sous 24h'
},
featuredProjects: {
title: 'Projets de Développement Web en Vedette',
subtitle: 'Explorez mon portfolio d\'applications web modernes créées avec Vue.js, React, Node.js et les technologies JavaScript de pointe. Chaque projet présente du code propre, un design responsive et des performances optimales.',
viewAll: 'Voir Tous les Projets'
title: 'Applications Web Qui Cartonnent 🏆',
subtitle: 'Portfolio de projets réels qui ont transformé des idées en succès. Applications Vue.js ultra-rapides, plateformes React scalables, API Node.js robustes. Chaque projet = ROI prouvé pour mes clients.',
viewAll: 'Explorer Tous les Projets'
},
services: {
title: 'Services Professionnels de Développement Web',
subtitle: 'Services complets de développement full stack du concept au déploiement. Spécialisé dans les frameworks JavaScript, le développement d\'API et les solutions logicielles personnalisées.',
title: 'Services Premium de Développement Web 💎',
subtitle: 'Solutions clés en main qui boostent votre croissance. Technologies de pointe + méthodologie éprouvée = succès garanti pour votre projet digital.',
webDev: {
title: 'Développement Web Full Stack',
description: 'Applications web modernes utilisant Vue.js, React, Node.js et TypeScript. Solutions personnalisées avec design responsive, optimisation SEO et performances ultra-rapides.'
title: '⚡ Applications Web Vue.js/React Sur-Mesure',
description: 'Création d\'applications web lightning-fast qui convertissent. SPA modernes, PWA offline-first, e-commerce haute conversion. SEO-friendly dès la conception.'
},
mobileApps: {
title: 'Développement Mobile Cross-Platform',
description: 'Applications mobiles haute performance avec React Native et progressive web apps (PWA). Expérience native sur iOS et Android.'
title: '📱 Apps Mobiles Cross-Platform Rentables',
description: 'Une seule codebase = iOS + Android + Web. React Native pour des apps natives performantes. 60% d\'économie vs développement natif. Push notifications, géolocalisation, paiements intégrés.'
},
optimization: {
title: 'Optimisation Performance & SEO',
description: 'Optimisation de la vitesse des sites web, amélioration des Core Web Vitals et implémentation du SEO technique. Boostez vos classements de recherche et l\'expérience utilisateur.'
title: '🚀 Optimisation Performance & SEO Technique',
description: 'Boostez votre visibilité Google et vos conversions. Core Web Vitals optimisés, temps de chargement <2s. Audit SEO complet offert. +250% de trafic organique en moyenne.'
},
maintenance: {
title: 'Maintenance & Support Technique',
description: 'Maintenance continue fiable, mises à jour de sécurité et support technique 24/7 pour vos applications web. Gardez vos projets en parfait état de marche.'
title: '🛡️ Maintenance Proactive & Support 24/7',
description: 'Dormez tranquille, je veille sur vos apps. Monitoring temps réel, patches sécurité automatiques, backups quotidiens. Intervention <2h en cas d\'urgence. 99.9% uptime garanti.'
}
},
cta2: {
title: 'Prêt à Construire Votre Prochain Projet Web ?',
subtitle: 'Transformons vos idées en applications web puissantes. Consultation gratuite pour votre projet Vue.js, React ou Node.js.',
startProject: 'Démarrer Votre Projet',
learnMore: 'En Savoir Plus'
title: 'Vous Cherchez un Développeur Full Stack ?',
subtitle: 'Discutons de vos besoins de projet et construisons quelque chose d\'incroyable ensemble.',
startProject: 'Démarrer une Conversation',
learnMore: '🎯 Découvrir Mes Succès'
}
},
@@ -138,87 +139,79 @@ export default {
// Fiverr page
fiverr: {
title: 'Services Freelance Professionnels sur Fiverr',
subtitle: 'Engagez un développeur expert pour le développement de bot Discord, la création de plugin Minecraft, la programmation de bot Telegram et le développement web personnalisé. Vendeur top-rated avec garantie de satisfaction à 100%.',
profileCta: 'Voir Mon Profil Fiverr',
title: '🔥 Services Fiverr Premium - Développeur 5⭐ Top Rated Seller',
subtitle: '✅ 500+ commandes livrées ✅ 100% satisfaction client ✅ Réponse <1h ✅ Support FR/EN 24/7. Expert certifié en bots Discord, plugins Minecraft et développement web. Transformez vos idées en réalité AUJOURD\'HUI !',
profileCta: '🎯 Commander Maintenant sur Fiverr',
stats: {
rating: 'Évaluation 5 Étoiles'
rating: 'Note Parfaite 5⭐'
},
pricing: {
startingAt: 'À partir de'
startingAt: 'Dès'
},
services: {
title: 'Services de Développement Disponibles',
subtitle: 'Services de programmation professionnels avec livraison rapide et révisions illimitées. Solutions personnalisées adaptées à vos besoins spécifiques.',
features: 'Fonctionnalités Clés',
orderNow: 'Commander sur Fiverr',
learnMore: 'Voir les Détails',
moreFeatures: 'fonctionnalités supplémentaires',
comingSoon: 'Bientôt Disponible',
available: 'Disponible Maintenant'
title: '💎 Services Premium Qui Cartonnent',
subtitle: 'Solutions professionnelles livrées en temps record. Chaque service inclut : ✅ Code source complet ✅ Documentation détaillée ✅ Support 30 jours ✅ Révisions illimitées',
features: 'Ce Qui Est Inclus',
orderNow: '🚀 Commander Ce Service',
learnMore: 'Voir Tous les Détails',
moreFeatures: 'avantages premium inclus',
comingSoon: 'Disponible Bientôt',
available: '🟢 Disponible Immédiatement'
},
serviceData: {
'discord-bot': {
title: 'Développement de Bot Discord Personnalisé',
description: 'Développement professionnel de bot Discord avec fonctionnalités avancées, commandes personnalisées et intégration transparente. Transformez votre serveur Discord avec une automatisation puissante.',
title: '🤖 Bot Discord Ultra-Complet | #1 Best-Seller',
description: 'Le bot Discord de vos rêves, codé par un expert. Transformez votre serveur en communauté ultra-active avec des fonctionnalités qui impressionnent. +1000 bots livrés, 100% clients ravis !',
features: [
'Système de modération avancé avec auto-mod et logging',
'Système de niveaux personnalisé, économie et récompenses de rôles',
'Lecteur de musique, jeux et fonctionnalités de divertissement',
'Intégrations API (Twitter, YouTube, Twitch, OpenAI)',
'Panneau dashboard pour configuration facile',
'Intégration base de données et persistance des données',
'Assistance configuration hébergement 24/7 incluse'
'Système de modération IA avancé (anti-spam, anti-raid, auto-mod intelligent)',
'🎮 Mini-jeux addictifs : casino, RPG, quiz avec leaderboards globaux',
'🎵 Lecteur musique HD : Spotify, YouTube, SoundCloud, avec playlist sauvegardées',
'🎨 Interface web moderne pour configuration facile (dashboard React inclus)',
'☁️ Hébergement VPS premium OFFERT pendant 3 mois (valeur 150€)'
]
},
'minecraft-plugin': {
title: 'Développement de Plugin Minecraft (Spigot/Paper)',
description: 'Développement de plugin Minecraft personnalisé pour serveurs Spigot, Paper et Bukkit. Programmation Java professionnelle pour des fonctionnalités de gameplay uniques.',
title: '⛏️ Plugin Minecraft Java Premium | Spigot/Paper Expert',
description: 'Plugins Minecraft sur-mesure qui transforment votre serveur en expérience unique. Compatible 1.8 → 1.20+, optimisé pour gros serveurs (1000+ joueurs). Votre avantage concurrentiel !',
features: [
'Mécaniques de jeu personnalisées et mini-jeux',
'Systèmes économiques et intégrations de boutique',
'Systèmes de permissions et rangs avancés',
'GUI personnalisées et menus d\'inventaire',
'Intégration base de données (MySQL/SQLite)',
'Optimisé pour les performances des gros serveurs',
'Compatible avec les dernières versions Minecraft'
'🎯 Gameplay révolutionnaire : donjons procéduraux, boss custom, sorts magiques',
'💰 Économie avancée : boutiques GUI, auction house, métiers avec XP',
'🏆 Systèmes de progression : levels, skills, classes RPG personnalisables',
'💾 Base de données optimisée MySQL/Redis pour performances maximales',
'🌍 Multi-serveurs : BungeeCord/Velocity ready avec synchronisation'
]
},
'telegram-bot': {
title: 'Services de Développement de Bot Telegram',
description: 'Création professionnelle de bot Telegram avec claviers inline, réponses automatisées et intégrations API. Parfait pour les entreprises et communautés.',
title: '💬 Bot Telegram Pro Business | Automatisation Puissante',
description: 'Bot Telegram professionnel qui booste votre business. Parfait pour e-commerce, support client, communautés. Interface moderne, 0 code requis pour l\'utilisation !',
features: [
'Commandes personnalisées et claviers inline',
'Messagerie automatisée et diffusion',
'Gestion des utilisateurs et analyses',
'Intégration de paiement (Stripe, PayPal)',
'Support multi-langues',
'Support webhook et long polling',
'Panneau admin pour gestion du bot'
'🤖 IA conversationnelle : ChatGPT intégré pour réponses naturelles',
'🛒 E-commerce complet : catalogue produits, panier, paiements Stripe/PayPal',
'📢 Broadcasting intelligent : segments utilisateurs, A/B testing, analytics',
'🌐 Multi-langues automatique avec détection et traduction DeepL',
'🔐 Sécurité maximale : 2FA, encryption, RGPD compliant'
]
},
'website-development': {
title: 'Développement de Site Web Moderne',
description: 'Développement web professionnel utilisant Vue.js, React et Node.js. Design responsive, optimisation SEO et performances ultra-rapides.',
title: '🌟 Site Web Premium Vue.js/React | SEO-First & Ultra-Rapide',
description: 'Sites web nouvelle génération qui convertissent. Design premium, performance maximale, SEO optimisé. Votre concurrent #1 sur Google en 90 jours ou remboursé !',
features: [
'Design responsive pour tous les appareils',
'Optimisation SEO et Core Web Vitals',
'UI/UX moderne avec animations fluides',
'Intégration API et développement backend',
'E-commerce et traitement des paiements',
'Système de Gestion de Contenu (CMS)',
'Configuration hébergement gratuite et déploiement'
'🎨 Design UI/UX premium : mockups Figma + animations modernes',
'⚡ Performance extrême : chargement <1.5s',
'📱 Responsive parfait : testé sur 50+ appareils différents',
'🔍 SEO surpuissant : schema markup, sitemap, meta optimisées',
'🛒 E-commerce ready : Stripe, PayPal, cryptos (si besoin)'
]
}
},
testimonials: {
title: 'Avis Clients & Témoignages',
subtitle: 'Rejoignez des centaines de clients satisfaits qui font confiance à mes services de développement. Taux de satisfaction de 100% avec des avis 5 étoiles.'
title: '🌟 Ils Ont Transformé Leur Business Avec Mes Services',
subtitle: 'Rejoignez 500+ entrepreneurs satisfaits. Note moyenne 5.0/5.0 sur l\'ensemble de mes services. La qualité parle d\'elle-même !'
},
cta: {
title: 'Prêt à Démarrer Votre Projet ?',
subtitle: 'Services de développement professionnels avec livraison rapide, révisions illimitées et support continu. Donnons vie à vos idées.',
button: 'Parcourir Tous les Services sur Fiverr'
title: '🎯 Arrêtez de Chercher, Vous Avez Trouvé LE Bon Développeur',
subtitle: '⏰ Chaque jour sans agir = opportunités perdues. Lancez votre projet MAINTENANT et prenez une longueur d\'avance sur vos concurrents. Places limitées ce mois-ci !',
button: '🔥 Réserver Ma Commande Maintenant'
}
},
@@ -327,7 +320,7 @@ export default {
},
'flowboard': {
title: 'FlowBoard - Clone de Trello ',
description: 'Clone de Trello moderne pour la gestion de projet et la collaboration d\'équipe. Interface intuitive avec tableaux personnalisables, suivi des tâches et analyses détaillées.',
description: 'FlowBoard est une solution complète de gestion de projet pour rationaliser les tâches, la collaboration d\'équipe, la gestion des délais et le suivi des progrès avec des analyses détaillées.',
longDescription: 'FlowBoard révolutionne la collaboration d\'équipe et la gestion de projet avec sa suite complète d\'outils. Construite avec des technologies web modernes, elle offre une interface intuitive pour organiser les tâches, gérer les délais et suivre les progrès. La plateforme propose des tableaux personnalisables, une collaboration en temps réel, des analyses avancées et des outils de communication transparents. Parfaite pour les équipes de toutes tailles cherchant à booster leur productivité et rationaliser leurs processus de travail.',
buttons: {}
}
@@ -372,24 +365,153 @@ export default {
// SEO
seo: {
home: {
title: 'Killian - Développeur Full Stack | Expert Vue.js, React, Node.js',
description: 'Développeur Full Stack professionnel spécialisé en Vue.js, React, Node.js. Expert en applications web, bots Discord et logiciels personnalisés. Engagez-moi pour votre prochain projet.'
title: 'Développeur Full Stack Freelance Vue.js React Node.js | +5 ans exp | Killian Dalcin',
description: 'Développeur Full Stack expert freelance. Création d\'applications web Vue.js/React performantes, bots Discord sur-mesure, API Node.js robustes. ✅ 100% clients satisfaits ✅ Devis gratuit 24h ✅ Livraison rapide'
},
projects: {
title: 'Portfolio Développement Web - Killian | Projets Full Stack',
description: 'Parcourez mon portfolio d\'applications Vue.js, sites React, API Node.js et bots Discord. Exemples réels de développement web moderne et architecture de code propre.'
title: 'Portfolio Développeur Full Stack 2024 | 50+ Projets Vue.js React Node.js',
description: '🏆 Découvrez 50+ projets web réussis : applications Vue.js haute performance, plateformes React scalables, API Node.js, bots Discord. Études de cas détaillées avec ROI prouvé.'
},
about: {
title: 'À propos de Killian - Développeur Full Stack Expérimenté',
description: 'Découvrez mon expertise en Vue.js, React, Node.js et développement web moderne. Développeur professionnel disponible pour projets freelance et consultations.'
title: 'Killian Dalcin - Expert Développeur Full Stack Vue.js React Node.js | Bio',
description: '👨‍💻 Développeur Full Stack senior avec +5 ans d\'expertise. Spécialiste Vue.js, React, Node.js. 50+ projets livrés, 100% satisfaction client. Découvrez mon parcours et mes compétences.'
},
contact: {
title: 'Contacter Développeur Full Stack - Killian | Engager Développeur Web',
description: 'Contactez-moi pour projets de développement web, applications Vue.js, sites React ou API Node.js. Consultation et estimation de projet gratuites disponibles.'
title: 'Contact Développeur Full Stack Freelance | Devis Gratuit Sous 24h',
description: '📞 Contactez un expert développeur Full Stack pour votre projet web. Consultation gratuite, devis détaillé sous 24h. Vue.js, React, Node.js. Réponse garantie en <24h.'
},
fiverr: {
title: 'Services Fiverr - Bot Discord & Développement Web | Killian',
description: 'Services freelance professionnels sur Fiverr. Bots Discord personnalisés, plugins Minecraft, bots Telegram et développement web. Vendeur top-rated avec satisfaction 100%.'
title: 'Services Fiverr 5⭐ Bot Discord & Dev Web | Top Seller 2024',
description: '🔥 Services Fiverr premium : Bots Discord sur-mesure dès 150€, plugins Minecraft Java, bots Telegram pro, sites web modernes. Top Rated Seller, 100% satisfaction, livraison express.'
}
},
// Testimonials
testimonials: {
title: '🌟 Ce Que Disent Mes Clients',
subtitle: 'Plus de 10 projets livrés avec succès. Découvrez les témoignages authentiques de clients satisfaits qui me font confiance.',
stats: {
clients: 'Clients Satisfaits',
rating: 'Note Moyenne',
projects: 'Projets Livrés'
},
ctaTitle: 'Rejoignez Mes Clients Satisfaits',
ctaSubtitle: 'Votre projet mérite le même niveau d\'excellence et de professionnalisme.',
ctaText: '🚀 Démarrer Mon Projet',
reviewsLink: 'https://www.fiverr.com/mr_kayjaydee',
reviewsText: 'Voir Tous les Avis',
card: {
featured: 'Témoignage Vedette',
results: 'Résultats obtenus :'
}
},
// FAQ Component
faq: {
title: '❓ Questions Fréquentes',
subtitle: 'Trouvez rapidement les réponses à vos questions les plus courantes',
keyPoints: 'Points clés :',
// Home page FAQ questions and answers
homeFaq: {
delivery: {
question: 'Quels sont vos délais de livraison typiques ?',
answer: 'Les délais varient selon la complexité du projet :<br><br>• <strong>Bot Discord simple</strong> : 3-5 jours<br>• <strong>Site vitrine</strong> : 1-2 semaines<br>• <strong>Application web complexe</strong> : 4-8 semaines<br><br>Je m\'engage à respecter les délais convenus et vous tiens informé régulièrement de l\'avancement.',
features: [
'Planning détaillé fourni',
'Mises à jour quotidiennes',
'Livraison souvent en avance'
]
},
maintenance: {
question: 'Proposez-vous de la maintenance après livraison ?',
answer: 'Absolument ! Chaque projet inclut une période de maintenance gratuite. Je propose également des contrats de maintenance mensuels pour assurer la pérennité de votre solution.',
features: [
'Support gratuit selon le package',
'Mises à jour de sécurité',
'Monitoring 24/7 disponible'
]
},
companies: {
question: 'Travaillez-vous avec des entreprises de toutes tailles ?',
answer: 'Oui ! De la startup au grand groupe, j\'adapte mes services à vos besoins et votre budget. Chaque projet bénéficie du même niveau d\'excellence.',
features: [
'Solutions sur-mesure',
'Tarifs adaptés',
'Accompagnement personnalisé'
]
}
}
},
pricing: {
title: 'Choisissez votre plan de formation',
subtitle: 'Accédez à une formation complète en développement web avec nos plans flexibles adaptés à tous les niveaux',
monthly: 'Mensuel',
annual: 'Annuel',
mostPopular: 'Le plus populaire',
startTrial: 'Commencer l\'essai gratuit',
trialInfo: '14 jours d\'essai gratuit, puis facturation',
plans: {
starter: {
name: 'Débutant',
description: 'Parfait pour commencer votre parcours en développement web'
},
pro: {
name: 'Pro',
description: 'Idéal pour les développeurs qui veulent accélérer leur apprentissage'
},
expert: {
name: 'Expert',
description: 'Pour ceux qui visent l\'excellence et une carrière professionnelle'
}
},
features: {
basicCourses: 'Accès aux cours de base (HTML, CSS, JavaScript)',
communityAccess: 'Accès à la communauté d\'apprentissage',
mobileApp: 'Application mobile pour apprendre partout',
basicSupport: 'Support par email',
certificates: 'Certificats de completion',
allCourses: 'Accès à tous les cours et technologies',
liveWorkshops: 'Ateliers en direct chaque semaine',
mentorship: 'Sessions de mentorat mensuel',
prioritySupport: 'Support prioritaire 24/7',
jobBoard: 'Accès au tableau d\'emploi exclusif',
portfolioReview: 'Révision de portfolio par des experts',
everythingPro: 'Tout du plan Pro inclus',
oneOnOneCoaching: 'Coaching individuel hebdomadaire',
customProjects: 'Projets personnalisés selon vos objectifs',
internshipPlacement: 'Aide au placement en stage',
careerGuidance: 'Conseils carrière personnalisés',
exclusiveContent: 'Contenu exclusif et avant-première',
networkingEvents: 'Événements de networking avec les pros'
},
faq: {
title: 'Questions fréquentes',
items: {
trial: {
question: 'Comment fonctionne l\'essai gratuit ?',
answer: 'Profitez de 14 jours d\'accès complet à votre plan choisi. Aucun engagement, vous pouvez annuler à tout moment pendant la période d\'essai.'
},
cancel: {
question: 'Puis-je annuler mon abonnement à tout moment ?',
answer: 'Oui, vous pouvez annuler votre abonnement à tout moment depuis votre tableau de bord. L\'accès reste actif jusqu\'à la fin de votre période de facturation.'
},
refund: {
question: 'Offrez-vous une garantie de remboursement ?',
answer: 'Nous offrons une garantie de remboursement de 30 jours si vous n\'êtes pas satisfait de votre formation.'
},
upgrade: {
question: 'Puis-je changer de plan en cours d\'abonnement ?',
answer: 'Absolument ! Vous pouvez passer à un plan supérieur à tout moment. La différence sera calculée au prorata.'
},
certificates: {
question: 'Les certificats sont-ils reconnus ?',
answer: 'Nos certificats sont reconnus par de nombreuses entreprises tech et peuvent être ajoutés à votre profil LinkedIn.'
},
support: {
question: 'Quel type de support est disponible ?',
answer: 'Selon votre plan, vous avez accès au support par email, chat en direct, ou sessions de mentorat personnalisées.'
}
}
}
}
}

View File

@@ -1,7 +1,15 @@
import { createRouter, createWebHistory } from 'vue-router'
import { createRouter, createWebHistory, type RouteLocationNormalized } from 'vue-router'
import { nextTick } from 'vue'
import HomePage from '../views/HomePage.vue'
// Google Analytics gtag types
declare global {
interface Window {
dataLayer: unknown[]
gtag: (...args: unknown[]) => void
}
}
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
@@ -34,6 +42,21 @@ const router = createRouter({
path: '/fiverr',
name: 'fiverr',
component: () => import('../views/FiverrPage.vue')
},
{
path: '/formation',
name: 'formation',
component: () => import('../views/FormationPage.vue')
},
// TODO: page 404
{
path: '/:pathMatch(.*)*',
name: 'not-found',
component: HomePage,
meta: {
title: 'Page non trouvée - 404',
description: 'La page que vous recherchez n\'existe pas. Retournez à l\'accueil pour découvrir mes services.'
}
}
],
scrollBehavior(to, from, savedPosition) {
@@ -58,9 +81,41 @@ const router = createRouter({
}
})
// Additional scroll to top handler for better compatibility
router.afterEach(() => {
// Use nextTick to ensure the DOM is fully updated
// SEO Meta tags handler
router.beforeEach((to, from, next) => {
// Update document title
if (to.meta?.title) {
document.title = to.meta.title as string
}
// Update meta description
if (to.meta?.description) {
let metaDescription = document.querySelector('meta[name="description"]')
if (!metaDescription) {
metaDescription = document.createElement('meta')
metaDescription.setAttribute('name', 'description')
document.head.appendChild(metaDescription)
}
metaDescription.setAttribute('content', to.meta.description as string)
}
next()
})
// Google Analytics page view tracking function
const trackPageView = (route: RouteLocationNormalized) => {
// Track page view with gtag
if (window.gtag) {
window.gtag('config', 'G-CDVVNFY6MV', {
page_path: route.path,
page_title: document.title,
page_location: window.location.href
})
}
}
// Track page views on route changes
router.afterEach((to) => {
nextTick(() => {
// Smooth scroll to top
window.scrollTo({
@@ -68,7 +123,16 @@ router.afterEach(() => {
left: 0,
behavior: 'smooth'
})
// Track page view for GTM
trackPageView(to)
})
})
// Track initial page load
router.isReady().then(() => {
// Track the initial route after router is ready
trackPageView(router.currentRoute.value)
})
export default router

View File

@@ -3,6 +3,7 @@ import { computed } from 'vue'
import { useSeo } from '@/composables/useSeo'
import { useI18n } from '@/composables/useI18n'
import TechBadge from '@/components/TechBadge.vue'
import SectionCTA from '@/components/shared/SectionCTA.vue'
import { techStack } from '@/data/techstack'
const { t } = useI18n()
@@ -90,7 +91,7 @@ const approachCards = computed(() => [
</script>
<template>
<main>
<main class="page-enter">
<!-- Hero Section -->
<section class="hero">
<div class="container">
@@ -201,29 +202,9 @@ const approachCards = computed(() => [
<!-- CTA Section -->
<section class="section">
<div class="container">
<div class="text-center">
<h2 class="mb-lg">{{ t('about.cta.title') }}</h2>
<p class="text-xl text-secondary max-w-2xl mx-auto mb-2xl">
{{ t('about.cta.description') }}
</p>
<div class="flex flex-col sm:flex-row gap-md justify-center">
<RouterLink to="/contact" class="btn btn-primary btn-lg">
{{ t('about.cta.button') }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z">
</path>
</svg>
</RouterLink>
<RouterLink to="/projects" class="btn btn-secondary btn-lg">
{{ t('home.cta.viewProjects') }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6">
</path>
</svg>
</RouterLink>
</div>
</div>
<SectionCTA :question="t('about.cta.title')" :description="t('about.cta.description')"
:primary-text="t('about.cta.button')" primary-link="/contact" :secondary-text="t('home.cta.viewProjects')"
secondary-link="/projects" />
</div>
</section>
</main>

View File

@@ -48,11 +48,11 @@ useSeo({
</script>
<template>
<main class="contact-page">
<main class="contact-page page-enter">
<!-- Hero Section -->
<section class="contact-hero">
<div class="container">
<div class="hero-content text-center">
<div class="hero-content text-center animate-fade-in-up">
<h1 class="hero-title">{{ t('contact.title') }}</h1>
<p class="hero-subtitle">
{{ t('contact.subtitle') }}
@@ -82,7 +82,7 @@ useSeo({
<div class="container">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-2xl max-w-4xl mx-auto">
<!-- Contact Methods -->
<div class="card">
<div class="card animate-fade-in-up" style="animation-delay: 0.2s;">
<div class="card-body">
<h2 class="text-2xl font-bold mb-lg">{{ t('contact.quickContact') }}</h2>
<div class="space-y-md">
@@ -101,7 +101,7 @@ useSeo({
</div>
<!-- Social Links -->
<div class="card">
<div class="card animate-fade-in-up" style="animation-delay: 0.3s;">
<div class="card-body">
<h2 class="text-2xl font-bold mb-lg">{{ t('contact.findMeOn') }}</h2>
<div class="space-y-sm">
@@ -142,7 +142,7 @@ useSeo({
<!-- FAQ Section -->
<section class="faq-section">
<div class="container">
<div class="text-center mb-2xl">
<div class="text-center mb-2xl animate-fade-in-up" style="animation-delay: 0.4s;">
<h2 class="mb-lg">{{ t('contact.faq.title') }}</h2>
<p class="text-xl text-secondary max-w-2xl mx-auto">
{{ t('contact.faq.subtitle') }}
@@ -150,7 +150,7 @@ useSeo({
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-xl">
<div class="card text-center">
<div class="card text-center animate-fade-in-up" style="animation-delay: 0.5s;">
<div class="card-body">
<div class="faq-icon faq-icon-success">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -163,7 +163,7 @@ useSeo({
</div>
</div>
<div class="card text-center">
<div class="card text-center animate-fade-in-up" style="animation-delay: 0.6s;">
<div class="card-body">
<div class="faq-icon faq-icon-primary">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -177,7 +177,7 @@ useSeo({
</div>
</div>
<div class="card text-center">
<div class="card text-center animate-fade-in-up" style="animation-delay: 0.7s;">
<div class="card-body">
<div class="faq-icon faq-icon-secondary">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">

View File

@@ -20,33 +20,42 @@ useSeo({
description: t('seo.fiverr.description'),
keywords: 'fiverr services, discord bot development, minecraft plugin development, telegram bot creation, web development services, freelance developer, custom bot development, fiverr gigs',
ogImage: '/portfolio-preview.webp',
structuredData: {
'@context': 'https://schema.org',
'@type': 'Service',
'name': 'Professional Development Services on Fiverr',
'description': 'Custom Discord bot development, Minecraft plugins, Telegram bots, and web development services',
'provider': {
'@type': 'Person',
'name': 'Killian',
'jobTitle': 'Full Stack Developer'
structuredData: [
{
'@context': 'https://schema.org',
'@type': 'Service',
'name': 'Professional Development Services on Fiverr',
'description': 'Custom Discord bot development, Minecraft plugins, Telegram bots, and web development services',
'url': 'https://killiandalcin.fr/fiverr',
'provider': {
'@type': 'Person',
'name': 'Killian',
'jobTitle': 'Full Stack Developer',
'url': 'https://killiandalcin.fr'
},
'offers': siteConfig.value.fiverr.services.map(service => ({
'@type': 'Offer',
'name': t(`fiverr.serviceData.${service.id}.title`),
'description': t(`fiverr.serviceData.${service.id}.description`),
'price': service.price.replace('$', ''),
'priceCurrency': 'USD',
'url': service.url,
'availability': service.url !== '#' ? 'https://schema.org/InStock' : 'https://schema.org/PreOrder'
}))
},
'offers': siteConfig.value.fiverr.services.map(service => ({
'@type': 'Offer',
'name': t(`fiverr.serviceData.${service.id}.title`),
'description': t(`fiverr.serviceData.${service.id}.description`),
'price': service.price.replace('$', ''),
'priceCurrency': 'USD',
'url': service.url,
'availability': service.url !== '#' ? 'https://schema.org/InStock' : 'https://schema.org/PreOrder'
})),
'aggregateRating': {
{
'@type': 'AggregateRating',
'ratingValue': '5',
'bestRating': '5',
'worstRating': '1',
'reviewCount': '50+'
'itemReviewed': {
'@type': 'LocalBusiness',
'name': 'Professional Development Services on Fiverr'
},
'ratingValue': 5,
'bestRating': 5,
'worstRating': 1,
'ratingCount': 50,
'reviewCount': 50
}
}
]
})
const services = computed(() => siteConfig.value.fiverr.services)
@@ -90,30 +99,37 @@ const getServiceCardProps = (service: { id: string; price: string; url: string;
</script>
<template>
<main class="fiverr-page">
<main class="fiverr-page page-enter">
<!-- Hero Section -->
<FiverrHero :title="t('fiverr.title')" :subtitle="t('fiverr.subtitle')" :stats="heroStats"
:cta-url="siteConfig.fiverr.profileUrl" :cta-text="t('fiverr.profileCta')" />
<div class="animate-fade-in-up">
<FiverrHero :title="t('fiverr.title')" :subtitle="t('fiverr.subtitle')" :stats="heroStats"
:cta-url="siteConfig.fiverr.profileUrl" :cta-text="t('fiverr.profileCta')" />
</div>
<!-- Services Section -->
<section class="services-grid-section">
<div class="container">
<!-- Section Header -->
<div class="section-header text-center">
<div class="section-header text-center animate-fade-in-up" style="animation-delay: 0.2s;">
<h2 class="section-title">{{ t('fiverr.services.title') }}</h2>
<p class="section-subtitle">{{ t('fiverr.services.subtitle') }}</p>
</div>
<!-- Services Grid -->
<div class="services-grid">
<FiverrServiceCard v-for="service in services" :key="service.id" v-bind="getServiceCardProps(service)" />
<div v-for="(service, index) in services" :key="service.id" class="animate-fade-in-up"
:style="{ 'animation-delay': `${0.3 + index * 0.1}s` }">
<FiverrServiceCard v-bind="getServiceCardProps(service)" />
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<FiverrCta :title="t('fiverr.cta.title')" :subtitle="t('fiverr.cta.subtitle')"
:cta-url="siteConfig.fiverr.profileUrl" :cta-text="t('fiverr.cta.button')" />
<div class="animate-fade-in-up" style="animation-delay: 0.4s;">
<FiverrCta :title="t('fiverr.cta.title')" :subtitle="t('fiverr.cta.subtitle')"
:cta-url="siteConfig.fiverr.profileUrl" :cta-text="t('fiverr.cta.button')" />
</div>
</main>
</template>

170
src/views/FormationPage.vue Normal file
View File

@@ -0,0 +1,170 @@
<template>
<div class="formation-page page-enter">
<!-- Hero Section -->
<section class="hero-section">
<div class="container">
<div class="hero-content animate-fade-in-up">
<h1 class="hero-title">{{ $t('pricing.title') }}</h1>
<p class="hero-subtitle">{{ $t('pricing.subtitle') }}</p>
<!-- Billing Toggle -->
<div class="billing-toggle">
<span :class="{ active: billingType === 'monthly' }">{{ $t('pricing.monthly') }}</span>
<label class="toggle-switch">
<input type="checkbox" v-model="isAnnual" @change="toggleBilling">
<span class="slider"></span>
</label>
<span :class="{ active: billingType === 'annual' }">
{{ $t('pricing.annual') }}
<span class="discount-badge">-20%</span>
</span>
</div>
</div>
</div>
</section>
<!-- Pricing Cards -->
<section class="pricing-section">
<div class="container">
<div class="pricing-grid">
<div v-for="(plan, index) in pricingPlans" :key="plan.id" :class="['pricing-card', { popular: plan.popular }]"
class="animate-fade-in-up" :style="{ 'animation-delay': `${index * 0.1}s` }">
<div v-if="plan.popular" class="popular-badge">
{{ $t('pricing.mostPopular') }}
</div>
<div class="card-header">
<h3 class="plan-name">{{ $t(`pricing.plans.${plan.id}.name`) }}</h3>
<div class="plan-price">
<span class="currency"></span>
<span class="amount">{{ getCurrentPrice(plan) }}</span>
<span class="period">/{{ billingType === 'monthly' ? 'mois' : 'an' }}</span>
</div>
<p class="plan-description">{{ $t(`pricing.plans.${plan.id}.description`) }}</p>
</div>
<div class="card-body">
<ul class="features-list">
<li v-for="feature in plan.features" :key="feature" class="feature-item">
<svg class="check-icon" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd"
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
clip-rule="evenodd" />
</svg>
{{ $t(`pricing.features.${feature}`) }}
</li>
</ul>
<div class="card-actions">
<button :class="['cta-button', plan.popular ? 'primary' : 'secondary']">
{{ $t('pricing.startTrial') }}
</button>
<p class="trial-info">{{ $t('pricing.trialInfo') }}</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- FAQ Section -->
<section class="faq-section">
<div class="container">
<h2 class="section-title animate-fade-in-up">{{ $t('pricing.faq.title') }}</h2>
<div class="faq-grid">
<div v-for="(faq, index) in pricingFAQ" :key="faq.id" class="faq-item animate-fade-in-up"
:style="{ 'animation-delay': `${index * 0.1}s` }">
<h3 class="faq-question">{{ $t(`pricing.faq.items.${faq.id}.question`) }}</h3>
<p class="faq-answer">{{ $t(`pricing.faq.items.${faq.id}.answer`) }}</p>
</div>
</div>
</div>
</section>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useSeo } from '@/composables/useSeo'
// SEO
useSeo({
title: 'Tarifs - Formation Développement Web',
description: 'Découvrez nos plans de formation en développement web. Choisissez l\'abonnement qui vous convient avec des prix flexibles mensuels ou annuels.',
keywords: 'formation développement web, tarifs, abonnement, cours en ligne, prix'
})
// Billing state
const isAnnual = ref(false)
const billingType = computed(() => isAnnual.value ? 'annual' : 'monthly')
const toggleBilling = () => {
// The billingType is computed, no need to manually set it
}
// Pricing plans
const pricingPlans = [
{
id: 'starter',
popular: false,
monthlyPrice: 29,
annualPrice: 279, // 20% discount
features: [
'basicCourses',
'communityAccess',
'mobileApp',
'basicSupport',
'certificates'
]
},
{
id: 'pro',
popular: true,
monthlyPrice: 59,
annualPrice: 567, // 20% discount
features: [
'allCourses',
'liveWorkshops',
'mentorship',
'prioritySupport',
'certificates',
'jobBoard',
'portfolioReview'
]
},
{
id: 'expert',
popular: false,
monthlyPrice: 99,
annualPrice: 950, // 20% discount
features: [
'everythingPro',
'oneOnOneCoaching',
'customProjects',
'internshipPlacement',
'careerGuidance',
'exclusiveContent',
'networkingEvents'
]
}
]
// FAQ data
const pricingFAQ = [
{ id: 'trial' },
{ id: 'cancel' },
{ id: 'refund' },
{ id: 'upgrade' },
{ id: 'certificates' },
{ id: 'support' }
]
// Helper function to get current price
const getCurrentPrice = (plan: { monthlyPrice: number; annualPrice: number }) => {
return billingType.value === 'monthly' ? plan.monthlyPrice : plan.annualPrice
}
</script>
<style scoped>
@import './styles/FormationPage.css';
</style>

View File

@@ -2,11 +2,41 @@
import { computed } from 'vue'
import { useSeo } from '@/composables/useSeo'
import { useI18n } from '@/composables/useI18n'
import { useProjects } from '@/composables/useProjects'
import ProjectCard from '@/components/ProjectCard.vue'
import HeroSection from '@/components/sections/HeroSection.vue'
import FeaturedProjectsSection from '@/components/sections/FeaturedProjectsSection.vue'
import ServicesSection from '@/components/sections/ServicesSection.vue'
import TestimonialsSection from '@/components/TestimonialsSection.vue'
import ServiceFAQ from '@/components/ServiceFAQ.vue'
import CTASection from '@/components/sections/CTASection.vue'
import { testimonials, testimonialsStats } from '@/data/testimonials'
import frLocale from '@/locales/fr'
import enLocale from '@/locales/en'
const { t } = useI18n()
const { projects } = useProjects()
const { t, currentLocale } = useI18n()
// Get translated FAQs using computed with direct locale access
const homeFAQs = computed(() => {
const locale = currentLocale.value === 'fr' ? frLocale : enLocale
const faqData = locale.faq.homeFaq
return [
{
question: faqData.delivery.question,
answer: faqData.delivery.answer,
features: faqData.delivery.features
},
{
question: faqData.maintenance.question,
answer: faqData.maintenance.answer,
features: faqData.maintenance.features
},
{
question: faqData.companies.question,
answer: faqData.companies.answer,
features: faqData.companies.features
}
]
})
// Enhanced SEO with structured data
useSeo({
@@ -37,168 +67,33 @@ useSeo({
}
}
})
// Featured projects
const featuredProjects = computed(() => {
return projects.value.filter(project => project.featured).slice(0, 3)
})
// Services data
const services = computed(() => [
{
icon: 'M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z',
color: 'var(--color-primary)',
title: t('home.services.webDev.title'),
description: t('home.services.webDev.description')
},
{
icon: 'M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z',
color: 'var(--color-secondary)',
title: t('home.services.mobileApps.title'),
description: t('home.services.mobileApps.description')
},
{
icon: 'M13 10V3L4 14h7v7l9-11h-7z',
color: 'var(--color-success)',
title: t('home.services.optimization.title'),
description: t('home.services.optimization.description')
},
{
icon: 'M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z',
color: 'var(--color-warning)',
title: t('home.services.maintenance.title'),
description: t('home.services.maintenance.description')
}
])
</script>
<template>
<main>
<main class="page-enter">
<!-- Hero Section -->
<section class="hero">
<div class="container">
<div class="hero-content animate-fade-in-up">
<h1 class="hero-title">
{{ t('home.title') }}
</h1>
<p class="hero-subtitle">
{{ t('home.subtitle') }}
</p>
<div class="flex flex-col sm:flex-row gap-md justify-center">
<RouterLink to="/projects" class="btn btn-primary btn-lg">
{{ t('home.cta.viewProjects') }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6">
</path>
</svg>
</RouterLink>
<RouterLink to="/fiverr" class="btn btn-secondary btn-lg">
{{ t('nav.fiverr') }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z">
</path>
</svg>
</RouterLink>
<RouterLink to="/contact" class="btn btn-secondary btn-lg">
{{ t('home.cta.contactMe') }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z">
</path>
</svg>
</RouterLink>
</div>
</div>
</div>
</section>
<HeroSection />
<!-- Featured Projects Section -->
<section class="section">
<div class="container">
<div class="text-center mb-2xl">
<h2 class="mb-lg">{{ t('home.featuredProjects.title') }}</h2>
<p class="text-xl text-secondary max-w-2xl mx-auto">
{{ t('home.featuredProjects.subtitle') }}
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-xl mb-2xl">
<ProjectCard v-for="project in featuredProjects" :key="project.id" :project="project"
class="animate-fade-in-up" />
</div>
<div class="text-center">
<RouterLink to="/projects" class="btn btn-secondary">
{{ t('home.featuredProjects.viewAll') }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
</svg>
</RouterLink>
</div>
</div>
</section>
<FeaturedProjectsSection />
<!-- Services Section -->
<section class="services-section">
<div class="container">
<div class="text-center mb-2xl">
<h2 class="mb-lg">{{ t('home.services.title') }}</h2>
<p class="text-xl text-secondary max-w-2xl mx-auto">
{{ t('home.services.subtitle') }}
</p>
</div>
<ServicesSection />
<div class="grid grid-cols-1 md:grid-cols-2 gap-xl">
<div v-for="(service, index) in services" :key="index" class="card animate-fade-in-up"
:style="{ 'animation-delay': `${index * 0.1}s` }">
<div class="card-body">
<div class="flex items-start">
<div class="service-icon" :style="{ background: service.color, color: 'var(--text-inverse)' }">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" :d="service.icon"></path>
</svg>
</div>
<div>
<h3 class="text-xl font-bold mb-md">{{ service.title }}</h3>
<p class="text-secondary">{{ service.description }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Testimonials Section -->
<TestimonialsSection :title="t('testimonials.title')" :subtitle="t('testimonials.subtitle')"
:testimonials="testimonials" :stats="testimonialsStats"
:stats-labels="{ clients: t('testimonials.stats.clients'), rating: t('testimonials.stats.rating'), projects: t('testimonials.stats.projects') }"
:cta-title="t('testimonials.ctaTitle')" :cta-subtitle="t('testimonials.ctaSubtitle')"
:cta-text="t('testimonials.ctaText')" :cta-link="'/contact'" :reviews-link="t('testimonials.reviewsLink')"
:reviews-text="t('testimonials.reviewsText')" />
<!-- FAQ Section -->
<ServiceFAQ :title="t('faq.title')" :subtitle="t('faq.subtitle')" :faqs="homeFAQs" :cta-title="t('faq.ctaTitle')"
:cta-subtitle="t('faq.ctaSubtitle')" :cta-text="t('faq.ctaText')" :cta-link="'/contact'" />
<!-- CTA Section -->
<section class="section">
<div class="container">
<div class="text-center">
<h2 class="mb-lg">{{ t('home.cta2.title') }}</h2>
<p class="text-xl text-secondary max-w-2xl mx-auto mb-2xl">
{{ t('home.cta2.subtitle') }}
</p>
<div class="flex flex-col sm:flex-row gap-md justify-center">
<RouterLink to="/contact" class="btn btn-primary btn-lg">
{{ t('home.cta2.startProject') }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z">
</path>
</svg>
</RouterLink>
<RouterLink to="/about" class="btn btn-secondary btn-lg">
{{ t('home.cta2.learnMore') }}
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z">
</path>
</svg>
</RouterLink>
</div>
</div>
</div>
</section>
<CTASection />
</main>
</template>

View File

@@ -8,6 +8,7 @@ import { useI18n } from '@/composables/useI18n'
import { useGallery } from '@/composables/useGallery'
import TechBadge from '@/components/TechBadge.vue'
import GalleryModal from '@/components/GalleryModal.vue'
import CTAButtons from '@/components/shared/CTAButtons.vue'
const route = useRoute()
const router = useRouter()
@@ -67,11 +68,11 @@ onMounted(() => {
</script>
<template>
<main v-if="project" class="project-detail-page">
<main v-if="project" class="project-detail-page page-enter">
<!-- Hero Section - Redesigned -->
<section class="project-hero">
<div class="container">
<div class="hero-content">
<div class="hero-content animate-fade-in-up">
<!-- Navigation -->
<nav class="breadcrumb">
<button @click="goBack" class="breadcrumb-link">
@@ -100,7 +101,7 @@ onMounted(() => {
<p class="project-description">{{ project.description }}</p>
<!-- Actions -->
<div class="project-actions">
<CTAButtons layout="row">
<a v-if="project.demoUrl" :href="project.demoUrl" target="_blank" rel="noopener noreferrer"
class="btn btn-primary">
<svg class="btn-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -137,7 +138,7 @@ onMounted(() => {
</svg>
{{ t('projects.projectDetail.share') }}
</button>
</div>
</CTAButtons>
</div>
</div>
</div>
@@ -196,7 +197,8 @@ onMounted(() => {
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z">
</path>
</svg>
</div>
</div>
@@ -225,11 +227,6 @@ onMounted(() => {
<span class="info-label">{{ t('projects.projectDetail.status') }}</span>
<span class="info-value">{{ project.status }}</span>
</div>
<!-- <div v-if="project.duration" class="info-item">
<span class="info-label">Durée</span>
<span class="info-value">{{ project.duration }}</span>
</div> -->
</div>
</div>

View File

@@ -4,6 +4,7 @@ import { useSeo } from '@/composables/useSeo'
import { useI18n } from '@/composables/useI18n'
import { useProjects } from '@/composables/useProjects'
import ProjectCard from '@/components/ProjectCard.vue'
import CTAButtons from '@/components/shared/CTAButtons.vue'
const { t } = useI18n()
const { projects } = useProjects()
@@ -80,11 +81,11 @@ const featuredProjects = computed(() => projects.value.filter(p => p.featured).l
</script>
<template>
<main class="projects-page">
<main class="projects-page page-enter">
<!-- Hero Section -->
<section class="projects-hero">
<div class="container">
<div class="hero-content text-center">
<div class="hero-content text-center animate-fade-in-up">
<h1 class="hero-title">{{ t('projects.title') }}</h1>
<p class="hero-subtitle">
{{ t('projects.subtitle') }}
@@ -112,7 +113,7 @@ const featuredProjects = computed(() => projects.value.filter(p => p.featured).l
<!-- Filters Section -->
<section class="filters-section">
<div class="container">
<div class="filters-container">
<div class="filters-container animate-fade-in-up" style="animation-delay: 0.2s;">
<!-- Search -->
<div class="search-container">
<div class="search-input-wrapper">
@@ -151,7 +152,7 @@ const featuredProjects = computed(() => projects.value.filter(p => p.featured).l
<section class="projects-grid-section">
<div class="container">
<!-- Results Info -->
<div class="results-info">
<div class="results-info animate-fade-in-up" style="animation-delay: 0.3s;">
<p class="results-text">
{{ filteredProjects.length }} {{ t('nav.projects').toLowerCase() }}{{ filteredProjects.length > 1 ? 's' : ''
}} {{ t('common.search').toLowerCase() }}{{ filteredProjects.length > 1 ? 's' : '' }}
@@ -176,9 +177,11 @@ const featuredProjects = computed(() => projects.value.filter(p => p.featured).l
<p class="no-results-description">
{{ t('projects.noResults.description') }}
</p>
<button @click="searchQuery = ''; selectedCategory = 'all'" class="btn btn-primary">
{{ t('common.reset') }}
</button>
<CTAButtons layout="stack">
<button @click="searchQuery = ''; selectedCategory = 'all'" class="btn btn-primary">
{{ t('common.reset') }}
</button>
</CTAButtons>
</div>
</div>
</div>

View File

@@ -0,0 +1,435 @@
.formation-page {
min-height: 100vh;
background: linear-gradient(135deg, var(--bg-primary) 0%, var(--bg-secondary) 100%);
padding-top: 80px;
color: var(--text-primary);
}
/* Hero Section */
.hero-section {
padding: var(--space-4xl) 0 var(--space-2xl);
text-align: center;
}
.hero-title {
font-size: var(--font-size-5xl);
font-weight: var(--font-weight-extrabold);
color: var(--text-primary);
margin-bottom: var(--space-md);
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.hero-subtitle {
font-size: var(--font-size-xl);
color: var(--text-secondary);
margin-bottom: var(--space-3xl);
max-width: 600px;
margin-left: auto;
margin-right: auto;
line-height: var(--line-height-relaxed);
}
/* Billing Toggle */
.billing-toggle {
display: flex;
align-items: center;
justify-content: center;
gap: var(--space-md);
margin-bottom: var(--space-2xl);
background: var(--bg-tertiary);
padding: var(--space-md) var(--space-2xl);
border-radius: var(--border-radius-full);
border: var(--border-width) solid var(--border-color);
display: inline-flex;
box-shadow: var(--shadow-md);
}
.billing-toggle span {
color: var(--text-secondary);
font-weight: var(--font-weight-medium);
transition: var(--transition-normal);
}
.billing-toggle span.active {
color: var(--text-primary);
font-weight: var(--font-weight-semibold);
}
.discount-badge {
background: var(--color-success);
color: var(--text-inverse);
padding: var(--space-xs) var(--space-sm);
border-radius: var(--border-radius-md);
font-size: var(--font-size-xs);
font-weight: var(--font-weight-semibold);
margin-left: var(--space-sm);
}
/* Toggle Switch */
.toggle-switch {
position: relative;
display: inline-block;
width: 60px;
height: 30px;
}
.toggle-switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: var(--color-gray-300);
transition: var(--transition-normal);
border-radius: 30px;
}
.dark .slider {
background-color: var(--color-gray-600);
}
.slider:before {
position: absolute;
content: '';
height: 22px;
width: 22px;
left: 4px;
bottom: 4px;
background-color: var(--bg-primary);
transition: var(--transition-normal);
border-radius: 50%;
}
input:checked + .slider {
background-color: var(--color-primary);
}
input:checked + .slider:before {
transform: translateX(30px);
}
/* Pricing Section */
.pricing-section {
padding: var(--space-2xl) 0 var(--space-4xl);
}
.pricing-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-xl);
max-width: 1600px;
margin: 0 auto;
padding: 0 var(--space-md);
align-items: stretch;
}
/* Pricing Cards */
.pricing-card {
background: var(--bg-primary);
border-radius: var(--border-radius-2xl);
padding: var(--space-2xl);
position: relative;
box-shadow: var(--shadow-xl);
transition: var(--transition-normal);
border: 2px solid transparent;
display: flex;
flex-direction: column;
height: 100%;
min-width: 0;
}
.pricing-card:hover {
transform: translateY(-10px);
box-shadow: var(--shadow-2xl);
}
.pricing-card.popular {
border-color: var(--color-primary);
transform: scale(1.05);
box-shadow: 0 25px 50px rgba(133, 203, 133, 0.2);
}
.dark .pricing-card.popular {
box-shadow: 0 25px 50px rgba(163, 214, 163, 0.2);
}
.pricing-card.popular:hover {
transform: scale(1.05) translateY(-10px);
}
.popular-badge {
position: absolute;
top: -15px;
left: 50%;
transform: translateX(-50%);
background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark));
color: var(--text-inverse);
padding: var(--space-sm) var(--space-lg);
border-radius: 25px;
font-size: var(--font-size-sm);
font-weight: var(--font-weight-semibold);
box-shadow: 0 4px 12px rgba(133, 203, 133, 0.3);
}
.dark .popular-badge {
box-shadow: 0 4px 12px rgba(163, 214, 163, 0.3);
}
/* Card Header */
.card-header {
text-align: center;
margin-bottom: var(--space-2xl);
}
.plan-name {
font-size: var(--font-size-2xl);
font-weight: var(--font-weight-bold);
color: var(--text-primary);
margin-bottom: var(--space-md);
}
.plan-price {
display: flex;
align-items: baseline;
justify-content: center;
margin-bottom: var(--space-md);
}
.currency {
font-size: var(--font-size-xl);
font-weight: var(--font-weight-semibold);
color: var(--text-secondary);
}
.amount {
font-size: var(--font-size-5xl);
font-weight: var(--font-weight-bold);
color: var(--text-primary);
margin: 0 var(--space-xs);
}
.period {
font-size: var(--font-size-base);
color: var(--text-secondary);
}
.plan-description {
color: var(--text-secondary);
line-height: var(--line-height-relaxed);
margin-bottom: 0;
}
/* Card Body */
.card-body {
flex: 1;
display: flex;
flex-direction: column;
}
/* Features List */
.features-list {
list-style: none;
padding: 0;
margin: 0 0 var(--space-lg) 0;
flex: 1;
}
.feature-item {
display: flex;
align-items: center;
padding: var(--space-md) 0;
border-bottom: var(--border-width) solid var(--border-color);
}
.feature-item:last-child {
border-bottom: none;
}
.check-icon {
width: 20px;
height: 20px;
color: var(--color-success);
margin-right: var(--space-md);
flex-shrink: 0;
}
/* Card Actions */
.card-actions {
margin-top: auto;
padding-top: var(--space-xl);
}
/* CTA Button */
.cta-button {
width: 100%;
padding: var(--space-md) var(--space-2xl);
border: none;
border-radius: var(--border-radius-lg);
font-size: var(--font-size-lg);
font-weight: var(--font-weight-semibold);
cursor: pointer;
transition: var(--transition-normal);
margin-bottom: var(--space-md);
box-shadow: var(--shadow-sm);
}
.cta-button.primary {
background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark));
color: var(--text-inverse);
box-shadow: 0 4px 12px rgba(133, 203, 133, 0.3);
}
.dark .cta-button.primary {
box-shadow: 0 4px 12px rgba(163, 214, 163, 0.3);
}
.cta-button.primary:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(133, 203, 133, 0.4);
}
.dark .cta-button.primary:hover {
box-shadow: 0 6px 20px rgba(163, 214, 163, 0.4);
}
.cta-button.secondary {
background: var(--bg-secondary);
color: var(--text-primary);
border: 2px solid var(--border-color);
}
.cta-button.secondary:hover {
background: var(--bg-tertiary);
border-color: var(--color-primary);
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
.trial-info {
text-align: center;
color: var(--text-tertiary);
font-size: var(--font-size-sm);
margin: 0;
}
/* FAQ Section */
.faq-section {
background: var(--bg-secondary);
padding: var(--space-4xl) 0;
border-top: var(--border-width) solid var(--border-color);
}
.section-title {
text-align: center;
font-size: var(--font-size-4xl);
font-weight: var(--font-weight-bold);
color: var(--text-primary);
margin-bottom: var(--space-3xl);
}
.faq-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: var(--space-2xl);
max-width: 1000px;
margin: 0 auto;
padding: 0 var(--space-md);
}
.faq-item {
background: var(--bg-primary);
padding: var(--space-2xl);
border-radius: var(--border-radius-xl);
border: var(--border-width) solid var(--border-color);
box-shadow: var(--shadow-md);
transition: var(--transition-normal);
}
.faq-item:hover {
box-shadow: var(--shadow-lg);
transform: translateY(-2px);
}
.faq-question {
color: var(--text-primary);
font-size: var(--font-size-xl);
font-weight: var(--font-weight-semibold);
margin-bottom: var(--space-md);
}
.faq-answer {
color: var(--text-secondary);
line-height: var(--line-height-relaxed);
margin: 0;
}
/* Container */
.container {
max-width: 1600px;
margin: 0 auto;
padding: 0 var(--space-md);
}
/* Responsive Design */
@media (max-width: 1024px) {
.pricing-grid {
grid-template-columns: 1fr;
gap: var(--space-xl);
max-width: 500px;
}
.pricing-card.popular {
transform: none;
}
.pricing-card.popular:hover {
transform: translateY(-10px);
}
}
@media (max-width: 768px) {
.hero-title {
font-size: var(--font-size-4xl);
}
.billing-toggle {
flex-direction: column;
gap: var(--space-sm);
padding: var(--space-lg);
}
.faq-grid {
grid-template-columns: 1fr;
gap: var(--space-lg);
}
}
@media (max-width: 480px) {
.hero-title {
font-size: var(--font-size-3xl);
}
.amount {
font-size: var(--font-size-4xl);
}
.pricing-card {
padding: var(--space-lg);
}
.faq-grid {
grid-template-columns: 1fr;
gap: var(--space-md);
}
.faq-item {
padding: var(--space-lg);
}
}

View File

@@ -6,6 +6,43 @@
padding: var(--space-4xl) 0;
}
/* Services Grid - 2x2 Layout */
.services-grid {
display: grid;
grid-template-columns: 1fr;
gap: 2rem;
margin-bottom: 3rem;
}
@media (min-width: 768px) {
.services-grid {
grid-template-columns: repeat(2, 1fr);
gap: 2rem;
}
}
/* Projects Grid - 3 Columns */
.projects-grid {
display: grid;
grid-template-columns: 1fr;
gap: 2rem;
margin-bottom: 3rem;
}
@media (min-width: 768px) {
.projects-grid {
grid-template-columns: repeat(2, 1fr);
gap: 2rem;
}
}
@media (min-width: 1024px) {
.projects-grid {
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
}
}
/* Service Icons */
.service-icon {
width: 3rem;