> For the complete documentation index, see [llms.txt](https://docs.ipcheck.ing/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ipcheck.ing/developer/fr/development/coding-conventions.md).

# Conventions de code

Ce sont les règles de cette base de code. Ce ne sont pas des préférences de style à discuter à chaque pull request — ce sont les critères sur lesquels les relecteurs s'appuient, et ce qui permet de garder lisible un projet avec deux runtimes et quatre langues.

## Langue

{% hint style="warning" %}
**JavaScript uniquement. Pas de TypeScript.**
{% endhint %}

Les nouveaux fichiers sont `.js` ou `.vue`. Pas de `lang="ts"` sur un `<script setup>` bloc, pas de `.ts` modules, pas de migration incrémentale vers TypeScript. Une PR qui introduit TypeScript devra le retirer.

Les commentaires de code, les messages de commit et la documentation du dépôt sont rédigés en **anglais**. Les packs de locale portent évidemment leur propre langue.

## Fonctions

Les fonctions nouvelles et réécrites utilisent **`const` la syntaxe fléchée**:

{% code title="le style maison" %}

```js
const isValidMAC = (address) => {
    const normalized = address.replace(/[:-]/g, '');
    return normalized.length === 12 && /^[0-9A-Fa-f]+$/.test(normalized);
};

const loadSecurityChecklist = async () => { /* … */ };
```

{% endcode %}

Deux réserves :

* **Les méthodes d'objet conservent la syntaxe raccourcie.** `{ status(code) { … } }` reste tel quel.
* **Les constantes fléchées ne sont pas remontées.** Déclarez-les avant le code qui les appelle.

Cela s'applique au code que vous écrivez ou réécrivez. Ne **défiler** convertissez pas en masse les `déclarations de fonctions` existantes — un diff plein de changements de style sans rapport est plus difficile à relire que la fonctionnalité qu'il masque.

## Commentaires

Trois règles, par ordre d'importance :

1. **Tout nouveau fichier commence par un commentaire d'en-tête indiquant son objectif.** Pour un gestionnaire d'API, cela signifie sa route et ce qu'il fait. C'est ainsi que le reste de la base de code reste navigable sans ouvrir chaque fichier — la documentation au niveau du répertoire s'arrête volontairement à « lisez les commentaires d'en-tête ».
2. **Les grands templates et les grandes fonctions comportent des commentaires de bloc pour chaque zone significative.** Un template de 400 lignes `.vue` devrait vous indiquer où se termine la zone d'entrée et où commence la zone de résultat.
3. **Les commentaires décrivent le code tel qu'il est maintenant.** Pas de récit de changelog : pas de « auparavant nous faisions X », pas de « cela corrige le bug où… ». L'historique Git couvre le passé. Un commentaire qui explique *pourquoi* un choix non évident a été fait est précieux ; un commentaire qui raconte la modification qui l'a produit est du bruit.

Un commentaire devrait rester plus court que le code qu'il explique.

## Conventions frontend

Architecture complète dans [Frontend](/developer/fr/architecture/frontend.md). Les règles à connaître quand vous écrivez du code :

* **API de composition, `<script setup>`, partout.** Pas d'Options API.
* **Alias de chemin `@` → `frontend/`.** Importez sous `@/utils/valid-ip.js`, jamais avec un tas de `../`.
* **shadcn-vue d'abord.** Vérifiez `frontend/components/ui/` s'il existe déjà une primitive, puis le catalogue shadcn-vue pour en copier une. Le Tailwind fait main est le dernier recours.
* **Uniquement des jetons de conception sémantiques.** `bg-info`, `bg-action`, `text-muted-foreground`, et consorts — les jetons se thématisent eux-mêmes. N'écrivez jamais `dark:` des utilitaires en paires doubles.
* **`console.*` C'est acceptable sur le frontend.** C'est interdit uniquement sur le backend (voir ci-dessous).

### Où va un helper

Cette décision revient dans presque chaque changement, donc elle a une réponse fixe :

<table><thead><tr><th width="200">Répertoire</th><th>Ce qui va là</th></tr></thead><tbody><tr><td><code>frontend/composables/</code></td><td>Logique qui a besoin de la réactivité ou du cycle de vie Vue. Nommée <code>use-xxx.js</code>, exportant <code>useXxx()</code>.</td></tr><tr><td><code>frontend/utils/</code></td><td>Helpers et E/S indépendants du framework. Jamais <code>use-</code> préfixés.</td></tr><tr><td><code>frontend/lib/</code></td><td>couche de support shadcn uniquement — pour l'instant juste <code>cn()</code>. N'y ajoutez rien.</td></tr><tr><td><code>frontend/data/</code></td><td>Configuration statique et registres : outils, sections, accomplissements, changelog.</td></tr></tbody></table>

Une précision : **une fonction pure qui vit à côté d'un composable est exportée depuis le fichier de ce composable**, pas promue dans son propre module dans `utils/`. `ipFieldTone()` expédié depuis `composables/use-status-tone.js` est le modèle à reproduire.

## Le code partagé vit dans `common/`

Tout ce dont les deux moitiés ont besoin va dans `common/` — la source unique de vérité — et le frontend y accède via un **pont de réexport léger** dans `utils/`, afin que les imports frontend conservent leur `@/utils/...` forme familière :

{% code title="frontend/utils/valid-ip.js" %}

```js
// La source unique de vérité est common/valid-ip.js (partagée avec le backend).
// Ce fichier existe comme un simple réexport pour que le code front-end puisse continuer à écrire
// `import { isValidIP } from '@/utils/valid-ip.js'` sans se soucier d'où
// se trouve l'implémentation.
export { isValidIP, isIPv6, isValidDomain } from '../../common/valid-ip.js';
```

{% endcode %}

`frontend/utils/fetch-with-timeout.js` suit le même modèle. Lorsque vous ajoutez un pont, ajoutez une spec qui importe **les deux** chemins et vérifie qu'ils concordent — `tests/valid-ip.test.js` fait exactement cela, ce qui empêche un pont de se transformer discrètement en seconde implémentation.

## Conventions backend

Vue d'ensemble complète dans [Backend](/developer/fr/architecture/backend.md). Les règles qui comptent :

### Forme du handler

Un fichier par route sous `api/`, avec un unique export par défaut :

```js
export default async (req, res) => {
    // lire req.query / req.body, appeler l'upstream, écrire une réponse
};
```

La forme des erreurs est concise et cohérente : `400` sur une entrée incorrecte, `res.status(500).json({ error: error.message })` en cas d'échec de l'upstream. Le frontend ne les affiche pas tels quels.

### Jamais de simple `fetch()`

Chaque appel HTTP sortant depuis `api/` passe par `fetchUpstream` depuis `common/fetch-with-timeout.js`Cela applique un délai d'attente de 8 secondes et une valeur par défaut de `User-Agent`. Un fournisseur amont bloqué doit expirer, pas maintenir la connexion ouverte.

### Gardes, pas de vérifications en ligne

Le contrôle d'accès et la validation des paramètres vivent dans le middleware (`common/guards.js`), attaché dans `backend-server.js`. Les handlers ne les répètent jamais :

* `requireReferer` — globalement dans `/api/*`
* `requireValidIP()` / `requireValidDomain()` / `requireValidPrefix()` / `requireValidASN()` / `requireValidProviderId()` / `requireValidReportId()` — par route

Une nouvelle forme de paramètre signifie une nouvelle garde dans `common/guards.js`, pas une vérification codée en dur en haut d'un handler.

### Journalisation

{% hint style="danger" %}
**`console.*` est interdit dans les fichiers backend.** Toujours le logger pino partagé de `common/logger.js`.
{% endhint %}

Pino est d'abord centré sur le contexte — l'objet vient en premier, le court message ensuite :

{% code title="le style maison" %}

```js
import logger from '../common/logger.js';

logger.error({ err: e, mac: macAddress }, 'mac-checker handler failed');
logger.warn({ err: e, query }, 'whois: RDAP IP lookup failed, trying WHOIS');
```

{% endcode %}

Encore deux règles :

* **Les handlers ne journalisent jamais de lignes « requête reçue ».** La journalisation par requête est `pino-http`l'affaire de `/api` montée sur `LOG_HTTP=true`.
* **les lignes de démarrage uniquement commencent par un emoji** — 🚀 en écoute, 📦 prêt, 📥 téléchargement, 🛡️ sécurité, 🐢 limitation, 🗓️ planification, ⚠️ récupérable, ❌ échec. Les journaux par requête restent sobres.

La configuration est `LOG_LEVEL` (par défaut `info`), `LOG_FORMAT=json` pour les expéditeurs de journaux, et `LOG_HTTP=true`. Il n'y a pas de `NODE_ENV` nulle part dans ce projet — voir [Journalisation](/developer/fr/configuration/logging.md).

### Mise en cache en périphérie

Chaque `/api/*` réponse est par défaut `Cache-Control: no-store`. Les routes publiques à évolution lente optent pour le middleware `cacheable(maxAgeSeconds)` dans `backend-server.js`. Écrivez les TTL comme des expressions multipliées (`24 * 60 * 60`), pas comme des secondes brutes. Les handlers eux-mêmes ne touchent jamais à `Cache-Control`, et les endpoints par utilisateur ou authentifiés ne sont jamais enveloppés.

## Ce qui est livré avec votre changement

Deux choses ne sont pas optionnelles, et toutes deux sont vérifiées :

* **couverture i18n.** Tout ce qui expose du texte va dans **les quatre locales** (`en` / `zh` / `fr` / `ru`) dans le même changement, y compris l'entrée `frontend/data/changelog.json` entrée. Voir [i18n](/developer/fr/development/i18n.md).
* **Tests.** Toute logique non visuelle exerçable sans appel réseau est livrée avec une spec dans `tests/`, dans le même changement. Mettez à jour les specs concernées quand le comportement change — ne différez pas. Voir [Tests](/developer/fr/development/testing.md).

Puis lancez `pnpm check`. Il doit être au vert avant que vous ne remettiez le changement.

## Ensuite

* [Ajout d'un nouvel outil](/developer/fr/development/adding-a-new-tool.md) — tout ce qui précède, appliqué de bout en bout.
* [Comment contribuer](/developer/fr/contributing/how-to-contribute.md) — branches, commits et attentes pour les PR.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.ipcheck.ing/developer/fr/development/coding-conventions.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
