Portfolio — Franck Delmas · AI Systems Architect · Freelance 55€/h
graph LR
Hero[Hero + CTA] --> Services[4 Services]
Services --> Projects[4 Projects]
Projects --> Stats[Count-up Stats]
Stats --> Tech[Tech Stack]
Tech --> Footer[Contact Links]
- Dark theme, glass-morphism cards, gradient animations
- Responsive mobile-first design
- Zero external dependencies (single HTML file)
- Count-up animation on scroll (IntersectionObserver)
- 4 services with pricing
- 4 featured projects linking to GitHub
| Service | Price |
|---|---|
| Agents IA Autonomes | à partir de 2 000€ |
| Assistants Vocaux IA | à partir de 3 500€ |
| Automatisation Métier | sur devis |
| Conseil & Audit IA | 55€/h |
# View locally
open index.html
# Deploy on GitHub Pages (already live)
# Settings → Pages → Source: main / rootMy professional portfolio — a single HTML file that tells visitors who I am, what I build, and how to hire me. Deployed for free on GitHub Pages.
No framework, no build step, no dependencies. Just HTML + inline CSS + vanilla JS. Opens instantly, works everywhere.
| Choice | Why |
|---|---|
| Single file | No build step, instant deploy, easy to maintain |
| Dark theme | Professional tech aesthetic, reduces eye strain |
| Glass-morphism | Modern look with backdrop-filter blur |
| Count-up stats | Engages visitors with animated numbers |
| Mobile-first | 60%+ of visitors come from mobile |
| Zero deps | No CDN failures, no version conflicts |
<!-- Change colors in :root -->
<style>
:root {
--accent: #3b82f6; /* Main accent (blue) */
--purple: #8b5cf6; /* Secondary (purple) */
--bg: #0a0a0f; /* Background */
}
</style>
<!-- Update content directly in HTML -->
<h1>Your Name</h1>
<p class="tagline">Your tagline here</p>
<!-- Add/remove service cards -->
<div class="card">
<h3>Your Service</h3>
<p>Description</p>
<span class="price">Your price</span>
</div>First Contentful Paint: 0.4s
Largest Contentful Paint: 0.8s
Total Blocking Time: 0ms
File size: 22KB (uncompressed)
Lighthouse score: 98/100
# Fork this repo
gh repo fork Turbo31150/franckdelmas.dev
# Edit index.html with your content
# Push to main branch
# Enable GitHub Pages in Settings → Pages → Source: main
# Your site is live at: https://yourusername.github.io/franckdelmas.dev/This section is a complete tutorial for developers who want to fork this repo and build their own portfolio. Every technique used in this site is explained below.
The entire portfolio lives in one index.html file. This is intentional -- no build step, no framework, no dependencies. The structure follows a classic landing page pattern:
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Your Name - Your Title</title>
<style>/* All CSS goes here */</style>
</head>
<body>
<nav><!-- Navigation --></nav>
<section id="hero"><!-- Hero with CTA --></section>
<section id="services"><!-- Service cards --></section>
<section id="projects"><!-- Project showcase --></section>
<section id="stats"><!-- Animated statistics --></section>
<section id="tech"><!-- Tech stack --></section>
<footer><!-- Contact links --></footer>
<script>/* All JS goes here */</script>
</body>
</html>All styles are inlined in a <style> tag. The design system uses CSS custom properties for easy theming:
:root {
--accent: #3b82f6; /* Primary blue */
--purple: #8b5cf6; /* Secondary purple */
--bg: #0a0a0f; /* Dark background */
--card-bg: rgba(255, 255, 255, 0.05); /* Glass effect */
--text: #e2e8f0; /* Light text */
--text-muted: #94a3b8; /* Muted text */
--radius: 16px; /* Card border radius */
--transition: 0.3s ease; /* Default animation speed */
}The signature look uses backdrop-filter for a frosted glass effect:
.card {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: var(--radius);
padding: 2rem;
transition: transform var(--transition), box-shadow var(--transition);
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 20px 40px rgba(59, 130, 246, 0.15);
}Browser support: backdrop-filter works in Chrome 76+, Firefox 103+, Safari 9+. For older browsers, the card still looks fine -- just without the blur.
The hero section uses a moving gradient background:
@keyframes gradient-shift {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
.hero {
background: linear-gradient(-45deg, #0a0a0f, #1a1a2e, #16213e, #0f3460);
background-size: 400% 400%;
animation: gradient-shift 15s ease infinite;
}This creates a subtle, slow-moving color shift that gives the page life without being distracting.
Mobile-first approach with a single breakpoint:
/* Mobile (default) */
.grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; }
.nav-links { display: none; }
.hamburger { display: block; }
/* Desktop (768px+) */
@media (min-width: 768px) {
.grid { grid-template-columns: repeat(2, 1fr); }
.nav-links { display: flex; }
.hamburger { display: none; }
.stats-grid { grid-template-columns: repeat(4, 1fr); }
}The count-up statistics only animate when they scroll into view. This uses the IntersectionObserver API instead of scroll event listeners (which are expensive):
const observerOptions = {
root: null, // viewport
rootMargin: '0px',
threshold: 0.2 // trigger when 20% visible
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// Start count-up animation
animateCountUp(entry.target);
observer.unobserve(entry.target); // Only animate once
}
});
}, observerOptions);
document.querySelectorAll('.stat-number').forEach(el => {
observer.observe(el);
});Why IntersectionObserver? Scroll listeners fire on every pixel of scroll, causing jank. IntersectionObserver is async and only fires when the element's visibility changes. It is also the browser-native way to do lazy loading.
The statistics section shows animated numbers (e.g., "600+" agents, "46GB" VRAM):
function animateCountUp(element) {
const target = parseInt(element.dataset.target);
const suffix = element.dataset.suffix || '';
const duration = 2000; // 2 seconds
const start = performance.now();
function update(currentTime) {
const elapsed = currentTime - start;
const progress = Math.min(elapsed / duration, 1);
// Ease-out cubic for natural deceleration
const eased = 1 - Math.pow(1 - progress, 3);
const current = Math.floor(eased * target);
element.textContent = current + suffix;
if (progress < 1) {
requestAnimationFrame(update);
}
}
requestAnimationFrame(update);
}The cubic ease-out (1 - (1-t)^3) makes numbers accelerate quickly then slow down as they approach the target, which feels more natural than linear counting.
Mobile navigation uses a simple toggle:
const hamburger = document.querySelector('.hamburger');
const navLinks = document.querySelector('.nav-links');
hamburger.addEventListener('click', () => {
navLinks.classList.toggle('active');
hamburger.classList.toggle('open');
});
// Close menu when clicking a link
navLinks.querySelectorAll('a').forEach(link => {
link.addEventListener('click', () => {
navLinks.classList.remove('active');
hamburger.classList.remove('open');
});
});# 1. Push your code to main branch
git push origin main
# 2. Go to Settings > Pages > Source: main / root
# 3. Your site is live at: https://username.github.io/repo-name/Pros: Free, automatic HTTPS, auto-deploys on push. Cons: No server-side logic, limited to static files.
# 1. Connect your GitHub repo at netlify.com
# 2. Build command: (leave empty -- no build step)
# 3. Publish directory: /
# 4. Custom domain: your-domain.comPros: Free SSL, custom domains, form handling, deploy previews. Cons: 100GB bandwidth/month on free tier.
# 1. Import your GitHub repo at vercel.com
# 2. Framework: Other
# 3. Root directory: /
# 4. DeployPros: Global CDN, instant rollbacks, analytics. Cons: 100GB bandwidth/month on free tier.
# 1. Connect repo at dash.cloudflare.com > Pages
# 2. Build command: (empty)
# 3. Build output: /
# 4. DeployPros: Unlimited bandwidth on free tier, global CDN, Web Analytics. Cons: 500 builds/month limit.
Essential meta tags already included:
<head>
<!-- Basic SEO -->
<title>Franck Delmas - AI Systems Architect | Freelance 55EUR/h</title>
<meta name="description" content="AI agents, voice assistants,
automation -- freelance AI architect building production systems.">
<!-- Open Graph (social sharing) -->
<meta property="og:title" content="Franck Delmas - AI Systems Architect">
<meta property="og:description" content="Building AI agents and automation systems">
<meta property="og:type" content="website">
<meta property="og:url" content="https://turbo31150.github.io/franckdelmas.dev/">
<!-- Technical SEO -->
<link rel="canonical" href="https://turbo31150.github.io/franckdelmas.dev/">
<meta name="robots" content="index, follow">
<html lang="fr"> <!-- Important: set correct language -->
</head>- Page speed: Single-file HTML loads in < 0.5s. Google rewards fast pages.
- Mobile-friendly: Responsive design passes Google's mobile test.
- Structured data: Add JSON-LD for rich search results:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Person",
"name": "Franck Delmas",
"jobTitle": "AI Systems Architect",
"url": "https://turbo31150.github.io/franckdelmas.dev/",
"sameAs": [
"https://github.com/Turbo31150",
"https://linkedin.com/in/franck-hlb-80bb231b1"
]
}
</script>The portfolio follows WCAG 2.1 AA guidelines:
| Requirement | Implementation |
|---|---|
| Color contrast | Text at 7:1 ratio (light on dark) |
| Keyboard navigation | All interactive elements focusable with Tab |
| Screen readers | Semantic HTML (nav, section, footer, h1-h3) |
| Focus indicators | Custom :focus-visible styles on links and buttons |
| Motion preferences | Respects prefers-reduced-motion |
| Alt text | All images have descriptive alt attributes |
/* Respect user's motion preferences */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* Custom focus indicator */
a:focus-visible, button:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 4px;
border-radius: 4px;
}| Want to... | Do this |
|---|---|
| Change colors | Edit --accent and --purple in :root |
| Add a section | Copy a <section> block, update content |
| Change prices | Edit the .price spans in service cards |
| Add a project | Duplicate a .project-card div |
| Change language | Update lang="fr" and text content |
| Add analytics | Insert Google Analytics script before </head> |
| Add a favicon | Add <link rel="icon" href="favicon.ico"> |
| Metric | Score | Target |
|---|---|---|
| First Contentful Paint | 0.4s | < 1.0s ✅ |
| Largest Contentful Paint | 0.8s | < 2.5s ✅ |
| Total Blocking Time | 0ms | < 200ms ✅ |
| Cumulative Layout Shift | 0.00 | < 0.1 ✅ |
| Lighthouse Performance | 98/100 | > 90 ✅ |
| File size (gzipped) | 8KB | < 50KB ✅ |
| HTTP requests | 1 | Minimal ✅ |
| Browser | Version | Status |
|---|---|---|
| Chrome | 90+ | ✅ Full support |
| Firefox | 88+ | ✅ Full support |
| Safari | 14+ | ✅ Full support |
| Edge | 90+ | ✅ Full support |
| Mobile Chrome | 90+ | ✅ Responsive |
| Mobile Safari | 14+ | ✅ Responsive |
MIT License · © 2026 Franck Delmas
Part of JARVIS OS ecosystem