@jonathankablan/noraivoire-mcp 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,64 @@
1
+ NORAIVOIRE — LICENCE PROPRIÉTAIRE
2
+ Copyright (c) 2026 Jonathan KABLAN. Tous droits réservés.
3
+
4
+ Le présent logiciel, incluant sans limitation son code source, ses spécifications
5
+ (fichiers .nora.json), son compilateur, son moteur d'effets, ses adaptateurs, ses
6
+ modèles (templates), sa documentation, ses jeux de tests et ses éléments graphiques
7
+ (ci-après « le Logiciel »), est la propriété exclusive de Jonathan KABLAN
8
+ (ci-après « le Titulaire »).
9
+
10
+ 1. ABSENCE DE LICENCE OPEN SOURCE
11
+ Le Logiciel n'est pas distribué sous une licence open source. Aucun droit
12
+ n'est concédé implicitement, par estoppel ou autrement. La simple mise à
13
+ disposition du Logiciel, y compris dans un dépôt privé ou un registre de
14
+ paquets privé, ne vaut pas concession de licence.
15
+
16
+ 2. USAGE AUTORISÉ
17
+ Tout usage du Logiciel est subordonné à un contrat de licence écrit et signé
18
+ par le Titulaire (ci-après « Contrat de Licence »). En l'absence d'un tel
19
+ contrat, seul le Titulaire est autorisé à utiliser le Logiciel.
20
+
21
+ 3. INTERDICTIONS
22
+ Sauf autorisation écrite et préalable du Titulaire, il est interdit de :
23
+ a) copier, reproduire, modifier, adapter, traduire ou créer des œuvres
24
+ dérivées du Logiciel, en tout ou partie ;
25
+ b) distribuer, publier, sous-licencier, louer, prêter, vendre ou mettre à
26
+ disposition le Logiciel à des tiers, y compris sous forme de service
27
+ (SaaS) ou intégré dans un autre produit distribué ;
28
+ c) décompiler, désassembler ou procéder à de l'ingénierie inverse du
29
+ Logiciel, sauf dans les limites strictement prévues par l'article
30
+ L.122-6-1 du Code de la propriété intellectuelle ;
31
+ d) supprimer ou altérer les mentions de propriété, de copyright ou la
32
+ présente licence ;
33
+ e) utiliser le Logiciel, ses spécifications ou sa documentation pour
34
+ entraîner, affiner ou évaluer un modèle d'intelligence artificielle
35
+ destiné à des tiers, ou pour concevoir un produit concurrent.
36
+
37
+ 4. PRODUITS GÉNÉRÉS
38
+ Les fichiers produits par le compilateur NoraIvoire pour le compte d'un
39
+ licencié (CSS, Dart, TypeScript générés) peuvent être intégrés dans les
40
+ applications de ce licencié dans les conditions fixées par son Contrat de
41
+ Licence. Ils ne peuvent pas être redistribués en tant que bibliothèque,
42
+ framework ou kit de design autonome.
43
+
44
+ 5. CONFIDENTIALITÉ
45
+ Le Logiciel contient des informations confidentielles et des secrets
46
+ d'affaires du Titulaire. Toute personne y ayant accès s'engage à en
47
+ préserver la confidentialité.
48
+
49
+ 6. ABSENCE DE GARANTIE
50
+ Sauf stipulation contraire du Contrat de Licence, le Logiciel est fourni
51
+ « EN L'ÉTAT », sans garantie d'aucune sorte, expresse ou implicite. Dans
52
+ les limites autorisées par la loi, le Titulaire ne saurait être tenu
53
+ responsable d'aucun dommage résultant de l'utilisation du Logiciel.
54
+
55
+ 7. COMPOSANTS TIERS
56
+ Le Logiciel peut référencer des composants tiers soumis à leurs propres
57
+ licences, listés dans THIRD_PARTY_NOTICES.md. La présente licence ne
58
+ modifie pas ces licences.
59
+
60
+ 8. DROIT APPLICABLE
61
+ La présente licence est régie par le droit français. Tout litige relève de
62
+ la compétence des tribunaux du ressort de la Cour d'appel de Paris.
63
+
64
+ Contact licences : jonathan.kablan@gmail.com
package/README.md CHANGED
@@ -1,3 +1,143 @@
1
- # Temporary Holding Version
1
+ # @jonathankablan/noraivoire-mcp — Serveur MCP NoraIvoire
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ © 2026 Jonathan KABLAN — Propriétaire, tous droits réservés. Usage réservé aux licenciés.
4
+
5
+ Serveur [Model Context Protocol](https://modelcontextprotocol.io) qui donne aux agents IA (Claude Code, Claude Desktop, Cursor, VS Code…) un accès **en lecture seule** au contrat NoraIvoire : composants, tokens, validation `nora check` et recettes d'écrans.
6
+
7
+ - Transport **stdio**, un message JSON-RPC 2.0 par ligne. Serveur *dual-era* : requêtes sans état de la spec `2026-07-28` (version et capacités dans le `_meta` de chaque requête, `server/discover`) et poignée de main `initialize` des versions `2025-11-25`, `2025-06-18`, `2025-03-26`, `2024-11-05` (la version demandée est retenue si elle est connue, sinon la plus récente).
8
+ - **Zéro dépendance** : Node ≥ 20 suffit.
9
+ - Aucune exécution de commande, aucun réseau, aucune écriture disque (contrôlé par `nora audit`, contrôle `mcp:read-only`).
10
+
11
+ ## Outils
12
+
13
+ | Outil | Arguments | Renvoie |
14
+ |---|---|---|
15
+ | `nora_get_component` | `name` (ex. `btn`, `card`, `tilt`) | Définition du composant ou de l'effet : éléments, `data-tone`, `data-size`, tokens, accessibilité |
16
+ | `nora_list_tokens` | `group` facultatif (`color`, `space`, `radius`, `font`, `duration`) | Liste des groupes, ou variables CSS du groupe |
17
+ | `nora_validate` | `markup`, `format` (`html` par défaut, `jsx`, `tsx`, `vue`, `twig`, `jsp`, `angular`, `svelte`) | `{ valid, errors, warnings, issues[] }`, chaque problème avec sa correction `fix` |
18
+ | `nora_recipe` | `intent` (« connexion », « tarifs », « panier »…) | `{ id, title, components, html }` de l'écran de référence |
19
+
20
+ Tous les outils portent `readOnlyHint: true`, `destructiveHint: false`, `idempotentHint: true`, `openWorldHint: false`. Les résultats sont fournis en texte (JSON) et en `structuredContent`. Une erreur d'usage (composant inconnu, entrée trop longue, aucune recette) est un résultat `isError: true` lisible par l'agent, pas une erreur de protocole.
21
+
22
+ ## Fichiers lus
23
+
24
+ | Fichier | Quand |
25
+ |---|---|
26
+ | `packages/core/dist/manifest.json` | Au démarrage (lancer `npm run build` s'il manque) |
27
+ | `recipes/index.json` et les fichiers `.html` qu'il référence | À chaque appel de `nora_recipe` |
28
+
29
+ Le dossier des recettes peut être changé avec la variable `NORA_MCP_RECIPES`. Les noms de fichiers de recettes sont en liste blanche (`[a-z0-9-].html`), sans sous-dossier ni lien symbolique.
30
+
31
+ ## Limites
32
+
33
+ | Limite | Valeur |
34
+ |---|---|
35
+ | Message JSON-RPC entrant | 2 Mio de caractères (au-delà : erreur `-32600`, le serveur continue) |
36
+ | `markup` de `nora_validate` | 200 Kio de caractères |
37
+ | Autres arguments | 256 caractères |
38
+ | Portée de `nora_get_component` | Composants et effets uniquement : ni utilitaires ni primitives de mise en page (voir `llms-full.txt`) |
39
+ | `recipes/index.json` / fichier de recette | 256 Kio chacun, 500 recettes au plus |
40
+
41
+ Les lots JSON-RPC (tableaux) ne sont pas acceptés, conformément au protocole MCP depuis la version `2025-06-18`.
42
+
43
+ ## Installation depuis npm
44
+
45
+ ```bash
46
+ npm install --save-dev @jonathankablan/noraivoire-mcp
47
+ claude mcp add nora -- npx -y @jonathankablan/noraivoire-mcp
48
+ ```
49
+
50
+ Configuration JSON équivalente (Claude Desktop, Cursor, VS Code) : `"command": "npx"`, `"args": ["-y", "@jonathankablan/noraivoire-mcp"]`. Le paquet embarque le manifest (dépendance `@jonathankablan/noraivoire-core`) et les 20 recettes ; `NORA_MCP_RECIPES` reste disponible pour une autre bibliothèque. Les configurations ci-dessous lancent le serveur depuis le dépôt source.
51
+
52
+ ## Configuration
53
+
54
+ Les chemins ci-dessous sont relatifs à la racine du dépôt ; remplacez-les par un chemin absolu si le client ne démarre pas le serveur depuis cette racine.
55
+
56
+ ### Claude Code
57
+
58
+ ```bash
59
+ claude mcp add nora -- node packages/mcp/src/server.js
60
+ # portée projet, partagée avec l'équipe via .mcp.json :
61
+ claude mcp add --scope project nora -- node packages/mcp/src/server.js
62
+ ```
63
+
64
+ Ou directement dans `.mcp.json` à la racine du projet :
65
+
66
+ ```json
67
+ {
68
+ "mcpServers": {
69
+ "nora": {
70
+ "type": "stdio",
71
+ "command": "node",
72
+ "args": ["packages/mcp/src/server.js"]
73
+ }
74
+ }
75
+ }
76
+ ```
77
+
78
+ Vérifier avec `claude mcp list` puis `/mcp` dans une session.
79
+
80
+ ### Claude Desktop
81
+
82
+ `claude_desktop_config.json` (menu Réglages › Développeur › Modifier la configuration) :
83
+
84
+ ```json
85
+ {
86
+ "mcpServers": {
87
+ "nora": {
88
+ "command": "node",
89
+ "args": ["/chemin/absolu/vers/noraivoire/packages/mcp/src/server.js"]
90
+ }
91
+ }
92
+ }
93
+ ```
94
+
95
+ ### Cursor
96
+
97
+ `.cursor/mcp.json` dans le projet (ou `~/.cursor/mcp.json`) :
98
+
99
+ ```json
100
+ {
101
+ "mcpServers": {
102
+ "nora": {
103
+ "command": "node",
104
+ "args": ["${workspaceFolder}/packages/mcp/src/server.js"]
105
+ }
106
+ }
107
+ }
108
+ ```
109
+
110
+ ### VS Code (GitHub Copilot, mode agent)
111
+
112
+ `.vscode/mcp.json` :
113
+
114
+ ```json
115
+ {
116
+ "servers": {
117
+ "nora": {
118
+ "type": "stdio",
119
+ "command": "node",
120
+ "args": ["${workspaceFolder}/packages/mcp/src/server.js"]
121
+ }
122
+ }
123
+ }
124
+ ```
125
+
126
+ ### Autres clients
127
+
128
+ Tout client MCP compatible stdio : commande `node`, argument le chemin de `packages/mcp/src/server.js`, variable facultative `NORA_MCP_RECIPES`. Le binaire `nora-mcp` est fourni par le paquet npm (voir « Installation depuis npm »).
129
+
130
+ ## Essai manuel
131
+
132
+ ```bash
133
+ printf '%s\n' \
134
+ '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"essai","version":"1"}}}' \
135
+ '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"nora_validate","arguments":{"markup":"<button class=\"btn btn-primary\">OK</button>"}}}' \
136
+ | node packages/mcp/src/server.js
137
+ ```
138
+
139
+ ## Tests
140
+
141
+ `tests/unit/mcp.test.js` lance le serveur en sous-processus et dialogue en JSON-RPC : poignée de main, liste des outils, chaque outil, erreurs JSON-RPC, traversée de chemin, lien symbolique, index absent, entrées trop grandes.
142
+
143
+ Logiciel propriétaire © 2026 Jonathan KABLAN, tous droits réservés (voir LICENSE). La mise à disposition sur npm ne vaut pas concession de licence : tout usage est subordonné à un contrat de licence écrit.
package/package.json CHANGED
@@ -1,6 +1,34 @@
1
1
  {
2
2
  "name": "@jonathankablan/noraivoire-mcp",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "license": "UNLICENSED",
5
+ "description": "Serveur MCP NoraIvoire (stdio, lecture seule) : composants, tokens, validation et recettes pour les agents IA. Propriétaire.",
6
+ "author": "Jonathan KABLAN",
7
+ "type": "module",
8
+ "bin": {
9
+ "nora-mcp": "src/server.js"
10
+ },
11
+ "engines": {
12
+ "node": ">=20"
13
+ },
14
+ "dependencies": {
15
+ "@jonathankablan/noraivoire-cli": "0.1.1",
16
+ "@jonathankablan/noraivoire-core": "0.1.1"
17
+ },
18
+ "keywords": [
19
+ "noraivoire",
20
+ "mcp",
21
+ "model-context-protocol",
22
+ "ai"
23
+ ],
24
+ "files": [
25
+ "src",
26
+ "README.md",
27
+ "recipes",
28
+ "LICENSE"
29
+ ],
30
+ "publishConfig": {
31
+ "access": "public",
32
+ "registry": "https://registry.npmjs.org/"
33
+ }
34
+ }
@@ -0,0 +1,64 @@
1
+ <!doctype html>
2
+ <!-- NoraIvoire — recette « À propos et équipe ». © 2026 Jonathan KABLAN — Propriétaire. -->
3
+ <!-- Présentation de l'entreprise et de l'équipe. Données fictives. Aucun JS inline (CSP stricte). -->
4
+ <html lang="fr">
5
+ <head>
6
+ <meta charset="utf-8">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <title>À propos et équipe — NoraIvoire</title>
9
+ <link rel="stylesheet" href="../packages/core/dist/noraivoire.css">
10
+ <script type="module" src="../packages/core/dist/noraivoire.auto.js"></script>
11
+ </head>
12
+ <body>
13
+ <header>
14
+ <nav class="navbar" aria-label="Navigation principale">
15
+ <a class="navbar-brand" href="home.html">Boutique Démo</a>
16
+ <ul class="navbar-menu">
17
+ <li><a href="products.html">Produits</a></li>
18
+ <li><a href="pricing.html">Tarifs</a></li>
19
+ <li><a href="search.html">Recherche</a></li>
20
+ </ul>
21
+ <div class="navbar-actions">
22
+ <a class="btn" data-tone="neutral" data-size="sm" href="cart.html">Panier <span class="badge" data-tone="primary">2</span></a>
23
+ </div>
24
+ </nav>
25
+ </header>
26
+ <main class="container stack py-8">
27
+ <section class="stack" aria-labelledby="titre">
28
+ <h1 id="titre" class="text-xl font-bold">À propos</h1>
29
+ <p class="text-lg text-muted">Nous travaillons avec des ateliers indépendants depuis 2020.</p>
30
+ </section>
31
+ <section class="stack" aria-labelledby="equipe">
32
+ <h2 id="equipe" class="text-lg font-bold">L'équipe</h2>
33
+ <ul class="grid-auto p-0">
34
+ <li class="card stack text-center">
35
+ <span class="avatar mx-auto" data-tone="primary" data-size="lg" aria-hidden="true">A</span>
36
+ <h3 class="font-bold">Membre A</h3>
37
+ <p class="text-sm text-muted">Direction</p>
38
+ </li>
39
+ <li class="card stack text-center">
40
+ <span class="avatar mx-auto" data-tone="success" data-size="lg" aria-hidden="true">B</span>
41
+ <h3 class="font-bold">Membre B</h3>
42
+ <p class="text-sm text-muted">Design</p>
43
+ </li>
44
+ <li class="card stack text-center">
45
+ <span class="avatar mx-auto" data-tone="warning" data-size="lg" aria-hidden="true">C</span>
46
+ <h3 class="font-bold">Membre C</h3>
47
+ <p class="text-sm text-muted">Logistique</p>
48
+ </li>
49
+ <li class="card stack text-center">
50
+ <span class="avatar mx-auto" data-tone="neutral" data-size="lg" aria-hidden="true">D</span>
51
+ <h3 class="font-bold">Membre D</h3>
52
+ <p class="text-sm text-muted">Service client</p>
53
+ </li>
54
+ </ul>
55
+ </section>
56
+ <div class="cluster">
57
+ <a class="btn" href="contact.html">Nous écrire</a>
58
+ </div>
59
+ </main>
60
+ <footer class="container py-8 text-sm text-muted">
61
+ <p>© 2026 Boutique Démo — données fictives. <a class="link" data-tone="neutral" href="contact.html">Contact</a> · <a class="link" data-tone="neutral" href="about.html">À propos</a></p>
62
+ </footer>
63
+ </body>
64
+ </html>
@@ -0,0 +1,53 @@
1
+ <!doctype html>
2
+ <!-- NoraIvoire — recette « Panier ». © 2026 Jonathan KABLAN — Propriétaire. -->
3
+ <!-- Récapitulatif des articles et total. Données fictives. Aucun JS inline (CSP stricte). -->
4
+ <html lang="fr">
5
+ <head>
6
+ <meta charset="utf-8">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <title>Panier — NoraIvoire</title>
9
+ <link rel="stylesheet" href="../packages/core/dist/noraivoire.css">
10
+ <script type="module" src="../packages/core/dist/noraivoire.auto.js"></script>
11
+ </head>
12
+ <body>
13
+ <header>
14
+ <nav class="navbar" aria-label="Navigation principale">
15
+ <a class="navbar-brand" href="home.html">Boutique Démo</a>
16
+ <ul class="navbar-menu">
17
+ <li><a href="products.html">Produits</a></li>
18
+ <li><a href="pricing.html">Tarifs</a></li>
19
+ <li><a href="search.html">Recherche</a></li>
20
+ </ul>
21
+ <div class="navbar-actions">
22
+ <a class="btn" data-tone="neutral" data-size="sm" href="cart.html" aria-current="page">Panier <span class="badge" data-tone="primary">2</span></a>
23
+ </div>
24
+ </nav>
25
+ </header>
26
+ <main class="container stack py-8">
27
+ <h1 class="text-xl font-bold">Mon panier</h1>
28
+ <ul class="stack" aria-label="Articles">
29
+ <li class="card cluster">
30
+ <span class="font-bold">Lampe en rotin</span>
31
+ <span class="text-muted">1 × 45,00 €</span>
32
+ <button class="btn" data-tone="danger" data-size="sm" type="button" aria-label="Retirer la lampe en rotin">Retirer</button>
33
+ </li>
34
+ <li class="card cluster">
35
+ <span class="font-bold">Tasse en céramique</span>
36
+ <span class="text-muted">2 × 12,00 €</span>
37
+ <button class="btn" data-tone="danger" data-size="sm" type="button" aria-label="Retirer la tasse en céramique">Retirer</button>
38
+ </li>
39
+ </ul>
40
+ <section class="card stack" aria-labelledby="total">
41
+ <h2 id="total" class="text-lg font-bold">Total : 69,00 €</h2>
42
+ <p class="text-sm text-muted">Livraison calculée à l'étape suivante.</p>
43
+ <div class="cluster">
44
+ <a class="btn" href="checkout.html" data-size="lg">Passer commande</a>
45
+ <a class="btn" data-tone="neutral" href="products.html">Continuer mes achats</a>
46
+ </div>
47
+ </section>
48
+ </main>
49
+ <footer class="container py-8 text-sm text-muted">
50
+ <p>© 2026 Boutique Démo — données fictives. <a class="link" data-tone="neutral" href="contact.html">Contact</a> · <a class="link" data-tone="neutral" href="about.html">À propos</a></p>
51
+ </footer>
52
+ </body>
53
+ </html>
@@ -0,0 +1,65 @@
1
+ <!doctype html>
2
+ <!-- NoraIvoire — recette « Paiement ». © 2026 Jonathan KABLAN — Propriétaire. -->
3
+ <!-- Adresse de livraison, mode de paiement et total. Données fictives. Aucun JS inline (CSP stricte). -->
4
+ <html lang="fr">
5
+ <head>
6
+ <meta charset="utf-8">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <title>Paiement — NoraIvoire</title>
9
+ <link rel="stylesheet" href="../packages/core/dist/noraivoire.css">
10
+ <script type="module" src="../packages/core/dist/noraivoire.auto.js"></script>
11
+ </head>
12
+ <body>
13
+ <header>
14
+ <nav class="navbar" aria-label="Navigation principale">
15
+ <a class="navbar-brand" href="home.html">Boutique Démo</a>
16
+ <ul class="navbar-menu">
17
+ <li><a href="products.html">Produits</a></li>
18
+ <li><a href="pricing.html">Tarifs</a></li>
19
+ <li><a href="search.html">Recherche</a></li>
20
+ </ul>
21
+ <div class="navbar-actions">
22
+ <a class="btn" data-tone="neutral" data-size="sm" href="cart.html">Panier <span class="badge" data-tone="primary">2</span></a>
23
+ </div>
24
+ </nav>
25
+ </header>
26
+ <main class="container stack py-8">
27
+ <h1 class="text-xl font-bold">Paiement</h1>
28
+ <form class="grid-auto" action="#" method="post">
29
+ <section class="card">
30
+ <fieldset class="stack">
31
+ <legend class="text-lg font-bold">Livraison</legend>
32
+ <div class="field">
33
+ <label class="field-label" for="nom">Nom complet</label>
34
+ <input class="input" id="nom" name="nom" type="text" autocomplete="name" required>
35
+ </div>
36
+ <div class="field">
37
+ <label class="field-label" for="adresse">Adresse</label>
38
+ <input class="input" id="adresse" name="adresse" type="text" autocomplete="street-address" required>
39
+ </div>
40
+ <div class="field">
41
+ <label class="field-label" for="ville">Ville</label>
42
+ <input class="input" id="ville" name="ville" type="text" autocomplete="address-level2" required>
43
+ </div>
44
+ </fieldset>
45
+ </section>
46
+ <section class="card">
47
+ <fieldset class="stack">
48
+ <legend class="text-lg font-bold">Mode de paiement</legend>
49
+ <fieldset class="field">
50
+ <legend class="field-label">Moyen de paiement</legend>
51
+ <label class="radio"><input type="radio" name="mode" value="carte" checked> Carte bancaire</label>
52
+ <label class="radio"><input type="radio" name="mode" value="mobile"> Paiement mobile</label>
53
+ </fieldset>
54
+ <p class="text-sm text-muted">Le paiement est confié à votre prestataire certifié : aucune donnée de carte ne transite par cette page.</p>
55
+ <p class="text-lg font-bold">Total : 69,00 €</p>
56
+ <button class="btn w-full" type="submit" data-size="lg">Payer 69,00 €</button>
57
+ </fieldset>
58
+ </section>
59
+ </form>
60
+ </main>
61
+ <footer class="container py-8 text-sm text-muted">
62
+ <p>© 2026 Boutique Démo — données fictives. <a class="link" data-tone="neutral" href="contact.html">Contact</a> · <a class="link" data-tone="neutral" href="about.html">À propos</a></p>
63
+ </footer>
64
+ </body>
65
+ </html>
@@ -0,0 +1,59 @@
1
+ <!doctype html>
2
+ <!-- NoraIvoire — recette « Contact ». © 2026 Jonathan KABLAN — Propriétaire. -->
3
+ <!-- Formulaire de contact et coordonnées. Données fictives. Aucun JS inline (CSP stricte). -->
4
+ <html lang="fr">
5
+ <head>
6
+ <meta charset="utf-8">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <title>Contact — NoraIvoire</title>
9
+ <link rel="stylesheet" href="../packages/core/dist/noraivoire.css">
10
+ <script type="module" src="../packages/core/dist/noraivoire.auto.js"></script>
11
+ </head>
12
+ <body>
13
+ <header>
14
+ <nav class="navbar" aria-label="Navigation principale">
15
+ <a class="navbar-brand" href="home.html">Boutique Démo</a>
16
+ <ul class="navbar-menu">
17
+ <li><a href="products.html">Produits</a></li>
18
+ <li><a href="pricing.html">Tarifs</a></li>
19
+ <li><a href="search.html">Recherche</a></li>
20
+ </ul>
21
+ <div class="navbar-actions">
22
+ <a class="btn" data-tone="neutral" data-size="sm" href="cart.html">Panier <span class="badge" data-tone="primary">2</span></a>
23
+ </div>
24
+ </nav>
25
+ </header>
26
+ <main class="container grid-auto py-8">
27
+ <section class="card stack" aria-labelledby="titre">
28
+ <h1 id="titre" class="text-xl font-bold">Nous contacter</h1>
29
+ <form class="stack" action="#" method="post">
30
+ <div class="field">
31
+ <label class="field-label" for="nom">Nom</label>
32
+ <input class="input" id="nom" name="nom" type="text" autocomplete="name" required>
33
+ </div>
34
+ <div class="field">
35
+ <label class="field-label" for="email">Adresse e-mail</label>
36
+ <input class="input" id="email" name="email" type="email" autocomplete="email" required>
37
+ </div>
38
+ <div class="field">
39
+ <label class="field-label" for="sujet">Sujet</label>
40
+ <select class="select" id="sujet" name="sujet"><option>Commande</option><option>Partenariat</option><option>Autre</option></select>
41
+ </div>
42
+ <div class="field">
43
+ <label class="field-label" for="message">Message</label>
44
+ <textarea class="textarea" id="message" name="message" rows="6" required></textarea>
45
+ </div>
46
+ <button class="btn" type="submit">Envoyer</button>
47
+ </form>
48
+ </section>
49
+ <section class="card stack" aria-labelledby="coord">
50
+ <h2 id="coord" class="text-lg font-bold">Coordonnées</h2>
51
+ <p class="text-muted">contact@example.com</p>
52
+ <p class="text-muted">Réponse sous 2 jours ouvrés.</p>
53
+ </section>
54
+ </main>
55
+ <footer class="container py-8 text-sm text-muted">
56
+ <p>© 2026 Boutique Démo — données fictives. <a class="link" data-tone="neutral" href="contact.html">Contact</a> · <a class="link" data-tone="neutral" href="about.html">À propos</a></p>
57
+ </footer>
58
+ </body>
59
+ </html>
@@ -0,0 +1,66 @@
1
+ <!doctype html>
2
+ <!-- NoraIvoire — recette « Tableau de bord ». © 2026 Jonathan KABLAN — Propriétaire. -->
3
+ <!-- Indicateurs clés et dernières commandes. Données fictives. Aucun JS inline (CSP stricte). -->
4
+ <html lang="fr">
5
+ <head>
6
+ <meta charset="utf-8">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <title>Tableau de bord — NoraIvoire</title>
9
+ <link rel="stylesheet" href="../packages/core/dist/noraivoire.css">
10
+ <script type="module" src="../packages/core/dist/noraivoire.auto.js"></script>
11
+ </head>
12
+ <body>
13
+ <header>
14
+ <nav class="navbar" aria-label="Navigation de l'application">
15
+ <a class="navbar-brand" href="dashboard.html">Espace Démo</a>
16
+ <ul class="navbar-menu">
17
+ <li><a href="dashboard.html" aria-current="page">Tableau de bord</a></li>
18
+ <li><a href="notifications.html">Notifications <span class="badge" data-tone="danger">3</span></a></li>
19
+ <li><a href="profile.html">Profil</a></li>
20
+ <li><a href="settings.html">Paramètres</a></li>
21
+ </ul>
22
+ </nav>
23
+ </header>
24
+ <main class="container stack py-8">
25
+ <div class="cluster">
26
+ <h1 class="text-xl font-bold">Tableau de bord</h1>
27
+ <a class="btn" data-size="sm" href="products.html">Nouveau produit</a>
28
+ </div>
29
+ <section class="grid-auto" aria-label="Indicateurs">
30
+ <article class="card stack gap-2">
31
+ <h2 class="text-sm text-muted">Chiffre d'affaires</h2>
32
+ <p class="text-xl font-bold">12 480 €</p>
33
+ <span class="badge" data-tone="success">+8 %</span>
34
+ </article>
35
+ <article class="card stack gap-2">
36
+ <h2 class="text-sm text-muted">Commandes</h2>
37
+ <p class="text-xl font-bold">342</p>
38
+ <span class="badge" data-tone="success">+3 %</span>
39
+ </article>
40
+ <article class="card stack gap-2">
41
+ <h2 class="text-sm text-muted">Paniers abandonnés</h2>
42
+ <p class="text-xl font-bold">27</p>
43
+ <span class="badge" data-tone="warning">+5 %</span>
44
+ </article>
45
+ <article class="card stack gap-2">
46
+ <h2 class="text-sm text-muted">Remboursements</h2>
47
+ <p class="text-xl font-bold">4</p>
48
+ <span class="badge" data-tone="danger">+1</span>
49
+ </article>
50
+ </section>
51
+ <section class="card stack" aria-labelledby="dernieres">
52
+ <h2 id="dernieres" class="text-lg font-bold">Dernières commandes</h2>
53
+ <table class="w-full">
54
+ <caption class="sr-only">Quatre dernières commandes</caption>
55
+ <thead><tr><th scope="col">N°</th><th scope="col">Date</th><th scope="col">Montant</th><th scope="col">Statut</th></tr></thead>
56
+ <tbody>
57
+ <tr><td>1042</td><td>14/10/2026</td><td>89,00 €</td><td><span class="badge" data-tone="success">Payée</span></td></tr>
58
+ <tr><td>1041</td><td>14/10/2026</td><td>24,50 €</td><td><span class="badge" data-tone="warning">En attente</span></td></tr>
59
+ <tr><td>1040</td><td>13/10/2026</td><td>156,00 €</td><td><span class="badge" data-tone="success">Payée</span></td></tr>
60
+ <tr><td>1039</td><td>13/10/2026</td><td>12,00 €</td><td><span class="badge" data-tone="danger">Annulée</span></td></tr>
61
+ </tbody>
62
+ </table>
63
+ </section>
64
+ </main>
65
+ </body>
66
+ </html>
@@ -0,0 +1,25 @@
1
+ <!doctype html>
2
+ <!-- NoraIvoire — recette « Erreur 404 ». © 2026 Jonathan KABLAN — Propriétaire. -->
3
+ <!-- Page introuvable avec retours utiles. Données fictives. Aucun JS inline (CSP stricte). -->
4
+ <html lang="fr">
5
+ <head>
6
+ <meta charset="utf-8">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <title>Erreur 404 — NoraIvoire</title>
9
+ <link rel="stylesheet" href="../packages/core/dist/noraivoire.css">
10
+ <script type="module" src="../packages/core/dist/noraivoire.auto.js"></script>
11
+ </head>
12
+ <body>
13
+ <main class="container py-12">
14
+ <section class="card mx-auto stack text-center" data-size="lg" aria-labelledby="titre">
15
+ <span class="badge" data-tone="danger">Erreur 404</span>
16
+ <h1 id="titre" class="text-xl font-bold">Page introuvable</h1>
17
+ <p class="text-muted">La page demandée n'existe pas ou a été déplacée.</p>
18
+ <div class="cluster">
19
+ <a class="btn" href="home.html">Retour à l'accueil</a>
20
+ <a class="btn" data-tone="neutral" href="search.html">Rechercher</a>
21
+ </div>
22
+ </section>
23
+ </main>
24
+ </body>
25
+ </html>
@@ -0,0 +1,25 @@
1
+ <!doctype html>
2
+ <!-- NoraIvoire — recette « Erreur 500 ». © 2026 Jonathan KABLAN — Propriétaire. -->
3
+ <!-- Erreur serveur avec nouvelle tentative. Données fictives. Aucun JS inline (CSP stricte). -->
4
+ <html lang="fr">
5
+ <head>
6
+ <meta charset="utf-8">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <title>Erreur 500 — NoraIvoire</title>
9
+ <link rel="stylesheet" href="../packages/core/dist/noraivoire.css">
10
+ <script type="module" src="../packages/core/dist/noraivoire.auto.js"></script>
11
+ </head>
12
+ <body>
13
+ <main class="container py-12">
14
+ <section class="card mx-auto stack text-center" data-size="lg" aria-labelledby="titre">
15
+ <span class="badge" data-tone="danger">Erreur 500</span>
16
+ <h1 id="titre" class="text-xl font-bold">Une erreur est survenue</h1>
17
+ <p class="text-muted">Nos équipes ont été prévenues. Réessayez dans quelques instants.</p>
18
+ <div class="cluster">
19
+ <a class="btn" href="#">Réessayer</a>
20
+ <a class="btn" data-tone="neutral" href="contact.html">Contacter le support</a>
21
+ </div>
22
+ </section>
23
+ </main>
24
+ </body>
25
+ </html>
@@ -0,0 +1,29 @@
1
+ <!doctype html>
2
+ <!-- NoraIvoire — recette « Mot de passe oublié ». © 2026 Jonathan KABLAN — Propriétaire. -->
3
+ <!-- Demande de lien de réinitialisation. Données fictives. Aucun JS inline (CSP stricte). -->
4
+ <html lang="fr">
5
+ <head>
6
+ <meta charset="utf-8">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <title>Mot de passe oublié — NoraIvoire</title>
9
+ <link rel="stylesheet" href="../packages/core/dist/noraivoire.css">
10
+ <script type="module" src="../packages/core/dist/noraivoire.auto.js"></script>
11
+ </head>
12
+ <body>
13
+ <main class="container py-12">
14
+ <section class="card mx-auto stack" aria-labelledby="titre">
15
+ <h1 id="titre" class="text-xl font-bold">Mot de passe oublié</h1>
16
+ <p class="text-muted">Saisissez votre adresse : nous vous enverrons un lien de réinitialisation.</p>
17
+ <form class="stack" action="#" method="post">
18
+ <div class="field">
19
+ <label class="field-label" for="email">Adresse e-mail</label>
20
+ <input class="input" id="email" name="email" type="email" autocomplete="email" required value="demo@" aria-invalid="true" aria-describedby="email-erreur">
21
+ <p class="field-error" id="email-erreur">Adresse incomplète : ajoutez le domaine, par exemple demo@example.com.</p>
22
+ </div>
23
+ <button class="btn w-full" type="submit">Envoyer le lien</button>
24
+ </form>
25
+ <p class="text-sm text-center"><a class="link" href="login.html">Retour à la connexion</a></p>
26
+ </section>
27
+ </main>
28
+ </body>
29
+ </html>