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 | Vercel Web Analytics + Speed Insights |
| CI | GitHub Actions (lint, typecheck, build) |
| Deps | Renovate |
| Hébergement | Vercel |
| 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
│ ├── plugins/ # Vercel Analytics + Speed Insights
│ └── 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*
│ ├── data/db.csv # Dictionnaire français (~22 000 mots)
│ └── 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, beacons Vercel whitelistés |
| 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 (→ 100 sur Vercel, les beacons Analytics 404 sur localhost) |
| 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 Vercel (zero-config Nuxt). Pour déployer ton propre instance :
- Fork ce repo
- Importer dans Vercel (auto-détection du preset Nuxt)
- Aucune variable d'environnement requise
- 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