Devenez intégrateur web en 1 mois grâce à un programme détaillé semaine par semaine : HTML, CSS, responsive, Bootstrap 4, JavaScript et bonnes pratiques professionnelles.
Introduction : qu'est-ce qu'un intégrateur web ?
L'intégrateur web est le professionnel qui transforme une maquette graphique (Figma, Adobe XD, Photoshop…) en pages web fonctionnelles, accessibles et responsive. Il fait le lien entre le designer qui conçoit l'interface et le développeur backend qui gère les données côté serveur.
Intégrateur vs Développeur Frontend vs Designer
| Rôle | Compétences principales | Outils |
|---|---|---|
| Intégrateur web | HTML, CSS, Bootstrap, JS basique, accessibilité | VS Code, W3C Validator, DevTools |
| Développeur Frontend | JS avancé, React/Angular/Vue, API REST, tests | Node.js, webpack, Git, npm |
| Designer UI/UX | Maquettage, design system, typographie, couleurs | Figma, Adobe XD, Sketch |
Ce que vous serez capable de faire à la fin du programme
- Créer des pages HTML5 sémantiques, valides W3C et accessibles
- Styliser une interface complète avec CSS moderne (Flexbox, variables, animations)
- Intégrer une maquette responsive avec Bootstrap 4 sur tous les breakpoints
- Ajouter des interactions JavaScript sans framework (DOM, événements, toggle)
- Respecter les normes d'accessibilité WCAG de base (ARIA, contrastes, navigation clavier)
- Déployer un site statique en ligne sur Netlify ou Vercel en moins de 5 minutes
- Présenter un portfolio intégrateur fonctionnel avec 3 projets
Semaine 1 — Les fondations HTML (Jours 1 à 7)
| Jours | Thème | Objectif clé |
|---|---|---|
| 1–2 | Structure HTML5 & sémantique | Comprendre le rôle de chaque balise de structure |
| 3–4 | Texte, liens, images, listes | Maîtriser le contenu rédactionnel et médias |
| 5–6 | Formulaires & tableaux | Créer des formulaires accessibles et valides |
| 7 | Projet 1 — CV en HTML pur | Assembler toutes les balises sur une page réelle |
Jours 1–2 : Structure HTML5 et balises sémantiques
HTML5 introduit des balises sémantiques qui donnent du sens au contenu, améliorent l'accessibilité et favorisent le référencement naturel. Chaque balise a un rôle précis dans la structure de la page.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mon premier document HTML5</title>
</head>
<body>
<header>
<!-- En-tête du site : logo, titre principal -->
<h1>Mon Portfolio</h1>
<nav>
<ul>
<li><a href="#accueil">Accueil</a></li>
<li><a href="#projets">Projets</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
</header>
<main>
<!-- Contenu principal et unique de la page -->
<section id="accueil">
<h2>À propos</h2>
<article>
<p>Texte de présentation...</p>
</article>
</section>
<aside>
<!-- Contenu complémentaire : sidebar, liens utiles -->
<h2>Liens utiles</h2>
</aside>
</main>
<footer>
<!-- Pied de page : mentions légales, contact -->
<p>© 2026 Mon Portfolio</p>
</footer>
</body>
</html>
<header> et <footer> peuvent apparaître dans un <article> ou une <section>.
Il n'y a qu'un seul <main> par page. <nav> est réservé aux navigations principales.
Jours 3–4 : Texte, liens, images et listes
La hiérarchie des titres (h1 → h6), les liens hypertextes bien construits et les images avec attribut
alt sont des bases incontournables pour l'accessibilité et le SEO.
<!-- Hiérarchie des titres : un seul h1 par page -->
<h1>Titre principal de la page</h1>
<h2>Section principale</h2>
<h3>Sous-section</h3>
<!-- Texte avec emphase -->
<p>
Le CSS est <strong>indispensable</strong> pour styliser le HTML.
Il faut <em>pratiquer chaque jour</em> pour progresser.
</p>
<!-- Liens internes et externes -->
<a href="#section-contact">Aller au contact</a>
<a href="https://developer.mozilla.org" target="_blank" rel="noopener noreferrer">
MDN Web Docs
</a>
<!-- Image avec alt descriptif (obligatoire pour l'accessibilité) -->
<img src="assets/photo-profil.jpg"
alt="Photo de profil de Jean Dupont, intégrateur web"
width="200"
height="200"
loading="lazy">
<!-- Listes non ordonnées (ul) et ordonnées (ol) -->
<ul>
<li>HTML5</li>
<li>CSS3</li>
<li>Bootstrap 4</li>
</ul>
<ol>
<li>Apprendre HTML</li>
<li>Apprendre CSS</li>
<li>Créer un projet</li>
</ol>
<!-- Liste de définitions (dl) pour glossaires -->
<dl>
<dt>HTML</dt>
<dd>HyperText Markup Language — langage de structure</dd>
<dt>CSS</dt>
<dd>Cascading Style Sheets — langage de présentation</dd>
</dl>
alt sur les images n'est pas optionnel.
Un alt vide alt="" est utilisé pour les images décoratives (les lecteurs d'écran les ignorent).
Un alt descriptif est obligatoire pour les images porteuses de sens.
Jours 5–6 : Formulaires complets et tableaux
Les formulaires sont au cœur de l'interaction utilisateur. Chaque champ doit être associé
à un <label> via l'attribut for / id pour l'accessibilité.
<form action="/contact" method="POST" novalidate>
<fieldset>
<legend>Vos informations personnelles</legend>
<div>
<label for="prenom">Prénom *</label>
<input type="text"
id="prenom"
name="prenom"
placeholder="Ex : Marie"
required
autocomplete="given-name">
</div>
<div>
<label for="email">Email *</label>
<input type="email"
id="email"
name="email"
placeholder="marie@exemple.fr"
required
autocomplete="email">
</div>
<div>
<label for="niveau">Niveau</label>
<select id="niveau" name="niveau">
<option value="">-- Choisissez --</option>
<option value="debutant">Débutant</option>
<option value="intermediaire">Intermédiaire</option>
<option value="avance">Avancé</option>
</select>
</div>
<div>
<label for="message">Message</label>
<textarea id="message" name="message" rows="5" cols="40"
placeholder="Votre message..."></textarea>
</div>
</fieldset>
<button type="submit">Envoyer</button>
<button type="reset">Réinitialiser</button>
</form>
<!-- Tableau structuré avec thead, tbody, tfoot -->
<table>
<caption>Planning hebdomadaire d'apprentissage</caption>
<thead>
<tr>
<th scope="col">Jour</th>
<th scope="col">Thème</th>
<th scope="col">Durée</th>
</tr>
</thead>
<tbody>
<tr>
<td>Lundi</td>
<td>Structure HTML5</td>
<td>2h</td>
</tr>
<tr>
<td>Mardi</td>
<td>Liens et images</td>
<td>2h</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">Total semaine</td>
<td>14h</td>
</tr>
</tfoot>
</table>
autocomplete améliore l'UX sur mobile.
Utilisez les valeurs standardisées : given-name, family-name, email,
tel, postal-code…
Jour 7 : Projet 1 — CV en HTML pur
Le projet de fin de semaine consolide toutes les balises apprises. L'objectif est de créer un CV complet sans aucun CSS — ce qui force à utiliser les bonnes balises sémantiques.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>CV — Jean Dupont, Intégrateur Web</title>
</head>
<body>
<header>
<h1>Jean Dupont</h1>
<p><strong>Intégrateur Web Junior</strong></p>
<address>
<a href="mailto:jean@exemple.fr">jean@exemple.fr</a> |
<a href="tel:+33600000000">06 00 00 00 00</a> |
Lyon, France
</address>
</header>
<main>
<section aria-labelledby="titre-competences">
<h2 id="titre-competences">Compétences</h2>
<ul>
<li>HTML5 sémantique</li>
<li>CSS3 / Flexbox</li>
<li>Bootstrap 4</li>
<li>JavaScript ES6+</li>
</ul>
</section>
<section aria-labelledby="titre-experiences">
<h2 id="titre-experiences">Expériences</h2>
<article>
<h3>Intégrateur Web Stagiaire — Agence XYZ</h3>
<p><time datetime="2026-01">Janvier 2026</time> – <time datetime="2026-03">Mars 2026</time></p>
<ul>
<li>Intégration de maquettes Figma en HTML/CSS</li>
<li>Optimisation des performances (images, lazy loading)</li>
</ul>
</article>
</section>
</main>
<footer>
<p>Portfolio : <a href="https://jean-dupont.dev">jean-dupont.dev</a></p>
</footer>
</body>
</html>
Semaine 2 — CSS : du style à la mise en page (Jours 8 à 14)
| Jours | Thème | Objectif clé |
|---|---|---|
| 8–9 | Sélecteurs, cascade, box model | Comprendre le moteur CSS et le positionnement de base |
| 10–11 | Couleurs, typo, variables CSS | Créer un design system minimaliste |
| 12–13 | Flexbox + positionnement | Mettre en page des interfaces complexes |
| 14 | Projet 2 — CV stylisé + dark mode | Appliquer tout le CSS sur le projet HTML |
Jours 8–9 : Sélecteurs, cascade, héritage et Box Model
Le Box Model est le fondement de tout positionnement CSS : chaque élément est une boîte composée
du contenu, du padding, de la bordure et de la marge. La propriété box-sizing: border-box
est désormais la norme car elle inclut padding et bordure dans la largeur déclarée.
/* Reset moderne — à placer en début de feuille CSS */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
/* ========================
SÉLECTEURS CSS
======================== */
/* Sélecteur de balise */
p { color: #333; }
/* Sélecteur de classe (.) */
.card { background: #fff; }
/* Sélecteur d'ID (#) — utiliser avec parcimonie */
#hero { min-height: 100vh; }
/* Sélecteur descendant */
.nav ul li a { text-decoration: none; }
/* Pseudo-classe */
a:hover { color: #007bff; }
input:focus { outline: 2px solid #007bff; }
/* Pseudo-élément */
p::first-line { font-weight: bold; }
.card::before { content: "→ "; }
/* ========================
BOX MODEL
======================== */
.box {
width: 300px; /* Largeur du contenu */
padding: 20px; /* Espace intérieur */
border: 2px solid #ccc;
margin: 16px auto; /* Espace extérieur + centrage horizontal */
/* Avec border-box : largeur totale = 300px (padding et border inclus) */
}
/* ========================
UNITÉS CSS
======================== */
.container {
max-width: 1200px; /* px : valeur fixe en pixels */
width: 90%; /* % : relatif au parent */
margin: 0 auto;
}
body {
font-size: 16px; /* Base de référence */
}
h1 {
font-size: 2rem; /* rem : relatif à la racine (ici 32px) */
}
.sidebar {
padding: 1.5em; /* em : relatif à l'élément courant */
}
!important dans vos feuilles de style — c'est le signe d'une architecture CSS mal pensée.
Jours 10–11 : Couleurs, typographie et variables CSS
Les Custom Properties (variables CSS) permettent de centraliser les valeurs de design
et de créer facilement un dark mode avec une seule règle prefers-color-scheme.
/* ========================
VARIABLES CSS (Custom Properties)
======================== */
:root {
/* Couleurs */
--color-primary: #007bff;
--color-secondary: #6c757d;
--color-bg: #ffffff;
--color-text: #212529;
--color-border: #dee2e6;
/* Typographie */
--font-body: 'Manrope', sans-serif;
--font-code: 'Fira Code', monospace;
--font-size-base: 1rem;
--line-height: 1.6;
/* Espacements */
--spacing-xs: 0.25rem;
--spacing-sm: 0.5rem;
--spacing-md: 1rem;
--spacing-lg: 2rem;
--spacing-xl: 4rem;
/* Rayons */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 16px;
}
/* Dark mode automatique selon les préférences système */
@media (prefers-color-scheme: dark) {
:root {
--color-bg: #121212;
--color-text: #e9e9e9;
--color-border: #333;
}
}
/* ========================
TYPOGRAPHIE
======================== */
@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;700&display=swap');
body {
font-family: var(--font-body);
font-size: var(--font-size-base);
line-height: var(--line-height);
color: var(--color-text);
background-color: var(--color-bg);
}
h1, h2, h3, h4, h5, h6 {
font-weight: 700;
line-height: 1.2;
margin-bottom: var(--spacing-md);
}
/* Palette de couleurs fonctionnelles */
.text-primary { color: var(--color-primary); }
.bg-primary { background-color: var(--color-primary); color: #fff; }
.border-light { border: 1px solid var(--color-border); }
Jours 12–13 : Flexbox complet et positionnement
Flexbox est LE système de mise en page pour les interfaces modernes. Il gère la distribution des éléments sur un axe (horizontal ou vertical) et leur alignement. Maîtriser Flexbox remplace 90 % des cas d'usage des anciens floats.
/* ========================
FLEXBOX — RÉFÉRENCE COMPLÈTE
======================== */
.flex-container {
display: flex;
/* Axe principal (horizontal par défaut) */
flex-direction: row; /* row | row-reverse | column | column-reverse */
justify-content: space-between; /* flex-start | center | space-between | space-around | space-evenly */
/* Axe secondaire (vertical par défaut) */
align-items: center; /* stretch | flex-start | flex-end | center | baseline */
/* Retour à la ligne */
flex-wrap: wrap; /* nowrap | wrap | wrap-reverse */
/* Raccourci flex-flow = flex-direction + flex-wrap */
flex-flow: row wrap;
/* Espacement entre les éléments */
gap: 1rem; /* row-gap column-gap */
}
/* Propriétés sur les enfants (flex-items) */
.flex-item {
flex: 1; /* flex-grow: 1 + flex-shrink: 1 + flex-basis: 0% */
flex: 0 0 300px; /* Ne grandit pas, ne rétrécit pas, largeur fixe de 300px */
align-self: flex-start; /* Surcharge align-items pour cet élément */
order: 2; /* Réordonne l'affichage sans changer le HTML */
}
/* ========================
CAS PRATIQUES FLEXBOX
======================== */
/* Centrer parfaitement un élément */
.centered {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
/* Navbar avec logo à gauche, liens à droite */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
}
/* Grille de cards responsive sans media query */
.cards-grid {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
}
.card {
flex: 1 1 280px; /* Grandit, rétrécit, minimum 280px */
max-width: 400px;
}
/* ========================
POSITIONNEMENT CSS
======================== */
/* relative : le flux est conservé, décalage par rapport à sa position normale */
.badge {
position: relative;
top: -2px;
}
/* absolute : sort du flux, se positionne par rapport à l'ancêtre positionné le plus proche */
.card {
position: relative; /* Crée un contexte de positionnement */
}
.card-badge {
position: absolute;
top: 12px;
right: 12px;
}
/* fixed : reste visible même en scrollant (sticky header, bouton retour en haut) */
.topbar {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000;
}
/* sticky : reste visible jusqu'à un seuil de scroll */
.section-title {
position: sticky;
top: 70px; /* Distance depuis le haut une fois "collé" */
background: #fff;
}
position: relative + absolute
pour superposer des éléments (badges, overlays). Utilisez position: sticky pour les headers
de tableaux ou les titres de sections. Évitez position: fixed sur mobile — cela peut causer
des bugs de scroll sur iOS Safari.
Jour 14 : Projet 2 — Styliser le CV avec CSS et dark mode
/* cv-style.css — Feuille de style complète pour le CV */
:root {
--primary: #2563eb;
--text: #1f2937;
--bg: #f9fafb;
--card-bg: #ffffff;
--border: #e5e7eb;
}
@media (prefers-color-scheme: dark) {
:root {
--text: #f3f4f6;
--bg: #111827;
--card-bg: #1f2937;
--border: #374151;
}
}
body {
font-family: 'Manrope', sans-serif;
background: var(--bg);
color: var(--text);
max-width: 800px;
margin: 2rem auto;
padding: 0 1rem;
}
header {
display: flex;
align-items: center;
gap: 2rem;
padding: 2rem;
background: var(--card-bg);
border-radius: 12px;
border: 1px solid var(--border);
margin-bottom: 1.5rem;
}
header img {
width: 100px;
height: 100px;
border-radius: 50%;
object-fit: cover;
}
section {
background: var(--card-bg);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 1.5rem;
}
h2 {
color: var(--primary);
font-size: 1.1rem;
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 1rem;
padding-bottom: 0.5rem;
border-bottom: 2px solid var(--primary);
}
Semaine 3 — Bootstrap 4 + Responsive Design (Jours 15 à 21)
| Jours | Thème | Objectif clé |
|---|---|---|
| 15–16 | Grille Bootstrap & utilities | Maîtriser le système de 12 colonnes |
| 17–18 | Composants Bootstrap | Intégrer navbar, cards, modales, alertes |
| 19–20 | Media queries & CSS Grid intro | Écrire du CSS responsive mobile-first |
| 21 | Projet 3 — Landing page complète | Assembler hero + features + contact en Bootstrap |
Tableau des breakpoints Bootstrap 4
| Préfixe | Breakpoint | Largeur min | Usage typique |
|---|---|---|---|
col- | Extra small | < 576px | Smartphones portrait |
col-sm- | Small | ≥ 576px | Smartphones paysage |
col-md- | Medium | ≥ 768px | Tablettes |
col-lg- | Large | ≥ 992px | Laptops |
col-xl- | Extra large | ≥ 1200px | Écrans larges |
Jours 15–16 : Grille Bootstrap et classes utilitaires
<!-- CDN Bootstrap 4 -->
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
<!-- Structure de base : container > row > col -->
<div class="container">
<div class="row">
<!-- 12 colonnes sur mobile, 6 sur tablette, 4 sur desktop -->
<div class="col-12 col-md-6 col-lg-4">
<p>Colonne 1</p>
</div>
<div class="col-12 col-md-6 col-lg-4">
<p>Colonne 2</p>
</div>
<div class="col-12 col-md-12 col-lg-4">
<p>Colonne 3</p>
</div>
</div>
</div>
<!-- Utilities Bootstrap les plus utiles -->
<!-- Espacement : m = margin, p = padding | t b l r x y | 0 1 2 3 4 5 auto -->
<div class="mt-3 mb-4 px-2 py-3">Espacement</div>
<!-- Flexbox utilities -->
<div class="d-flex justify-content-between align-items-center">
<span>Gauche</span>
<span>Droite</span>
</div>
<!-- Affichage conditionnel selon breakpoint -->
<div class="d-none d-md-block">Visible seulement sur tablette et +</div>
<div class="d-block d-md-none">Visible seulement sur mobile</div>
<!-- Texte -->
<p class="text-center text-md-left font-weight-bold text-primary">
Centré sur mobile, aligné à gauche sur tablette
</p>
<!-- Couleurs de fond et de texte -->
<div class="bg-primary text-white p-3 rounded">Fond bleu</div>
<div class="bg-light text-dark border p-3 rounded-lg">Fond clair</div>
Jours 17–18 : Composants Bootstrap essentiels
<!-- ========================
NAVBAR RESPONSIVE
======================== -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">MonSite</a>
<!-- Bouton hamburger pour mobile -->
<button class="navbar-toggler" type="button"
data-toggle="collapse" data-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false"
aria-label="Ouvrir le menu">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ml-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Accueil <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#projets">Projets</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#contact">Contact</a>
</li>
</ul>
</div>
</nav>
<!-- ========================
CARDS
======================== -->
<div class="card shadow-sm">
<img src="projet.jpg" class="card-img-top" alt="Aperçu du projet">
<div class="card-body">
<h5 class="card-title">Projet Landing Page</h5>
<p class="card-text">Intégration d'une maquette Figma en HTML/CSS/Bootstrap.</p>
<span class="badge badge-primary">HTML</span>
<span class="badge badge-secondary">CSS</span>
<span class="badge badge-success">Bootstrap</span>
</div>
<div class="card-footer text-muted">
<a href="#" class="btn btn-primary btn-sm">Voir le projet</a>
<a href="#" class="btn btn-outline-secondary btn-sm ml-2">GitHub</a>
</div>
</div>
<!-- ========================
MODALE BOOTSTRAP
======================== -->
<button type="button" class="btn btn-info" data-toggle="modal" data-target="#maModale">
Ouvrir la modale
</button>
<div class="modal fade" id="maModale" tabindex="-1"
role="dialog" aria-labelledby="modaleTitre" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modaleTitre">Titre de la modale</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Fermer">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Contenu de la modale...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Fermer</button>
<button type="button" class="btn btn-primary">Confirmer</button>
</div>
</div>
</div>
</div>
<!-- ========================
ALERTES ET ACCORDÉON
======================== -->
<div class="alert alert-success alert-dismissible fade show" role="alert">
<strong>Bravo !</strong> Votre formulaire a été envoyé avec succès.
<button type="button" class="close" data-dismiss="alert" aria-label="Fermer">
<span aria-hidden="true">×</span>
</button>
</div>
<div id="accordeon">
<div class="card">
<div class="card-header" id="q1">
<h2 class="mb-0">
<button class="btn btn-link" data-toggle="collapse" data-target="#rep1"
aria-expanded="true" aria-controls="rep1">
Qu'est-ce que l'intégration web ?
</button>
</h2>
</div>
<div id="rep1" class="collapse show" aria-labelledby="q1" data-parent="#accordeon">
<div class="card-body">
L'intégration web consiste à convertir des maquettes graphiques en code HTML/CSS fonctionnel.
</div>
</div>
</div>
</div>
Jours 19–20 : Media queries et CSS Grid
/* ========================
MEDIA QUERIES — MOBILE FIRST
======================== */
/* Base : styles pour mobile (sans media query) */
.container {
width: 100%;
padding: 0 1rem;
}
.hero-title {
font-size: 1.8rem;
}
/* Tablette (≥ 768px) */
@media (min-width: 768px) {
.container {
max-width: 720px;
margin: 0 auto;
}
.hero-title {
font-size: 2.5rem;
}
}
/* Laptop (≥ 992px) */
@media (min-width: 992px) {
.container {
max-width: 960px;
}
.hero-title {
font-size: 3.2rem;
}
}
/* Grand écran (≥ 1200px) */
@media (min-width: 1200px) {
.container {
max-width: 1140px;
}
}
/* ========================
CSS GRID — INTRODUCTION
======================== */
/* Grille de projets 3 colonnes responsive */
.projects-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
}
/* Mise en page 2 colonnes (content + sidebar) */
.page-layout {
display: grid;
grid-template-columns: 1fr 300px; /* Contenu flexible + sidebar fixe */
grid-template-rows: auto 1fr auto; /* header, main, footer */
gap: 2rem;
min-height: 100vh;
}
@media (max-width: 767px) {
.page-layout {
grid-template-columns: 1fr; /* Une seule colonne sur mobile */
}
}
/* ========================
IMAGES RESPONSIVE
======================== */
img {
max-width: 100%;
height: auto;
display: block;
}
/* Bootstrap class : img-fluid = max-width: 100% + height: auto */
/* <img src="hero.jpg" class="img-fluid" alt="..."> */
@media (min-width: ...), vous évitez les surcharges inutiles. Les navigateurs mobiles
n'ont pas à parser des règles desktop qu'ils doivent ensuite écraser.
Jour 21 : Projet 3 — Landing page complète Bootstrap
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MonService — La solution pour votre business</title>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- NAVBAR -->
<nav class="navbar navbar-expand-lg navbar-light bg-white shadow-sm fixed-top">
<div class="container">
<a class="navbar-brand font-weight-bold text-primary" href="#">MonService</a>
<button class="navbar-toggler" type="button"
data-toggle="collapse" data-target="#nav"
aria-controls="nav" aria-expanded="false" aria-label="Menu">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="nav">
<ul class="navbar-nav ml-auto">
<li class="nav-item"><a class="nav-link" href="#features">Fonctionnalités</a></li>
<li class="nav-item"><a class="nav-link" href="#contact">Contact</a></li>
<li class="nav-item ml-lg-2">
<a class="btn btn-primary btn-sm" href="#contact">Essai gratuit</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- HERO -->
<section id="hero" class="hero-section d-flex align-items-center">
<div class="container text-center">
<h1 class="display-4 font-weight-bold mb-3">Boostez votre productivité</h1>
<p class="lead text-muted mb-4">
La plateforme tout-en-un pour gérer vos projets, équipes et clients.
</p>
<a href="#contact" class="btn btn-primary btn-lg px-5">Démarrer gratuitement</a>
<a href="#features" class="btn btn-outline-secondary btn-lg px-5 ml-3">En savoir plus</a>
</div>
</section>
<!-- FEATURES -->
<section id="features" class="py-5">
<div class="container">
<h2 class="text-center font-weight-bold mb-5">Fonctionnalités clés</h2>
<div class="row">
<div class="col-12 col-md-4 mb-4">
<div class="card h-100 shadow-sm border-0 text-center p-4">
<div class="feature-icon mb-3">🚀</div>
<h3 class="h5">Performance</h3>
<p class="text-muted">Chargement ultra-rapide pour une UX optimale.</p>
</div>
</div>
<div class="col-12 col-md-4 mb-4">
<div class="card h-100 shadow-sm border-0 text-center p-4">
<div class="feature-icon mb-3">🔒</div>
<h3 class="h5">Sécurité</h3>
<p class="text-muted">Données chiffrées, conformité RGPD.</p>
</div>
</div>
<div class="col-12 col-md-4 mb-4">
<div class="card h-100 shadow-sm border-0 text-center p-4">
<div class="feature-icon mb-3">📱</div>
<h3 class="h5">Responsive</h3>
<p class="text-muted">Parfait sur tous les écrans, du mobile au 4K.</p>
</div>
</div>
</div>
</div>
</section>
<!-- CONTACT -->
<section id="contact" class="py-5 bg-light">
<div class="container">
<div class="row justify-content-center">
<div class="col-12 col-md-8 col-lg-6">
<h2 class="text-center font-weight-bold mb-4">Contactez-nous</h2>
<form>
<div class="form-group">
<label for="name">Votre nom</label>
<input type="text" id="name" class="form-control" placeholder="Jean Dupont">
</div>
<div class="form-group">
<label for="mail">Email</label>
<input type="email" id="mail" class="form-control" placeholder="jean@exemple.fr">
</div>
<div class="form-group">
<label for="msg">Message</label>
<textarea id="msg" class="form-control" rows="4"></textarea>
</div>
<button type="submit" class="btn btn-primary btn-block">Envoyer</button>
</form>
</div>
</div>
</div>
</section>
</body>
</html>
Semaine 4 — JavaScript pour intégrateurs + Finitions pro (Jours 22 à 30)
| Jours | Thème | Objectif clé |
|---|---|---|
| 22–23 | DOM & événements JS | Manipuler le HTML depuis JavaScript |
| 24–25 | Animations CSS + interactions JS | Créer des effets visuels fluides |
| 26–27 | Accessibilité ARIA & WCAG | Rendre les interfaces accessibles à tous |
| 28–29 | Outils pro : VS Code, Git, Netlify | Travailler comme un pro dès le premier jour |
| 30 | Projet Final — Portfolio complet | Publier son portfolio en ligne |
Jours 22–23 : Manipulation du DOM et événements
En tant qu'intégrateur, vous n'avez pas besoin de maîtriser toute la programmation JavaScript. En revanche, savoir manipuler le DOM (Document Object Model) pour ajouter des interactions est une compétence indispensable.
// ========================
// SÉLECTIONNER DES ÉLÉMENTS
// ========================
// querySelector : sélectionne le premier élément correspondant
const btn = document.querySelector('#btn-menu');
const title = document.querySelector('h1');
const firstCard = document.querySelector('.card');
// querySelectorAll : sélectionne TOUS les éléments (retourne une NodeList)
const allCards = document.querySelectorAll('.card');
const navLinks = document.querySelectorAll('.nav-link');
// ========================
// MODIFIER LE DOM
// ========================
// Modifier le texte
title.textContent = 'Nouveau titre';
// Modifier le HTML (attention aux failles XSS !)
const container = document.querySelector('#content');
container.innerHTML = '<p>Texte généré dynamiquement</p>';
// Modifier les classes
const menu = document.querySelector('.menu');
menu.classList.add('active'); // Ajoute la classe
menu.classList.remove('active'); // Supprime la classe
menu.classList.toggle('active'); // Ajoute si absente, supprime si présente
menu.classList.contains('active'); // Retourne true/false
// Modifier les styles inline (préférer les classes CSS)
btn.style.backgroundColor = '#007bff';
btn.style.display = 'none';
// Modifier les attributs
const img = document.querySelector('img');
img.setAttribute('alt', 'Nouveau texte alternatif');
img.getAttribute('src');
// ========================
// ÉVÉNEMENTS
// ========================
// Click
btn.addEventListener('click', function() {
menu.classList.toggle('open');
});
// Version arrow function (ES6)
btn.addEventListener('click', () => {
menu.classList.toggle('open');
});
// Événement sur plusieurs éléments
allCards.forEach(card => {
card.addEventListener('mouseenter', () => card.classList.add('hovered'));
card.addEventListener('mouseleave', () => card.classList.remove('hovered'));
});
// Événement de soumission de formulaire
const form = document.querySelector('#contact-form');
form.addEventListener('submit', (event) => {
event.preventDefault(); // Empêche le rechargement de la page
const emailInput = document.querySelector('#email');
if (emailInput.value === '') {
alert('Veuillez renseigner votre email.');
emailInput.focus();
return;
}
console.log('Formulaire valide, envoi...');
});
// Scroll : afficher/masquer un bouton "retour en haut"
const backToTop = document.querySelector('#back-to-top');
window.addEventListener('scroll', () => {
if (window.scrollY > 400) {
backToTop.classList.add('visible');
} else {
backToTop.classList.remove('visible');
}
});
Jours 24–25 : Animations CSS et interactions JavaScript
/* ========================
TRANSITIONS CSS — pour les changements d'état
======================== */
.btn {
background-color: #007bff;
color: white;
padding: 0.75rem 1.5rem;
border: none;
border-radius: 8px;
cursor: pointer;
/* transition: propriété durée timing-function délai */
transition: background-color 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease;
}
.btn:hover {
background-color: #0056b3;
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(0, 123, 255, 0.3);
}
.btn:active {
transform: translateY(0);
box-shadow: none;
}
/* ========================
@KEYFRAMES — pour les animations autonomes
======================== */
/* Animation d'entrée en fondu + glissement */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.hero-title {
animation: fadeInUp 0.6s ease forwards;
}
.hero-subtitle {
animation: fadeInUp 0.6s ease 0.2s forwards; /* délai de 0.2s */
opacity: 0; /* invisible au départ (avant que l'animation commence) */
}
/* Spinner de chargement */
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.loader {
width: 40px;
height: 40px;
border: 4px solid #e0e0e0;
border-top-color: #007bff;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
/* ========================
MENU MOBILE AVEC JS + CSS
======================== */
// menu.js — Menu mobile toggle
const hamburger = document.querySelector('.hamburger');
const mobileMenu = document.querySelector('.mobile-menu');
hamburger.addEventListener('click', () => {
const isOpen = mobileMenu.classList.contains('menu-open');
mobileMenu.classList.toggle('menu-open');
hamburger.setAttribute('aria-expanded', String(!isOpen));
hamburger.setAttribute('aria-label', isOpen ? 'Ouvrir le menu' : 'Fermer le menu');
});
// Fermer le menu si on clique sur un lien
document.querySelectorAll('.mobile-menu a').forEach(link => {
link.addEventListener('click', () => {
mobileMenu.classList.remove('menu-open');
hamburger.setAttribute('aria-expanded', 'false');
hamburger.setAttribute('aria-label', 'Ouvrir le menu');
});
});
// Fermer si on appuie sur Echap
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && mobileMenu.classList.contains('menu-open')) {
mobileMenu.classList.remove('menu-open');
hamburger.setAttribute('aria-expanded', 'false');
hamburger.focus(); // Remettre le focus sur le bouton
}
});
Jours 26–27 : Accessibilité ARIA et normes WCAG
L'accessibilité n'est pas une option — c'est une obligation légale dans de nombreux pays et un gage de qualité professionnelle. Les WCAG 2.1 (Web Content Accessibility Guidelines) définissent 4 principes : Perceptible, Utilisable, Compréhensible, Robuste.
<!-- ========================
ARIA — Accessible Rich Internet Applications
======================== -->
<!-- 1. Rôles ARIA pour clarifier la sémantique -->
<div role="navigation" aria-label="Navigation principale">...</div>
<div role="main">...</div>
<div role="complementary" aria-label="Articles connexes">...</div>
<!-- 2. aria-label : étiquette un élément sans texte visible -->
<button aria-label="Fermer la modale">
<span aria-hidden="true">×</span>
</button>
<a href="https://github.com/user" aria-label="Profil GitHub de Jean Dupont">
<img src="github.svg" alt="" aria-hidden="true">
</a>
<!-- 3. aria-expanded : état ouvert/fermé d'un composant interactif -->
<button aria-expanded="false" aria-controls="menu-mobile" id="btn-menu">
Menu
</button>
<nav id="menu-mobile" aria-labelledby="btn-menu" hidden>...</nav>
<!-- 4. aria-live : annoncer les changements dynamiques aux lecteurs d'écran -->
<div aria-live="polite" aria-atomic="true" class="sr-only" id="status">
<!-- Les messages d'état s'insèrent ici dynamiquement -->
</div>
<!-- 5. tabindex : gérer l'ordre de navigation au clavier -->
<div tabindex="0" role="button" class="custom-btn"
onclick="doAction()" onkeypress="if(event.key==='Enter') doAction()">
Action personnalisée
</div>
| Critère WCAG | Exigence | Outil de vérification |
|---|---|---|
| Contraste texte / fond | Ratio ≥ 4.5:1 (normal), ≥ 3:1 (grand texte) | WebAIM Contrast Checker |
| Images | Attribut alt pertinent sur toutes les images |
WAVE, axe DevTools |
| Navigation clavier | Tous les éléments interactifs accessibles au Tab | Test manuel au clavier |
| Formulaires | Chaque input a un <label> associé |
W3C Validator, WAVE |
| Focus visible | Outline visible sur tous les éléments focusables | Test manuel Tab + CSS inspection |
outline: none ou outline: 0
appliquée globalement rend votre site inaccessible à la navigation clavier.
Remplacez-la par un outline personnalisé et esthétique : outline: 2px solid var(--color-primary); outline-offset: 3px;
Jours 28–29 : Outils professionnels
| Outil | Usage | Commande / Raccourci clé |
|---|---|---|
| VS Code | Éditeur de code | Live Server, Prettier, Auto Rename Tag |
| Chrome DevTools | Debug CSS/HTML en temps réel | F12 · Cmd+Shift+I · Inspect |
| W3C Validator | Vérifier la validité du HTML | validator.w3.org |
| Prettier | Formater le code automatiquement | Alt+Shift+F dans VS Code |
| Git | Versionner et sauvegarder le code | git init · git add . · git commit |
| Netlify / Vercel | Déployer un site statique gratuitement | Drag & drop du dossier sur netlify.com |
# Workflow Git de base — à pratiquer chaque jour
# 1. Initialiser un dépôt dans votre dossier projet
git init
# 2. Configurer votre identité (une seule fois)
git config --global user.name "Jean Dupont"
git config --global user.email "jean@exemple.fr"
# 3. Voir l'état des fichiers modifiés
git status
# 4. Ajouter tous les fichiers au suivi
git add .
# 5. Créer un commit avec un message descriptif
git commit -m "feat: ajouter section hero avec Bootstrap"
# 6. Connecter à un dépôt GitHub et pousser
git remote add origin https://github.com/user/mon-portfolio.git
git push -u origin main
# Bonnes pratiques de messages de commit (Conventional Commits)
# feat: nouvelle fonctionnalité
# fix: correction de bug
# style: changements CSS uniquement
# docs: mise à jour documentation
# chore: tâche de maintenance
Jour 30 : Projet Final — Portfolio intégrateur web
/* portfolio.css — Structure principale du portfolio final */
:root {
--primary: #6366f1; /* Indigo */
--bg: #0f172a; /* Slate 900 */
--surface: #1e293b; /* Slate 800 */
--text: #f1f5f9;
--text-muted: #94a3b8;
--border: #334155;
}
/* Toggle dark/light mode via JS */
body.light-mode {
--bg: #f8fafc;
--surface: #ffffff;
--text: #0f172a;
--text-muted: #64748b;
--border: #e2e8f0;
}
/* ========================
HERO SECTION
======================== */
.hero {
min-height: 100vh;
display: flex;
align-items: center;
background: var(--bg);
position: relative;
overflow: hidden;
}
.hero::before {
content: '';
position: absolute;
width: 600px;
height: 600px;
background: radial-gradient(circle, rgba(99, 102, 241, 0.15) 0%, transparent 70%);
top: -100px;
right: -100px;
border-radius: 50%;
pointer-events: none;
}
.hero-content {
position: relative;
z-index: 1;
}
.hero-title {
font-size: clamp(2rem, 5vw, 4rem); /* Responsive sans media query */
font-weight: 800;
background: linear-gradient(135deg, var(--primary), #a78bfa);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 1rem;
}
/* ========================
GRILLE PROJETS
======================== */
.projects-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.project-card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 16px;
overflow: hidden;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.project-card:hover {
transform: translateY(-6px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
}
// theme-toggle.js — Basculer dark/light mode et sauvegarder en localStorage
const themeToggle = document.querySelector('#theme-toggle');
const body = document.body;
// Charger la préférence sauvegardée
const savedTheme = localStorage.getItem('theme');
if (savedTheme === 'light') {
body.classList.add('light-mode');
themeToggle.textContent = '🌙';
}
themeToggle.addEventListener('click', () => {
body.classList.toggle('light-mode');
const isLight = body.classList.contains('light-mode');
localStorage.setItem('theme', isLight ? 'light' : 'dark');
themeToggle.textContent = isLight ? '🌙' : '☀️';
themeToggle.setAttribute('aria-label', isLight ? 'Activer le dark mode' : 'Activer le light mode');
});
Checklist des 30 compétences acquises
À la fin du programme, validez chaque compétence en la mettant en pratique dans votre portfolio.
HTML (10 compétences)
- Écrire un document HTML5 valide avec DOCTYPE, charset et viewport
- Utiliser les balises sémantiques : header, nav, main, section, article, aside, footer
- Respecter la hiérarchie des titres h1 → h6 (un seul h1 par page)
- Créer des liens internes (ancres) et externes (target + rel="noopener")
- Intégrer des images avec alt descriptif, width, height et loading="lazy"
- Construire des formulaires accessibles avec label/input associés
- Utiliser fieldset et legend pour regrouper les champs de formulaire
- Créer des tableaux avec thead, tbody, tfoot et attributs scope
- Utiliser les balises time, address, abbr, cite correctement
- Valider le HTML avec le validateur W3C (0 erreur, 0 warning)
CSS (10 compétences)
- Appliquer le reset CSS avec box-sizing: border-box
- Comprendre et utiliser la cascade et la spécificité des sélecteurs
- Maîtriser le Box Model (content, padding, border, margin)
- Utiliser les variables CSS Custom Properties pour un design system
- Mettre en page avec Flexbox (justify-content, align-items, gap, wrap)
- Créer une grille responsive avec CSS Grid (auto-fit, minmax)
- Écrire des animations avec transition et @keyframes
- Implémenter un dark mode avec prefers-color-scheme et/ou classe JS
- Écrire du CSS mobile-first avec les media queries
- Charger et utiliser des Google Fonts correctement
Bootstrap 4 (5 compétences)
- Utiliser la grille Bootstrap sur tous les breakpoints (col-12 col-md-6 col-lg-4)
- Intégrer une navbar responsive avec hamburger menu
- Utiliser les composants : cards, alerts, badges, boutons, modales
- Appliquer les classes utilitaires (spacing, flex, display, text)
- Personnaliser Bootstrap avec des variables SASS ou du CSS override
JavaScript & Accessibilité (5 compétences)
- Sélectionner des éléments DOM avec querySelector et querySelectorAll
- Gérer les événements : click, submit, scroll, keydown
- Ajouter/supprimer/toggler des classes CSS depuis JavaScript
- Ajouter les attributs ARIA indispensables (aria-label, aria-expanded, aria-hidden)
- Passer la navigation clavier complète sans souris sur son projet
Les erreurs classiques des débutants intégrateurs
1. Utiliser des <div> pour tout
La "div-ite aiguë" consiste à tout envelopper dans des <div> sans logique sémantique.
Préférez les balises appropriées : <nav> pour la navigation, <button> pour les actions,
<ul><li> pour les listes, <table> pour les données tabulaires.
2. Oublier le viewport meta tag
<!-- ❌ Sans viewport : le site semble zoomé sur mobile -->
<head>
<meta charset="UTF-8">
<title>Mon site</title>
</head>
<!-- ✅ Avec viewport : rendu correct sur mobile -->
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mon site</title>
</head>
3. Supprimer l'outline CSS sans alternative
/* ❌ À ne jamais faire — rend le site inaccessible au clavier */
* { outline: none; }
/* ✅ Personnaliser l'outline sans le supprimer */
:focus-visible {
outline: 2px solid var(--primary);
outline-offset: 3px;
border-radius: 4px;
}
4. Images sans attribut alt
<!-- ❌ Inaccessible et mauvais pour le SEO -->
<img src="hero.jpg">
<!-- ✅ Alt descriptif pour les images porteuses de sens -->
<img src="hero.jpg" alt="Equipe de développeurs web travaillant en open space">
<!-- ✅ Alt vide pour les images purement décoratives -->
<img src="decoration.svg" alt="" aria-hidden="true">
5. Utiliser des pixels pour les tailles de police
/* ❌ Bloque le zoom navigateur pour les malvoyants */
body { font-size: 14px; }
h1 { font-size: 24px; }
/* ✅ Utiliser rem : respecte les préférences de l'utilisateur */
body { font-size: 1rem; } /* 16px par défaut */
h1 { font-size: 2rem; } /* 32px */
small { font-size: 0.875rem; } /* 14px */
6. Labels non associés aux inputs
<!-- ❌ Le clic sur "Email" ne focus pas l'input -->
<label>Email</label>
<input type="email" name="email">
<!-- ✅ Associé via for/id -->
<label for="email">Email</label>
<input type="email" id="email" name="email">
<!-- ✅ Alternative : imbriquer l'input dans le label -->
<label>
Email
<input type="email" name="email">
</label>
7. Charger Bootstrap sans jQuery pour les composants JS
8. Négliger les performances des images
<!-- ❌ Image énorme non optimisée -->
<img src="photo-5000px.jpg" style="width: 300px">
<!-- ✅ Image correctement dimensionnée + lazy loading + format moderne -->
<picture>
<source srcset="hero.webp" type="image/webp">
<img src="hero.jpg"
alt="Description"
width="800"
height="450"
loading="lazy"
decoding="async">
</picture>
9. CSS trop spécifique dès le début
/* ❌ Difficile à surcharger, trop spécifique */
body div.container div.row div.col .card .card-title { font-size: 1.2rem; }
/* ✅ Classe directe, facile à maintenir */
.card-title { font-size: 1.2rem; }
10. Ne pas tester sur mobile réel
Le mode responsive des DevTools est utile mais ne remplace pas un test sur un vrai smartphone. Utilisez ngrok ou BrowserSync pour exposer votre localhost sur votre réseau local et tester sur votre téléphone dès le début du développement.
Ressources et outils essentiels
Documentation de référence
| Ressource | URL | Usage |
|---|---|---|
| MDN Web Docs | developer.mozilla.org/fr | Référence HTML, CSS, JS — la bible du développeur web |
| CSS-Tricks | css-tricks.com | Guides Flexbox, Grid, snippets CSS avancés |
| Bootstrap 4 Docs | getbootstrap.com/docs/4.6 | Documentation officielle de Bootstrap 4 |
| Can I Use | caniuse.com | Compatibilité CSS/JS par navigateur |
Outils de validation et d'accessibilité
| Outil | URL | Usage |
|---|---|---|
| W3C HTML Validator | validator.w3.org | Valider le HTML d'une page |
| W3C CSS Validator | jigsaw.w3.org/css-validator | Valider les feuilles de style CSS |
| WAVE | wave.webaim.org | Audit d'accessibilité complet d'une page |
| WebAIM Contrast Checker | webaim.org/resources/contrastchecker | Vérifier les ratios de contraste |
| PageSpeed Insights | pagespeed.web.dev | Audit de performance Google (Lighthouse) |
Pratique et inspiration
| Outil | URL | Usage |
|---|---|---|
| CodePen | codepen.io | Prototyper et partager des snippets HTML/CSS/JS |
| Flexbox Froggy | flexboxfroggy.com | Apprendre Flexbox en jouant |
| CSS Grid Garden | cssgridgarden.com | Apprendre CSS Grid en jouant |
| Frontend Mentor | frontendmentor.io | Défis d'intégration avec maquettes réelles |
| Dribbble / Behance | dribbble.com / behance.net | Inspiration UI/UX pour vos projets |
Extensions VS Code recommandées
- Live Server — Rechargement automatique du navigateur à chaque sauvegarde
- Prettier — Formatage automatique du code (HTML, CSS, JS)
- Auto Rename Tag — Renomme la balise fermante automatiquement
- IntelliSense for CSS — Autocomplétion des classes CSS dans le HTML
- axe Accessibility Linter — Signale les erreurs d'accessibilité en temps réel
- GitLens — Visualiser l'historique Git directement dans VS Code
- Color Highlight — Affiche les couleurs CSS directement dans l'éditeur
Conclusion — Et après le mois ?
Vous avez parcouru les 4 semaines du programme. En 30 jours, vous avez posé des bases que beaucoup de développeurs autodidactes mettent des années à consolider. La clé désormais est la pratique régulière sur des projets réels.
Étapes suivantes recommandées
| Mois | Objectif | Technologies |
|---|---|---|
| Mois 2 | JavaScript approfondi | ES6+, fetch API, localStorage, modules JS |
| Mois 3 | Framework CSS moderne | Tailwind CSS ou SASS/SCSS |
| Mois 4–6 | Framework JS | Angular ou React (selon vos objectifs) |
| Mois 7+ | Employabilité | Tests unitaires, CI/CD, Docker, APIs REST |