From bed824059a9fa1bfda7fe9d699df562e1822bb9f Mon Sep 17 00:00:00 2001 From: SarTron-NorthBlue Date: Fri, 14 Nov 2025 16:15:21 +0400 Subject: [PATCH] Initialize Next.js project with essential configurations and components - Added .gitignore to exclude unnecessary files and directories. - Created next.config.js for Next.js configuration. - Set up package.json and package-lock.json with dependencies including Next.js, React, and TypeScript. - Implemented Tailwind CSS for styling with a dedicated tailwind.config.ts. - Developed core application structure including layout, pages, and components for header, footer, and various sections (Hero, Services, Pricing, etc.). - Integrated contact form functionality using nodemailer for email handling. - Established global styles in globals.css and added animations with Framer Motion. - Included README.md for project documentation and setup instructions. --- .gitignore | 36 + README.md | 65 + app/api/contact/route.ts | 169 +++ app/globals.css | 114 ++ app/layout.tsx | 32 + app/page.tsx | 22 + components/BackgroundAnimations.tsx | 75 + components/Footer.tsx | 130 ++ components/Header.tsx | 124 ++ components/sections/Contact.tsx | 312 ++++ components/sections/Encryption.tsx | 97 ++ components/sections/FAQ.tsx | 113 ++ components/sections/Hero.tsx | 112 ++ components/sections/Pricing.tsx | 164 ++ components/sections/Services.tsx | 118 ++ components/sections/Stats.tsx | 75 + components/sections/Timeline.tsx | 129 ++ lib/stats.ts | 45 + next.config.js | 7 + package-lock.json | 2155 +++++++++++++++++++++++++++ package.json | 28 + postcss.config.js | 7 + tailwind.config.ts | 72 + tsconfig.json | 28 + 24 files changed, 4229 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 app/api/contact/route.ts create mode 100644 app/globals.css create mode 100644 app/layout.tsx create mode 100644 app/page.tsx create mode 100644 components/BackgroundAnimations.tsx create mode 100644 components/Footer.tsx create mode 100644 components/Header.tsx create mode 100644 components/sections/Contact.tsx create mode 100644 components/sections/Encryption.tsx create mode 100644 components/sections/FAQ.tsx create mode 100644 components/sections/Hero.tsx create mode 100644 components/sections/Pricing.tsx create mode 100644 components/sections/Services.tsx create mode 100644 components/sections/Stats.tsx create mode 100644 components/sections/Timeline.tsx create mode 100644 lib/stats.ts create mode 100644 next.config.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 postcss.config.js create mode 100644 tailwind.config.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1403e90 --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + diff --git a/README.md b/README.md new file mode 100644 index 0000000..04fad9a --- /dev/null +++ b/README.md @@ -0,0 +1,65 @@ +# Runlock.re - Site Web Next.js + +Site web moderne pour Runlock.re, expert Vaultwarden à la Réunion. + +## 🚀 Technologies + +- **Next.js 14** - Framework React +- **TypeScript** - Typage statique +- **Tailwind CSS** - Styling +- **Framer Motion** - Animations +- **Lucide React** - Icônes + +## 📦 Installation + +```bash +# Installer les dépendances +npm install + +# Lancer le serveur de développement +npm run dev + +# Build pour la production +npm run build + +# Lancer en production +npm start +``` + +## 🎨 Fonctionnalités + +- ✨ Animations fluides avec Framer Motion +- 🎯 Design moderne orienté sécurité +- 📱 Responsive design +- ⚡ Performance optimisée +- 🔒 Thème sombre sécurisé + +## 📄 Structure + +``` +├── app/ +│ ├── layout.tsx # Layout principal +│ ├── page.tsx # Page d'accueil +│ └── globals.css # Styles globaux +├── components/ +│ ├── Header.tsx # Navigation +│ ├── Footer.tsx # Pied de page +│ └── sections/ # Sections de la page +│ ├── Hero.tsx +│ ├── Stats.tsx +│ ├── Services.tsx +│ ├── Encryption.tsx +│ ├── Timeline.tsx +│ ├── Pricing.tsx +│ ├── FAQ.tsx +│ └── Contact.tsx +└── ... +``` + +## 🌐 Déploiement + +Le site peut être déployé sur : +- Vercel (recommandé pour Next.js) +- Netlify +- Tout hébergeur supportant Node.js + diff --git a/app/api/contact/route.ts b/app/api/contact/route.ts new file mode 100644 index 0000000..2419f37 --- /dev/null +++ b/app/api/contact/route.ts @@ -0,0 +1,169 @@ +import { NextRequest, NextResponse } from 'next/server' +import nodemailer from 'nodemailer' + +export async function POST(request: NextRequest) { + try { + const body = await request.json() + const { name, email, company, service, message } = body + + // Validation des champs requis + if (!name || !email || !service || !message) { + return NextResponse.json( + { error: 'Tous les champs requis doivent être remplis.' }, + { status: 400 } + ) + } + + // Validation de l'email + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ + if (!emailRegex.test(email)) { + return NextResponse.json( + { error: 'Adresse email invalide.' }, + { status: 400 } + ) + } + + // Configuration du transporteur SMTP OVH + const transporter = nodemailer.createTransport({ + host: process.env.SMTP_HOST || 'ssl0.ovh.net', + port: parseInt(process.env.SMTP_PORT || '465'), + secure: true, // true pour le port 465, false pour les autres ports + auth: { + user: process.env.SMTP_USER, // L'email d'envoi OVH + pass: process.env.SMTP_PASSWORD, // Le mot de passe de l'email OVH + }, + }) + + // Configuration de l'email + const mailOptions = { + from: process.env.SMTP_FROM || process.env.SMTP_USER, + to: 'contact@runlock.re', + replyTo: email, + subject: `[Runlock.re] Nouvelle demande de contact - ${service}`, + html: ` + + + + + + + +
+

Nouvelle demande de contact

+ +
+ Nom : + ${name} +
+ +
+ Email : + ${email} +
+ + ${company ? ` +
+ Entreprise : + ${company} +
+ ` : ''} + +
+ Service : + ${service} +
+ +
+ Message :

+ ${message.replace(/\n/g, '
')} +
+ + +
+ + + `, + text: ` +Nouvelle demande de contact - Runlock.re + +Nom: ${name} +Email: ${email} +${company ? `Entreprise: ${company}\n` : ''} +Service: ${service} + +Message: +${message} + +--- +Cet email a été envoyé depuis le formulaire de contact de runlock.re +Vous pouvez répondre directement à cet email pour contacter ${name} + `, + } + + // Envoi de l'email + await transporter.sendMail(mailOptions) + + return NextResponse.json( + { message: 'Votre message a été envoyé avec succès !' }, + { status: 200 } + ) + } catch (error) { + console.error('Erreur lors de l\'envoi de l\'email:', error) + return NextResponse.json( + { error: 'Une erreur est survenue lors de l\'envoi de votre message. Veuillez réessayer.' }, + { status: 500 } + ) + } +} + diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..020c75f --- /dev/null +++ b/app/globals.css @@ -0,0 +1,114 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + html { + scroll-behavior: smooth; + } + + body { + @apply bg-security-darker text-gray-100 antialiased; + } +} + +@layer components { + .gradient-text { + @apply bg-gradient-to-r from-security-accent via-green-400 to-emerald-400 bg-clip-text text-transparent; + } + + .gradient-bg { + @apply bg-gradient-to-br from-security-darker via-security-dark to-security-darker; + } + + .security-glow { + box-shadow: 0 0 30px rgba(0, 255, 136, 0.3), 0 0 60px rgba(0, 255, 136, 0.1); + } + + .card-hover { + @apply transition-all duration-300 hover:scale-105 hover:shadow-2xl hover:shadow-security-accent/20; + } + + .section-padding { + @apply py-24 px-4 sm:px-6 lg:px-8; + } + + .glass-effect { + @apply bg-security-card/80 backdrop-blur-lg border border-security-border/50; + } + + .neon-border { + @apply border-2 border-security-accent/40 shadow-lg shadow-security-accent/20; + } + + .card-dark { + @apply bg-security-card border border-security-border rounded-2xl; + } + + /* Animations de fond */ + .animated-grid { + background-image: + linear-gradient(to right, rgba(26, 26, 36, 0.3) 1px, transparent 1px), + linear-gradient(to bottom, rgba(26, 26, 36, 0.3) 1px, transparent 1px); + background-size: 4rem 4rem; + animation: gridMove 20s linear infinite; + } + + .floating-blob { + animation: float 20s ease-in-out infinite; + } + + .pulse-glow { + animation: pulseGlow 4s ease-in-out infinite; + } + + .gradient-shift { + animation: gradientShift 8s ease infinite; + background-size: 200% 200%; + } +} + +@keyframes gridMove { + 0% { + background-position: 0 0; + } + 100% { + background-position: 4rem 4rem; + } +} + +@keyframes float { + 0%, 100% { + transform: translateY(0px) translateX(0px); + } + 33% { + transform: translateY(-30px) translateX(20px); + } + 66% { + transform: translateY(20px) translateX(-20px); + } +} + +@keyframes pulseGlow { + 0%, 100% { + opacity: 0.5; + transform: scale(1); + } + 50% { + opacity: 0.8; + transform: scale(1.1); + } +} + +@keyframes gradientShift { + 0% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0% 50%; + } +} + diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..9442370 --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,32 @@ +import type { Metadata } from 'next' +import { Inter } from 'next/font/google' +import './globals.css' +import Header from '@/components/Header' +import Footer from '@/components/Footer' + +const inter = Inter({ subsets: ['latin'] }) + +export const metadata: Metadata = { + title: 'Runlock.re - Expert Vaultwarden à la Réunion | Sécurisez vos mots de passe', + description: 'Expert Vaultwarden à la Réunion - Hébergement sécurisé, installation NAS et Mini PC. Solutions de gestion de mots de passe pour entreprises 974.', + keywords: 'Vaultwarden, Réunion, gestionnaire de mots de passe, sécurité, NAS, Bitwarden', +} + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + +
+
+ {children} +
+