Files
site_web/lanro.eu/projets.html
T
felden.r@grenoble.archi.fr cf9a01000c Fix accessibility and mobile issues, add SEO meta tags
- Fixed HTML structure error (extra closing div in cv.html)
- Updated all dates from 2025 to 2026
- Added rel="noopener noreferrer" to external LinkedIn links
- Added Open Graph and Twitter Card meta tags for all pages
- Added Schema.org structured data (Person) for SEO
- Removed emoji badges for better accessibility
- Optimized Google Fonts loading
- Added mobile hamburger menu with ARIA labels
- Improved touch targets (44px minimum)
- Added prefers-reduced-motion support
- Enhanced keyboard navigation and focus states

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-13 09:46:22 +01:00

981 lines
40 KiB
HTML

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Projets de Roman Felden - Homelab, Android, Minecraft modding">
<meta name="theme-color" content="#4f46e5">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://lanro.eu/projets.html">
<meta property="og:title" content="Projets - Roman Felden">
<meta property="og:description" content="Découvrez les projets de Roman Felden : Homelab Proxmox, Boidelo Android, Custom Ore Gen Minecraft mod, GeoRealmCraft serveur.">
<meta property="og:image" content="https://lanro.eu/og-image.jpg">
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:url" content="https://lanro.eu/projets.html">
<meta property="twitter:title" content="Projets - Roman Felden">
<meta property="twitter:description" content="Découvrez les projets de Roman Felden : Homelab Proxmox, Boidelo Android, Custom Ore Gen Minecraft mod, GeoRealmCraft serveur.">
<meta property="twitter:image" content="https://lanro.eu/og-image.jpg">
<title>Projets - Roman Felden</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,400&display=swap" rel="stylesheet">
<style>
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--color-primary: #4f46e5;
--color-primary-light: #818cf8;
--color-primary-dark: #3730a3;
--color-secondary: #0ea5e9;
--color-accent: #f59e0b;
--color-text: #0f172a;
--color-text-muted: #64748b;
--color-text-light: #94a3b8;
--color-bg: #ffffff;
--color-bg-alt: #f8fafc;
--color-bg-card: #ffffff;
--color-border: #e2e8f0;
--color-border-light: #f1f5f9;
--shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
--radius-sm: 6px;
--radius-md: 12px;
--radius-lg: 20px;
--radius-xl: 28px;
}
html {
font-size: 16px;
scroll-behavior: smooth;
}
body {
font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
line-height: 1.7;
color: var(--color-text);
background: var(--color-bg-alt);
min-height: 100vh;
}
/* Navigation */
.navbar {
background: var(--color-bg);
box-shadow: var(--shadow-md);
position: sticky;
top: 0;
z-index: 1000;
padding: 1rem 2rem;
}
.navbar-container {
max-width: 1200px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
}
.navbar-brand {
font-size: 1.5rem;
font-weight: 800;
color: var(--color-primary);
text-decoration: none;
display: flex;
align-items: center;
gap: 0.5rem;
z-index: 1002;
}
.navbar-brand span {
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.navbar-brand:focus-visible,
.navbar-menu a:focus-visible {
outline: 3px solid var(--color-primary);
outline-offset: 2px;
border-radius: 4px;
}
/* Hamburger Menu Button */
.navbar-toggle {
display: none;
background: none;
border: none;
cursor: pointer;
padding: 0.75rem;
margin: -0.75rem;
z-index: 1002;
border-radius: var(--radius-sm);
transition: background 0.3s ease;
}
.navbar-toggle:hover {
background: var(--color-bg-alt);
}
.navbar-toggle:focus-visible {
outline: 3px solid var(--color-primary);
outline-offset: 2px;
}
.hamburger {
display: block;
width: 24px;
height: 2px;
background: var(--color-text);
position: relative;
transition: all 0.3s ease;
}
.hamburger::before,
.hamburger::after {
content: '';
position: absolute;
width: 24px;
height: 2px;
background: var(--color-text);
transition: all 0.3s ease;
}
.hamburger::before {
top: -8px;
}
.hamburger::after {
bottom: -8px;
}
.navbar-toggle.active .hamburger {
background: transparent;
}
.navbar-toggle.active .hamburger::before {
top: 0;
transform: rotate(45deg);
}
.navbar-toggle.active .hamburger::after {
bottom: 0;
transform: rotate(-45deg);
}
.navbar-menu {
display: flex;
gap: 2rem;
list-style: none;
}
.navbar-menu a {
color: var(--color-text);
text-decoration: none;
font-weight: 600;
padding: 0.75rem 1.25rem;
border-radius: var(--radius-sm);
transition: all 0.3s ease;
min-height: 44px;
min-width: 44px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.navbar-menu a:hover,
.navbar-menu a.active {
color: var(--color-primary);
background: var(--color-bg-alt);
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 3rem 2rem;
}
/* Header */
.page-header {
text-align: center;
margin-bottom: 4rem;
}
.page-header h1 {
font-size: 3rem;
font-weight: 800;
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 1rem;
}
.page-header p {
font-size: 1.2rem;
color: var(--color-text-muted);
}
/* Project Section */
.project-section {
background: var(--color-bg);
border-radius: var(--radius-xl);
padding: 3rem;
margin-bottom: 3rem;
box-shadow: var(--shadow-lg);
scroll-margin-top: 100px;
}
.project-section:last-child {
margin-bottom: 0;
}
.project-header {
display: flex;
align-items: center;
gap: 1.5rem;
margin-bottom: 2rem;
flex-wrap: wrap;
}
.project-icon {
width: 80px;
height: 80px;
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 100%);
border-radius: var(--radius-lg);
display: flex;
align-items: center;
justify-content: center;
font-size: 2.5rem;
flex-shrink: 0;
}
.project-icon svg {
width: 40px;
height: 40px;
color: white;
}
.project-title h2 {
font-size: 2rem;
font-weight: 800;
color: var(--color-text);
margin-bottom: 0.5rem;
}
.project-subtitle {
font-size: 1.1rem;
color: var(--color-text-muted);
}
.project-badges {
display: flex;
gap: 0.75rem;
flex-wrap: wrap;
margin-bottom: 2rem;
}
.badge {
display: inline-block;
background: var(--color-bg-alt);
color: var(--color-text);
padding: 0.5rem 1rem;
border-radius: 50px;
font-size: 0.85rem;
font-weight: 600;
border: 2px solid var(--color-border-light);
}
.badge-primary {
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-dark) 100%);
color: white;
border-color: transparent;
}
.project-description {
font-size: 1.05rem;
color: var(--color-text-muted);
line-height: 1.8;
margin-bottom: 2rem;
}
.project-features {
display: grid;
gap: 1.5rem;
margin-bottom: 2rem;
}
.feature-item {
display: flex;
align-items: flex-start;
gap: 1rem;
padding: 1.25rem;
background: var(--color-bg-alt);
border-radius: var(--radius-md);
border-left: 4px solid var(--color-primary);
}
.feature-icon {
width: 24px;
height: 24px;
color: var(--color-primary);
flex-shrink: 0;
margin-top: 0.1rem;
}
.feature-content h4 {
font-size: 1rem;
font-weight: 700;
color: var(--color-text);
margin-bottom: 0.25rem;
}
.feature-content p {
font-size: 0.95rem;
color: var(--color-text-muted);
margin: 0;
}
.tech-stack {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
margin-top: 2rem;
padding-top: 2rem;
border-top: 1px solid var(--color-border-light);
}
.tech-item {
display: flex;
align-items: center;
gap: 0.5rem;
background: var(--color-bg-alt);
padding: 0.5rem 1rem;
border-radius: var(--radius-sm);
font-size: 0.9rem;
font-weight: 600;
color: var(--color-text);
}
.tech-item::before {
content: '';
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--color-secondary);
}
/* Footer */
.footer {
background: var(--color-text);
color: white;
padding: 3rem 2rem;
text-align: center;
margin-top: 4rem;
}
.footer p {
opacity: 0.8;
}
.footer-heart {
color: #ef4444;
animation: heartbeat 1.5s ease-in-out infinite;
}
@keyframes heartbeat {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
/* Responsive */
@media (max-width: 768px) {
.navbar {
padding: 1rem;
}
.navbar-toggle {
display: block;
}
.navbar-menu {
position: fixed;
top: 0;
right: -100%;
width: 80%;
max-width: 300px;
height: 100vh;
background: var(--color-bg);
flex-direction: column;
gap: 0;
padding: 6rem 2rem 2rem;
box-shadow: -5px 0 20px rgba(0, 0, 0, 0.1);
transition: right 0.3s ease;
overflow-y: auto;
}
.navbar-menu.active {
right: 0;
}
.navbar-menu li {
width: 100%;
}
.navbar-menu a {
width: 100%;
padding: 1rem;
border-radius: var(--radius-md);
justify-content: flex-start;
}
/* Overlay when menu is open */
.navbar-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 1001;
}
.navbar-overlay.active {
display: block;
}
/* Prevent body scroll when menu is open */
body.menu-open {
overflow: hidden;
}
.page-header h1 {
font-size: 2rem;
}
.project-section {
padding: 2rem 1.5rem;
}
.project-header {
flex-direction: column;
text-align: center;
}
.project-icon {
width: 64px;
height: 64px;
font-size: 2rem;
}
.project-title h2 {
font-size: 1.5rem;
}
.project-badges {
justify-content: center;
}
.feature-item {
flex-direction: column;
text-align: center;
}
.feature-icon {
margin: 0 auto 0.5rem;
}
.tech-stack {
justify-content: center;
}
}
/* Respect prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
html {
scroll-behavior: auto;
}
}
/* Small screens (very small phones) */
@media (max-width: 380px) {
.navbar-menu {
width: 100%;
max-width: none;
}
.page-header h1 {
font-size: 1.75rem;
}
.project-section {
padding: 1.5rem 1rem;
}
}
</style>
</head>
<body>
<!-- Navigation -->
<nav class="navbar" role="navigation" aria-label="Navigation principale">
<div class="navbar-container">
<a href="index.html" class="navbar-brand" aria-label="Retour à l'accueil - Roman Felden">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
</svg>
<span>RF</span>
</a>
<button class="navbar-toggle" aria-label="Ouvrir le menu de navigation" aria-expanded="false" aria-controls="primary-menu">
<span class="hamburger"></span>
</button>
<ul class="navbar-menu" id="primary-menu" role="menubar">
<li role="none"><a href="index.html" role="menuitem">Accueil</a></li>
<li role="none"><a href="cv.html" role="menuitem">CV</a></li>
<li role="none"><a href="projets.html" role="menuitem" class="active" aria-current="page">Projets</a></li>
</ul>
</div>
<div class="navbar-overlay" aria-hidden="true"></div>
</nav>
<div class="container">
<!-- Page Header -->
<div class="page-header">
<h1>Mes Projets</h1>
<p>Découvrez mes réalisations personnelles dans le domaine de l'infrastructure, du développement et du modding</p>
</div>
<!-- Homelab Proxmox -->
<section id="homelab" class="project-section">
<div class="project-header">
<div class="project-icon">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01"/>
</svg>
</div>
<div class="project-title">
<h2>Homelab Proxmox</h2>
<p class="project-subtitle">Infrastructure de virtualisation complète</p>
</div>
</div>
<div class="project-badges">
<span class="badge badge-primary">Infrastructure</span>
<span class="badge">Virtualisation</span>
<span class="badge">Réseaux</span>
<span class="badge">Sécurité</span>
</div>
<div class="project-description">
<p>Mon Homelab basé sur Proxmox VE est une infrastructure de virtualisation complète qui me permet d'héberger divers services, d'expérimenter de nouvelles technologies et de développer mes compétences en administration système. C'est un environnement d'apprentissage et de test pour les technologies de virtualisation, de conteneurisation et de réseautage.</p>
</div>
<div class="project-features">
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Virtualisation avancée</h4>
<p>Gestion de machines virtuelles Linux et Windows avec Proxmox VE</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Conteneurisation</h4>
<p>Déploiement de services avec LXC et Docker pour une isolation légère</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Réseautage complexe</h4>
<p>VLANs, bridges, et configuration réseau avancée</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Stockage et backup</h4>
<p>ZFS pour la gestion du stockage avec snapshots et réplications</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Services auto-hébergés</h4>
<p>DNS, surveillance, stockage cloud, bases de données, etc.</p>
</div>
</div>
</div>
<div class="tech-stack">
<span class="tech-item">Proxmox VE</span>
<span class="tech-item">Linux</span>
<span class="tech-item">Docker</span>
<span class="tech-item">LXC</span>
<span class="tech-item">ZFS</span>
<span class="tech-item">VLAN</span>
<span class="tech-item">Networking</span>
</div>
</section>
<!-- Boidelo -->
<section id="boidelo" class="project-section">
<div class="project-header">
<div class="project-icon">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z"/>
</svg>
</div>
<div class="project-title">
<h2>Boidelo</h2>
<p class="project-subtitle">Application Android de jeu de société</p>
</div>
</div>
<div class="project-badges">
<span class="badge badge-primary">Android</span>
<span class="badge">Java</span>
<span class="badge">Material Design</span>
<span class="badge">Jeu</span>
</div>
<div class="project-description">
<p>Boidelo est une application Android de jeu de société multijoueur similaire à "King's Cup" ou "Never Have I Ever". L'application permet à un groupe de joueurs de répondre à des questions aléatoires et de relever des défis. Elle inclut 150 questions préchargées, une interface Material Design 3, et des paramètres personnalisables.</p>
</div>
<div class="project-features">
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Jeu multijoueur</h4>
<p>Support de 3 à illimité de joueurs avec saisie dynamique des noms</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>150 questions préchargées</h4>
<p>Questions variées depuis un fichier JSON avec système de variantes</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Défis multi-manches</h4>
<p>Système de défis avec compte à rebours et gestion optimisée</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Paramètres personnalisables</h4>
<p>Nombre de questions, ajout de gorgées, durée des défis, ratio BDD/OpenAI</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Interface Material Design 3</h4>
<p>Design moderne avec animations fluides et support du mode sombre</p>
</div>
</div>
</div>
<div class="tech-stack">
<span class="tech-item">Android SDK</span>
<span class="tech-item">Java 17</span>
<span class="tech-item">Material Design 3</span>
<span class="tech-item">Gradle</span>
<span class="tech-item">JSON</span>
<span class="tech-item">PostgreSQL</span>
</div>
</section>
<!-- Custom Ore Gen -->
<section id="custom-ore-gen" class="project-section">
<div class="project-header">
<div class="project-icon">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z"/>
</svg>
</div>
<div class="project-title">
<h2>Custom Ore Gen</h2>
<p class="project-subtitle">Mod Minecraft 1.20.1 - Forge</p>
</div>
</div>
<div class="project-badges">
<span class="badge badge-primary">Minecraft</span>
<span class="badge">Forge</span>
<span class="badge">MCreator</span>
<span class="badge">Java</span>
</div>
<div class="project-description">
<p>Custom Ore Gen est un mod Minecraft développé avec MCreator pour Forge 1.20.1. Ce mod modifie la distribution des ressources en ajoutant de nouvelles variantes de minerais avec des drops configurables, des outils personnalisés, et une armure intermédiaire située entre le fer et le diamant. Il est conçu pour être utilisé avec KubeJS et Biomes O' Plenty.</p>
</div>
<div class="project-features">
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>16 nouveaux minerais</h4>
<p>Variantes de diamant, or, charbon, fer, émeraude, redstone, lapis et cuivre</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Distribution par biome</h4>
<p>Génération basée sur la température (froid, chaud, tempéré, montagneux, rare)</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Diamond Shards</h4>
<p>Nouveau resource pour outils et armure intermédiaires (9 shards = 1 diamant)</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Outils en Diamond Shard</h4>
<p>Pioche, pelle, hache et Paxel (outil combiné pioche+pelle+hache)</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Armure intermédiaire</h4>
<p>17 protection, 1060 durabilité (entre fer et diamant)</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Ore Biome Finder</h4>
<p>Utilitaire pour identifier les minerais présents dans le biome actuel</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Support Biomes O' Plenty</h4>
<p>69 biomes BOP supplémentaires classés par température</p>
</div>
</div>
</div>
<div class="tech-stack">
<span class="tech-item">Minecraft 1.20.1</span>
<span class="tech-item">Forge 47.3.0</span>
<span class="tech-item">MCreator</span>
<span class="tech-item">Java 17</span>
<span class="tech-item">KubeJS</span>
<a href="https://www.curseforge.com/minecraft/mc-mods/custom-ore-gen" target="_blank" rel="noopener" class="tech-item" style="text-decoration: none; display: inline-flex; align-items: center; gap: 0.5rem; background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-dark) 100%); color: white; border-color: transparent;">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<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>
CurseForge
</a>
</div>
</section>
<!-- GeoRealmCraft -->
<section id="georealmcraft" class="project-section">
<div class="project-header">
<div class="project-icon">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</div>
<div class="project-title">
<h2>GeoRealmCraft</h2>
<p class="project-subtitle">Serveur Minecraft public & Infrastructure</p>
</div>
</div>
<div class="project-badges">
<span class="badge badge-primary">Infrastructure</span>
<span class="badge">Serveur Public</span>
<span class="badge">Administration</span>
<span class="badge">Minecraft</span>
</div>
<div class="project-description">
<p>GeoRealmCraft est un serveur Minecraft public avec infrastructure complète. Projet technique d'administration système et de gestion de communauté, incluant maintenance de serveur, modpack technique, gestion des utilisateurs et monitoring. Expérience concrète en gestion d'infrastructure et de communauté en ligne.</p>
</div>
<div class="project-features">
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Administration serveur</h4>
<p>Gestion complète de serveur, configuration, maintenance et mise à jour</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Gestion de communauté</h4>
<p>Moderation, support utilisateur, gestion des conflits et animation</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Infrastructure scalable</h4>
<p>Configuration technique optimisée, performance et gestion de la charge</p>
</div>
</div>
<div class="feature-item">
<svg class="feature-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<div class="feature-content">
<h4>Maintenance & monitoring</h4>
<p>Sauvegardes automatisées, surveillance des performances et résolution d'incidents</p>
</div>
</div>
</div>
<div class="tech-stack">
<span class="tech-item">Administration Système</span>
<span class="tech-item">Gestion de Communauté</span>
<span class="tech-item">Monitoring</span>
<span class="tech-item">Maintenance</span>
<span class="tech-item">Backup</span>
</div>
</section>
</div>
<!-- Footer -->
<footer class="footer">
<div class="container">
<p>© 2026 Roman Felden · Fait avec <span class="footer-heart"></span> à Grenoble, France</p>
<p style="margin-top: 0.5rem; font-size: 0.9rem; opacity: 0.8;">
<a href="index.html" style="color: white; text-decoration: none; opacity: 0.8;">Retour à l'accueil</a>
</p>
</div>
</footer>
<script>
// Mobile menu toggle functionality
(function() {
const toggle = document.querySelector('.navbar-toggle');
const menu = document.querySelector('.navbar-menu');
const overlay = document.querySelector('.navbar-overlay');
const body = document.body;
if (!toggle || !menu) return;
function toggleMenu() {
const isOpen = toggle.classList.contains('active');
toggle.classList.toggle('active');
menu.classList.toggle('active');
overlay.classList.toggle('active');
body.classList.toggle('menu-open');
toggle.setAttribute('aria-expanded', !isOpen);
toggle.setAttribute('aria-label', isOpen ? 'Ouvrir le menu de navigation' : 'Fermer le menu de navigation');
// Trap focus in menu when open
if (!isOpen) {
const menuLinks = menu.querySelectorAll('a');
if (menuLinks.length > 0) {
menuLinks[0].focus();
}
}
}
function closeMenu() {
if (toggle.classList.contains('active')) {
toggleMenu();
}
}
toggle.addEventListener('click', toggleMenu);
overlay.addEventListener('click', closeMenu);
// Close menu when clicking a link
const menuLinks = menu.querySelectorAll('a');
menuLinks.forEach(link => {
link.addEventListener('click', closeMenu);
});
// Close menu on Escape key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && toggle.classList.contains('active')) {
closeMenu();
toggle.focus();
}
});
// Handle tab trapping in menu
menu.addEventListener('keydown', function(e) {
if (e.key === 'Tab' && toggle.classList.contains('active')) {
const focusableElements = menu.querySelectorAll('a');
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
if (e.shiftKey && document.activeElement === firstElement) {
e.preventDefault();
lastElement.focus();
} else if (!e.shiftKey && document.activeElement === lastElement) {
e.preventDefault();
firstElement.focus();
}
}
});
})();
</script>
</body>
</html>