Pour tout problème contactez-nous par mail : support@froggit.fr | La FAQ :grey_question: | Rejoignez-nous sur le Chat :speech_balloon:

Skip to content
Snippets Groups Projects
Commit 741134db authored by LENIX.IO's avatar LENIX.IO
Browse files

initial commit

parents
No related branches found
No related tags found
No related merge requests found
Showing with 579 additions and 0 deletions
{
"template": "bolt-vite-react-ts"
}
For all designs I ask you to make, have them be beautiful, not cookie cutter. Make webpages that are fully featured and worthy for production.
By default, this template supports JSX syntax with Tailwind CSS classes, React hooks, and Lucide React for icons. Do not install other packages for UI themes, icons, etc unless absolutely necessary or I request them.
Use icons from lucide-react for logos.
Use stock photos from unsplash where appropriate, only valid URLs you know exist. Do not download the images, only link to them in image tags.
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import tseslint from 'typescript-eslint';
export default tseslint.config(
{ ignores: ['dist'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
);
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>LENIX.IO - Solutions DevOps & Administration Linux</title>
<meta name="description" content="Expert en solutions DevOps, infrastructure cloud, CI/CD, et administration Linux. Optimisez votre infrastructure IT avec LENIX.IO." />
<meta name="keywords" content="DevOps, Linux, Cloud, CI/CD, Automatisation, Sécurité IT, Infrastructure" />
<script src="https://apps.elfsight.com/p/platform.js" defer></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
{
"name": "vite-react-typescript-starter",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"lucide-react": "^0.344.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@eslint/js": "^9.9.1",
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.18",
"eslint": "^9.9.1",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.11",
"globals": "^15.9.0",
"postcss": "^8.4.35",
"tailwindcss": "^3.4.1",
"typescript": "^5.5.3",
"typescript-eslint": "^8.3.0",
"vite": "^5.4.2"
}
}
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
import React from 'react';
import Header from './components/Header';
import Hero from './components/Hero';
import Services from './components/Services';
import ClientLogos from './components/ClientLogos';
import Testimonials from './components/Testimonials';
import Footer from './components/Footer';
function App() {
return (
<div className="min-h-screen">
<Header />
<Hero />
<Services />
<ClientLogos />
<Testimonials />
<Footer />
</div>
);
}
export default App;
\ No newline at end of file
import React, { useEffect, useRef } from 'react';
const clients = [
'Charligroup', 'Sagemcom', 'RTE', 'Thales', 'Apple',
'Charligroup', 'Sagemcom', 'RTE', 'Thales', 'Apple' // Duplicated for infinite scroll
];
const ClientLogos = () => {
const sectionRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('appear');
}
});
},
{
threshold: 0.1
}
);
if (sectionRef.current) {
observer.observe(sectionRef.current);
}
return () => observer.disconnect();
}, []);
return (
<div className="bg-white py-12 overflow-hidden">
<div className="max-w-7xl mx-auto px-4">
<h2 className="text-center text-3xl font-bold text-slate-800 mb-12 slide-in slide-in-from-bottom">
Ils nous font confiance
</h2>
<div className="relative slide-in slide-in-from-bottom" ref={sectionRef}>
<div className="flex space-x-12 animate-scroll">
{clients.map((client, index) => (
<div
key={index}
className="flex-none w-48 h-20 bg-slate-50 rounded-lg flex items-center justify-center"
>
<span className="text-xl font-semibold text-slate-700">{client}</span>
</div>
))}
</div>
</div>
</div>
</div>
);
};
export default ClientLogos;
\ No newline at end of file
import React from 'react';
import { Server, Github, Linkedin } from 'lucide-react';
const Footer = () => {
const currentYear = new Date().getFullYear();
return (
<footer className="bg-slate-900 text-white py-12">
<div className="container mx-auto px-4">
<div className="flex flex-col md:flex-row justify-between items-center">
<div className="flex items-center space-x-2 mb-6 md:mb-0">
<Server className="h-8 w-8 text-indigo-400" />
<span className="text-2xl font-bold">LENIX.IO</span>
</div>
<div className="flex space-x-6">
<a
href="https://github.com/lenix-io"
target="_blank"
rel="noopener noreferrer"
className="hover:text-indigo-400 transition-colors"
>
<Github className="h-6 w-6" />
</a>
<a
href="https://linkedin.com/company/lenix-io"
target="_blank"
rel="noopener noreferrer"
className="hover:text-indigo-400 transition-colors"
>
<Linkedin className="h-6 w-6" />
</a>
</div>
</div>
<div className="mt-8 pt-8 border-t border-slate-800 text-center text-slate-400">
<p>&copy; {currentYear} LENIX.IO. Tous droits réservés.</p>
</div>
</div>
</footer>
);
};
export default Footer;
\ No newline at end of file
import React, { useState, useEffect } from 'react';
import { Server, Menu, X } from 'lucide-react';
const Header = () => {
const [isScrolled, setIsScrolled] = useState(false);
const [isMenuOpen, setIsMenuOpen] = useState(false);
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 0);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
return (
<header className={`fixed w-full z-50 transition-all duration-300 ${
isScrolled ? 'bg-white/80 backdrop-blur-lg shadow-md' : 'bg-transparent'
}`}>
<div className="container mx-auto px-4">
<div className="flex items-center justify-between h-20">
<div className="flex items-center space-x-2">
<Server className="h-8 w-8 text-indigo-600" />
<span className="text-2xl font-bold text-slate-800">LENIX.IO</span>
</div>
<nav className="hidden md:flex items-center space-x-8">
<a href="#services" className="text-slate-700 hover:text-indigo-600">Services</a>
<a href="#about" className="text-slate-700 hover:text-indigo-600">À propos</a>
<a href="#testimonials" className="text-slate-700 hover:text-indigo-600">Témoignages</a>
<a
href="https://calendly.com/lenix-io"
target="_blank"
rel="noopener noreferrer"
className="bg-indigo-600 text-white px-6 py-2 rounded-lg hover:bg-indigo-700 transition-colors"
>
Planifier un appel
</a>
</nav>
<button
className="md:hidden"
onClick={() => setIsMenuOpen(!isMenuOpen)}
>
{isMenuOpen ? <X /> : <Menu />}
</button>
</div>
{/* Mobile Menu */}
{isMenuOpen && (
<div className="md:hidden absolute top-20 left-0 w-full bg-white shadow-lg py-4">
<div className="flex flex-col space-y-4 px-4">
<a href="#services" className="text-slate-700 hover:text-indigo-600">Services</a>
<a href="#about" className="text-slate-700 hover:text-indigo-600">À propos</a>
<a href="#testimonials" className="text-slate-700 hover:text-indigo-600">Témoignages</a>
<a
href="https://calendly.com/lenix-io"
target="_blank"
rel="noopener noreferrer"
className="bg-indigo-600 text-white px-6 py-2 rounded-lg hover:bg-indigo-700 transition-colors text-center"
>
Planifier un appel
</a>
</div>
</div>
)}
</div>
</header>
);
};
export default Header;
\ No newline at end of file
import React from 'react';
const Hero = () => {
return (
<section className="relative min-h-screen flex items-center bg-gradient-to-br from-slate-900 via-indigo-900 to-slate-900">
<div className="absolute inset-0 bg-[url('https://images.unsplash.com/photo-1451187580459-43490279c0fa?auto=format&fit=crop&q=80')] bg-cover bg-center opacity-10"></div>
<div className="container mx-auto px-4 py-32 relative z-10">
<div className="max-w-3xl mx-auto text-center">
<h1 className="text-5xl md:text-6xl font-bold text-white mb-6">
Solutions DevOps & Administration Linux
</h1>
<p className="text-xl text-slate-300 mb-8">
Expertise en infrastructure, automatisation et sécurité pour propulser votre entreprise vers l'excellence technologique
</p>
<div className="flex flex-col sm:flex-row justify-center gap-4">
<a
href="https://calendly.com/lenix-io"
target="_blank"
rel="noopener noreferrer"
className="bg-indigo-600 text-white px-8 py-3 rounded-lg hover:bg-indigo-700 transition-colors text-lg font-semibold"
>
Démarrer un projet
</a>
<a
href="#services"
className="bg-white text-indigo-600 px-8 py-3 rounded-lg hover:bg-slate-100 transition-colors text-lg font-semibold"
>
Découvrir nos services
</a>
</div>
</div>
</div>
</section>
);
};
export default Hero;
\ No newline at end of file
import React, { useEffect, useRef } from 'react';
import { Cloud, GitBranch, Shield, Monitor, Layout } from 'lucide-react';
const services = [
{
icon: Cloud,
title: 'Infrastructure Cloud & On-premise',
description: 'Déploiement et gestion d\'infrastructures hybrides optimisées pour vos besoins spécifiques.'
},
{
icon: GitBranch,
title: 'CI/CD & Automatisation',
description: 'Mise en place de pipelines d\'intégration et de déploiement continu pour accélérer vos cycles de développement.'
},
{
icon: Shield,
title: 'Sécurité & Monitoring',
description: 'Protection et surveillance proactive de vos systèmes avec des solutions de sécurité avancées.'
},
{
icon: Monitor,
title: 'Poste Linux Utilisateur',
description: 'Configuration et maintenance de postes de travail Linux pour une productivité optimale.'
},
{
icon: Layout,
title: 'Landing Pages Professionnelles',
description: 'Création de pages d\'atterrissage performantes et optimisées pour la conversion, intégrant les meilleures pratiques UX/UI et SEO.'
}
];
const Services = () => {
const servicesRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('appear');
}
});
},
{
threshold: 0.1,
rootMargin: '0px'
}
);
const cards = document.querySelectorAll('.service-card');
cards.forEach((card) => observer.observe(card));
return () => observer.disconnect();
}, []);
return (
<section id="services" className="py-20 bg-slate-50">
<div className="container mx-auto px-4">
<div className="text-center mb-16 slide-in slide-in-from-bottom">
<h2 className="text-4xl font-bold text-slate-800 mb-4">Nos Services</h2>
<p className="text-lg text-slate-600 max-w-2xl mx-auto">
Des solutions DevOps complètes et des services web professionnels pour propulser votre entreprise
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8" ref={servicesRef}>
{services.map((service, index) => (
<div
key={index}
className={`service-card slide-in ${
index % 2 === 0 ? 'slide-in-from-left' : 'slide-in-from-right'
} bg-white p-6 rounded-xl shadow-lg hover:shadow-xl transform hover:-translate-y-1 transition-all duration-300`}
>
<div className="w-12 h-12 bg-indigo-100 rounded-lg flex items-center justify-center mb-6">
<service.icon className="w-6 h-6 text-indigo-600" />
</div>
<h3 className="text-xl font-semibold text-slate-800 mb-3">{service.title}</h3>
<p className="text-slate-600">{service.description}</p>
</div>
))}
</div>
</div>
</section>
);
};
export default Services;
\ No newline at end of file
import React, { useEffect, useRef } from 'react';
const Testimonials = () => {
const sectionRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('appear');
}
});
},
{
threshold: 0.1
}
);
if (sectionRef.current) {
observer.observe(sectionRef.current);
}
return () => observer.disconnect();
}, []);
return (
<section id="testimonials" className="py-20 bg-slate-50">
<div className="container mx-auto px-4">
<h2 className="text-4xl font-bold text-slate-800 text-center mb-16 slide-in slide-in-from-bottom">
Ce que disent nos clients
</h2>
<div
className="slide-in slide-in-from-bottom"
ref={sectionRef}
>
<div className="elfsight-app-79c260d4-113c-4d61-b984-b3f223a5c82b"></div>
</div>
</div>
</section>
);
};
export default Testimonials;
\ No newline at end of file
@tailwind base;
@tailwind components;
@tailwind utilities;
@keyframes scroll {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-50%);
}
}
.animate-scroll {
animation: scroll 30s linear infinite;
}
/* Elfsight Widget Styles */
.elfsight-app-widget {
max-width: 1200px;
margin: 0 auto;
}
/* Animation classes */
.slide-in {
@apply opacity-0 transition-all duration-1000 ease-out;
}
.slide-in-from-left {
@apply -translate-x-full;
}
.slide-in-from-right {
@apply translate-x-full;
}
.slide-in-from-bottom {
@apply translate-y-24;
}
.slide-in.appear {
@apply opacity-100 translate-x-0 translate-y-0;
}
\ No newline at end of file
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.tsx';
import './index.css';
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>
);
/// <reference types="vite/client" />
/** @type {import('tailwindcss').Config} */
export default {
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {
animation: {
scroll: 'scroll 30s linear infinite',
},
},
},
plugins: [],
};
\ No newline at end of file
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment