---
title: charleliemorineau.com — Site personnel sans framework
---
<!-- Étude de cas complète. Titres « ## » = sections, ```mermaid = schéma. -->

## Contexte

Mon ancien site, en PHP, n'était plus maintenu. Je voulais le remplacer par un site qui remplisse quatre exigences :

- **lisible en cinq secondes** par un recruteur : nom, rôle, expériences et contact visibles sans défiler ;
- **éditable sans compétence technique** : modifier un texte ne doit demander ni compilation ni base de données ;
- **hébergeable partout** : un hébergement mutualisé classique (Apache + PHP) doit suffire ;
- **sécurisé par défaut**, puisque c'est mon métier.

## Architecture

```mermaid
flowchart LR
  subgraph edit["Édition"]
    md["Fichiers Markdown<br/>content/fr · content/en"]
  end
  subgraph tools["Outils locaux (Node)"]
    gen["tools/"] --> og["Images de partage"]
    gen --> qr["QR code"]
  end
  subgraph host["Hébergement mutualisé : Apache + PHP"]
    pages["Pages statiques<br/>/ · /cv · /projets · /blog"]
    api["api/contact.php"]
  end
  md --> pages
  md --> gen
  visitor(("Visiteur")) -->|"HTTPS + CSP stricte"| pages
  visitor -->|"jeton signé"| api
  api --> mailbox[("Boîte mail")]
```

Un petit script transforme le contenu Markdown en pages HTML complètes, lisibles par les moteurs de recherche et les robots des IA sans exécuter de JavaScript. Dans le navigateur, le même code de rendu reprend la main pour les animations et l'interactivité. Publier un texte, c'est modifier un fichier `.md`, lancer le script, puis pousser : le déploiement est automatique.

## Choix techniques

| Besoin | Choix | Pourquoi |
| --- | --- | --- |
| Contenu éditable | Markdown + parseur maison | Ni CMS, ni base de données, ni compilation |
| Interface | HTML, CSS et JavaScript natifs | Zéro dépendance, rapide, durable |
| Hébergement | Mutualisé Apache + PHP | Coût minimal ; `.htaccess` pour le cache et la sécurité |
| Formulaire | PHP sans dépendance | Jeton signé, limitation de débit, adresse jamais exposée |
| Schémas | Mermaid auto-hébergé | Chargé uniquement sur les pages qui en contiennent |
| Aperçus, QR | Scripts Node locaux | Toujours alignés avec le contenu, rien à publier en plus |

## Sécurité

- **Politique de contenu stricte** (`script-src 'self'`) : aucun script inline, aucune ressource tierce, police auto-hébergée.
- **En-têtes** HSTS, `X-Frame-Options`, `Permissions-Policy`, isolation `Cross-Origin-*`.
- **Rendu du Markdown sans `innerHTML`** : le HTML éventuellement présent dans le contenu n'est jamais interprété.
- **Formulaire de contact** : jeton HMAC à usage unique, contrôle d'origine, champ piège, limitation par IP hachée, en-têtes de mail non injectables. L'adresse de destination n'existe que dans la configuration serveur.

## Résultats

- 0 dépendance de production, 0 requête vers un tiers ;
- mise à jour du contenu = modifier un fichier texte.
<!-- À remettre si la page /stack/ est publiée :
- mesures de performance et en-têtes de sécurité visibles **en direct** sur la page [Stack](stack/).
-->
