Les mots de passe robustes type xK9$mP2#vL! sont impossibles à retenir. Une passphrase composée de mots français choisis aléatoirement (Cerise-Voyage42$, Mésange/Crépuscule61?) atteint la même entropie tout en restant lisible et mémorisable.
Passphrase génère ces combinaisons en un clic, calcule leur entropie en bits, et expose une API REST publique pour intégration depuis n'importe quel client.
- Génération à la demande : 10 variantes par requête, avec aperçu d'entropie en couleur (très faible → très fort)
- Personnalisation complète : nombre de mots (2 à 7), séparateur, chiffres finaux, caractère spécial, longueur minimale, accents, majuscule en début ou aléatoire
- Calcul d'entropie en bits selon la formule
longueur × log2(taille du jeu de caractères) - API publique RESTful sur
GET /api/passwordsavec CORS ouvert (Access-Control-Allow-Origin: *) - Préférences mémorisées dans un cookie local (30 jours, fonctionnel, sans tracking)
- Article pédagogique sur l'entropie, la sécurité, et le choix d'un gestionnaire de mots de passe
| Couche | Technologie |
|---|---|
| Framework | Nuxt 4 (Vue 3.5, SSR + Nitro) |
| Language | TypeScript 6 |
| UI | Nuxt UI 4 + Tailwind CSS 4 |
| Polices | Manrope + Fraunces (self-hostées via @nuxt/fonts) |
| Sécurité | nuxt-security (CSP avec nonce, HSTS, Permissions-Policy) |
| Analytics | Cloudflare Web Analytics |
| CI | GitHub Actions (lint, typecheck, build) |
| Deps | Renovate |
| Hébergement | Cloudflare Pages |
| Outil | Version |
|---|---|
| Node.js | 22 LTS |
| pnpm | 10 |
git clone git@github.com:InstaZDLL/Passphrase.git
cd Passphrase
pnpm installpnpm devOuvre http://localhost:3000. Les nonces CSP et le module nuxt-security sont désactivés en dev pour ne pas casser le hot reload Vite.
pnpm build
pnpm start # serveur Nitro local sur :3000pnpm lint # ESLint (config Nuxt + project rules)
pnpm lint:fix # auto-fix
pnpm typecheck # vue-tsc + tscGET /api/passwords — génère 1 ou plusieurs passphrases.
| Paramètre | Type | Défaut | Valeurs |
|---|---|---|---|
count |
int | 1 |
1–50 |
nb_mots |
int | 2 |
2–7 |
longueur_minimale |
int | 12 |
8–50 |
separateur |
string | random |
random, -, _, , *, /, + |
majuscule_debut |
bool | true |
true, false |
majuscule_aleatoire |
bool | false |
true, false |
longueur_nombre |
int | 2 |
0–5 |
caractere_special |
string | random |
random, none, $, !, #, ?, -, +, @, ,, ;, :, * |
caracteres_accentues |
bool | true |
true, false |
curl "https://www.passphrase.ch/api/passwords?count=3&nb_mots=3&caractere_special=!"{
"passwords": [
{ "password": "Cerise-Voyage-Brume42!" },
{ "password": "Mésange/Galet/Tonnerre18!" },
{ "password": "Vermeil_Aubépine_Sablier09!" }
]
}L'API retourne aussi entropy et class sur la route privée /api/passwords/preview utilisée par le frontend.
.
├── app/
│ ├── app.vue # Layout racine (header, footer, skip-link, manifest)
│ ├── error.vue # Page 404 / 500 custom
│ ├── pages/
│ │ ├── index.vue # Landing + générateur
│ │ ├── privacy.vue # Politique de confidentialité (nLPD + RGPD)
│ │ └── blog/[slug].vue # Article (entropie)
│ ├── components/passphrase/ # PasswordList, EntropyBadge
│ ├── data/ # Site config, article, info légales
│ └── assets/css/main.css # Tailwind + tokens custom
├── server/
│ ├── api/passwords.get.ts # API publique
│ ├── api/passwords/preview.get.ts# API frontend (avec entropy)
│ ├── middleware/cors.ts # CORS public sur /api/passwords*
│ ├── assets/db.csv # Dictionnaire français
│ └── utils/dictionary.ts # Chargement et filtrage du dictionnaire
├── shared/passphrase.ts # Types + génération + entropy (ISO client/serveur)
├── public/ # Icônes, manifest, sitemap, robots
└── nuxt.config.ts # Modules, security headers, fonts
| Mesure | Détail |
|---|---|
| HSTS | max-age=31536000; includeSubDomains; preload |
| CSP | strict avec nonce par requête sur script-src, 'self' sur tout le reste, beacon Cloudflare autorisé |
| X-Frame-Options | DENY |
| X-Content-Type-Options | nosniff |
| Referrer-Policy | strict-origin-when-cross-origin |
| Permissions-Policy | camera/microphone/geolocation/interest-cohort désactivés |
| CORS | * uniquement sur /api/passwords* |
| Stockage | aucun (pas de DB, pas de session, pas de log applicatif persistant) |
Les rapports CSP sont envoyés à un endpoint csper.io. Voir nuxt.config.ts pour la config complète.
Build de production audité avec Lighthouse desktop (localhost) :
| Catégorie | Score |
|---|---|
| Performance | 99 |
| Accessibility | 100 |
| Best Practices | 96 lors de la mesure locale initiale |
| SEO | 100 |
Core Web Vitals : LCP < 1 s · CLS 0 · TBT 0 ms.
Optimisations clés : self-hosting des polices, conversion des images en WebP, fetchpriority="high" sur le LCP, @nuxt/fonts pour preload + display-swap, CSS critical inline par Nuxt.
Le projet cible Cloudflare Pages avec le preset Nitro cloudflare_pages.
Le site et les deux routes /api/passwords sont servis par le même déploiement.
L'extension Chrome conserve son adresse API : https://www.passphrase.ch/api/passwords.
Pour configurer le projet Pages connecté à GitHub :
- Branche de production :
main - Commande de build :
pnpm build - Répertoire de sortie :
dist - Activer Web Analytics dans Metrics après le premier déploiement
Les URL passphrase-landing.pages.dev et leurs aperçus reçoivent X-Robots-Tag: noindex.
Le domaine racine passphrase.ch redirige vers www.passphrase.ch.
Aucune variable d'environnement applicative n'est requise.
4. Configurer le domaine custom (le redirect apex → www se fait côté Vercel/DNS)
Le pipeline de build télécharge les polices Google au build (via @nuxt/fonts) puis les self-host — aucun appel runtime vers Google Fonts.
Issues et PR bienvenues. Avant d'ouvrir une PR :
pnpm lint
pnpm typecheck
pnpm buildCe projet est distribué sous licence MIT — voir LICENSE.
Il s'agit d'une réécriture en Nuxt 4 d'un projet original en Symfony :
- Concept original et implémentation Symfony : Alexandre Monchain —
AlexandreMonchain/Passphrase - Boilerplate Nuxt : Nuxt UI Templates
- Réécriture Nuxt 4, sécurité, déploiement : InstaZDLL
Tous les copyrights sont conservés conformément aux exigences de la licence MIT.
L'extension Chrome (refonte 2.0) est disponible sur le store : Chrome Web Store · Code source
L'extension v1 originale d'Alexandre Monchain reste disponible : Chrome Web Store · Code source