> 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/architecture/project-structure.md).

# Structure du projet

Comment le dépôt est organisé : un dépôt, deux processus, trois couches.

MyIP est un dépôt unique qui fournit **deux processus Node** et contient **trois couches de code**. Rien d'autre. Une fois cette image en tête, chaque fichier de l'arborescence a une place évidente.

## Deux processus

| Processus        | Fichier              | Port par défaut           | Tâche                                                                                                       |
| ---------------- | -------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------- |
| Serveur statique | `frontend-server.js` | `18966` (`FRONTEND_PORT`) | Sert la SPA compilée depuis `dist/`, relaye `/api` vers le backend, gère le repli de l'historique de la SPA |
| Serveur API      | `backend-server.js`  | `11966` (`BACKEND_PORT`)  | L'application Express 5 — chaque `/api/*` route, gardes, limitation de débit, jeux de données hors ligne    |

`pnpm start` exécute les deux avec `concurrently`. En production, ils sont généralement gérés par pm2 (`ecosystem.config.cjs` définit `myip-frontend` et `myip-backend`) ou par l'image Docker, qui exécute `npm start` dans un seul conteneur et n'expose que `18966`.

```mermaid
flowchart LR
    B["Navigateur"]
    F["frontend-server.js :18966<br/>serveur statique dist/ + repli SPA"]
    A["backend-server.js :11966<br/>API Express 5"]
    U["Fournisseurs amont<br/>ipinfo.io, ip-api.com, RIPEstat, OONI"]
    D["Jeux de données locaux<br/>MaxMind mmdb, CAIDA as2org / as-rel, index PeeringDB, registres MAC IEEE"]

    B -->|"GET / , /tools/whois , /assets/*"| F
    B -->|"GET /api/*"| F
    F -->|"http-proxy-middleware"| A
    A -->|"fetchUpstream, délai d'attente de 8 s"| U
    A --> D
```

{% hint style="info" %}
Seul le port du frontend doit être accessible depuis Internet. Le backend écoute sur `11966` pour le proxy ; gardez-le sur le même hôte ou sur un réseau privé. Voir [Proxy inverse et domaines](/developer/fr/getting-started/reverse-proxy-and-domains.md).
{% endhint %}

## Trois couches de code

| Répertoire         | S'exécute où           | Contenu                                                                                                                                                                                                                                                                                                                                                                                                            |
| ------------------ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `frontend/`        | Navigateur             | La SPA Vue 3 — composants, routeur, store Pinia, locales, registre d'outils                                                                                                                                                                                                                                                                                                                                        |
| `api/` + `server/` | Node                   | Le backend. `api/` contient un module de gestionnaire Express par route, rien d'autre ; `server/` contient le code réservé au backend que ces gestionnaires partagent : gardes, journaliseur, middleware de cache en périphérie, clients amont, l'interrogateur d'état du service, et — dans `server/datasets/` — le moteur de jeux de données hors ligne avec ses lecteurs MaxMind / CAIDA / PeeringDB / IEEE MAC |
| `common/`          | Node **et** navigateur | Uniquement le code que le frontend ou la compilation importe aussi : validateurs, l'enveloppe fetch, les calculs IP, le registre des locales, le schéma de rapport. Il contient aussi les répertoires de jeux de données téléchargés (`*-db/`)                                                                                                                                                                     |

`common/` est la seule couche qui franchit la frontière, donc un module n'y atterrit que lorsque le frontend ou la compilation l'importe aussi (`valid-ip.js`, `fetch-with-timeout.js`, `report-schema.js`, `dns-record-types.js`, `ip-math.js`, `mac-input.js`, `locale-registry.js`, …). Ces modules restent exempts de `fs` et `process` accès, n'importent jamais depuis `server/`, et sont réexportés via de fines passerelles dans `frontend/utils/` afin que le code de l'application continue d'importer `@/utils/...`. Les préoccupations propres à Node vivent dans `server/` — par exemple, le User-Agent amont est construit dans `server/upstream-ua.js` (qui lit `package.json` depuis le disque) et injecté dans `common/fetch-with-timeout.js` au démarrage.

## Arborescence annotée

```
.
├── backend-server.js       Application Express : table des routes, ordre des middleware, TTL de cache par route
├── frontend-server.js      Serveur statique + proxy /api + repli de l'historique SPA
├── sentry-instrument.js    Amorçage Sentry du backend, chargé via `node --import`
├── ecosystem.config.cjs    définitions de processus pm2 (porte le drapeau --import)
├── index.html              Vite entry / SPA shell
├── vite.config.js          Configuration de build : alias, chunks manuels, proxy de développement
├── Dockerfile              Construction en deux étapes (voir ci-dessous)
│
├── frontend/               SPA Vue 3  → voir Frontend
│   ├── App.vue             Coquille légère : navigation, dialogues globaux + <router-view> conservé en mémoire
│   ├── main.js             Amorçage + initialisation dynamique conditionnée par l'environnement
│   ├── store.js            Store principal Pinia
│   ├── router/             Table des routes + redirection héritée /?tool= + hooks de transition de page
│   ├── data/               Registres statiques : outils, sections, réussites, bases de données IP, paramètres de connectivité par défaut et listes d'importation sélectionnées, tableaux de personas, sondes de blocage de publicités
│   │   └── banners/        Données de bannières de section au déploiement — ignorées par git (voir Bannières de section)
│   ├── components/         Home / ToolPage / Nav / sections / outils-avancés / rapport / widgets / ui
│   ├── composables/        Logique `useXxx` adaptée à Vue
│   ├── utils/              Aides indépendantes du framework : plomberie globale de l'application à la racine (bus d'événements, bus de commandes, …)
│   │   ├── ip/             Mise en forme et validation des données IP / ASN (y compris les passerelles vers common/)
│   │   ├── report/         Le pipeline de rapport partageable
│   │   ├── features/       La logique pure d'une fonctionnalité (ip-calc.js, bulk-lookup-extract.js, mtr-parse.js, pulse-*.js, …)
│   │   └── getips/ · dnsleaks/ · persona/   Modules de sondage par source
│   └── locales/            Un pack par langue enregistrée + sous-packs à la demande
│
├── api/                    Un gestionnaire par route  → voir Backend
│
├── server/                 Code réservé au backend
│   ├── guards.js           Middleware de validation des paramètres
│   ├── cache-control.js    middleware de cache en périphérie cacheable()
│   ├── logger.js           singleton pino
│   ├── ip-timezone.js      Coordonnées → fuseau IANA + middleware withTimeZone()
│   ├── offline-data.js     Verrou 503 au démarrage pour les routes dont les données sont encore en téléchargement
│   ├── as-relationships.js Relations amont / pair / client cohérentes avec le graphe
│   ├── asn-profile.js      Composition de /api/asn-profile : échéances et statuts
│   ├── bulk-lookup-sources.js  Sources de données locales pour /api/bulk-lookup, sélectionnées par BULK_LOOKUP_SOURCE
│   ├── rdap.js             Client RDAP pour les domaines, IPs et numéros AS
│   ├── asrank.js           Client CAIDA AS Rank
│   ├── service-status-*.js Liste des fournisseurs, sondeur, transformation de la réponse
│   └── datasets/           Le moteur de jeux de données hors ligne et ses lecteurs
│       ├── datasets.js         Lignes de jeux de données hors ligne : GeoLite2, as2org, as-rel, PeeringDB, IEEE MAC
│       ├── dataset-updater.js  Un moteur : téléchargement au démarrage, actualisation quotidienne, verrou, publication, surveillance
│       ├── maxmind-service.js  Lecteurs GeoLite2 locaux + recherche
│       ├── as-org-db.js        Recherche CAIDA AS → organisation
│       ├── as-rel-db.js        Relations CAIDA AS (graphe p2c + p2p)
│       ├── peeringdb-distill.js Dump PeeringDB en flux → index par ASN
│       ├── peeringdb-db.js     Recherche locale dans l'index PeeringDB
│       └── oui-db.js           Recherche locale dans le registre IEEE MAC (MAC Lookup)
│
├── common/                 Code que le frontend ou la compilation importe aussi
│   ├── valid-ip.js         Validateurs IP / domaine
│   ├── fetch-with-timeout.js  fetchWithTimeout (5 s) / fetchUpstream (8 s)
│   ├── ip-math.js          Arithmétique BigInt IP / CIDR (calculateur IP + containment RDAP)
│   ├── dns-record-types.js Les types d'enregistrements DNS auxquels le résolveur répond
│   ├── mac-input.js        Analyse des requêtes d'adresse MAC / préfixe
│   ├── locale-registry.js  Les langues de l'interface, et tous les mappages qui en dérivent
│   ├── locale-pack.js      Aides de forme pour les packs de langue + la suppression au moment de la compilation
│   ├── report-schema.js    Schéma du rapport partageable, validateur et masquage IP
│   ├── maxmind-db/         GeoLite2-City.mmdb · GeoLite2-ASN.mmdb
│   ├── as-org-db/          as-org2info.txt
│   ├── as-rel-db/          as-rel2.txt
│   ├── peeringdb-db/       peeringdb-index.json
│   └── oui-db/             oui.csv · mam.csv · oui36.csv · iab.csv · cid.csv
│
├── tests/                  Spécifications du lanceur de tests Node (`node --test`)
└── dist/                   Sortie de compilation (générée, non commise)
```

## Comment une requête circule

**Chargement de la page.** Le navigateur demande `frontend-server.js` une URL.

1. `/api/*` est d'abord intercepté par le middleware proxy et transféré vers `http://localhost:11966/api`.
2. Sinon `express.static` essaie de servir un vrai fichier depuis `dist/`, en appliquant un `Cache-Control` en-tête par classe de ressource — `dist/assets/**` et `dist/fonts/**` obtiennent un an plus `immutable` (Vite leur applique des hachages de contenu), les images à la racine 7 jours, `index.html` et `manifest.webmanifest` zéro dans les navigateurs mais 24 h en périphérie, tout le reste une heure.
3. Si aucun fichier ne correspond, le repli de l'historique de la SPA renvoie `index.html` pour que vue-router puisse résoudre une route côté client comme `/tools/whois`. Le repli est volontairement restreint : `GET` uniquement, `Accept: text/html` uniquement, et jamais pour un chemin dont le dernier segment contient un point — un `/assets/x.js` manquant doit renvoyer 404, et non recevoir un corps HTML.

**Appel API.** À l'intérieur du backend, la requête traverse la chaîne de middleware dans `backend-server.js` — facultatif `pino-http`, limiteur de débit, ralentisseur, analyseur de corps JSON, le `no-store` par défaut, la garde globale du referer, puis les gardes de paramètres propres à la route et le gestionnaire. Un gestionnaire effectue normalement un appel amont, via `fetchUpstream`; l'exception est `/api/asn-profile`, qui compose plusieurs sources en parallèle, chacune avec sa propre échéance. Détails dans [Backend](/developer/fr/architecture/backend.md).

{% hint style="warning" %}
`backend-server.js` monte également `express.static('./dist')`. C'est une commodité pour les configurations qui exposent directement le backend ; le chemin normal reste navigateur → serveur frontend → proxy.
{% endhint %}

## Pipeline de compilation

`pnpm build` lance Vite, qui génère `dist/`:

* `@` se résout en `frontend/`.
* `manualChunks` sépare les dépendances lourdes en quatre chunks — `vendor` (vue / vue-router / vue-i18n), `chart` (chart.js), `speedtest` (@cloudflare/speedtest) et `browser-detect` (thumbmarkjs / ua-parser-js) — et extrait les aides de source IP et d'authentification dans `utils-getips` / `utils-auth`.
* Les polices vont dans `dist/fonts/`, tout le reste est haché par contenu dans `dist/assets/`.
* Les sourcemaps ne sont générées que lorsque `SENTRY_AUTH_TOKEN` est défini, en tant que `cartes masquées, et sont supprimées de` après l'envoi — voir `dist/` d'erreurs [Surveillance des erreurs](/developer/fr/configuration/error-monitoring.md).

Docker compile en deux étapes. L'étape de compilation installe avec `pnpm install --frozen-lockfile` et exécute `pnpm run build`; l'étape de production ne copie que `node_modules`, `package.json`, `dist/`, les deux fichiers serveur, `sentry-instrument.js`, `api/`, `server/` et `common/`. Pas de chaîne d'outils, pas d'étape d'installation à l'exécution. Voir [Déployer avec Docker](/developer/fr/getting-started/deploy-with-docker.md).

## Mode développement

`pnpm dev` démarre Vite et le backend ensemble. Vite sert la SPA sur `FRONTEND_PORT` elle-même (pas de `dist/`, pas de `frontend-server.js`) et relaie `/api` vers `BACKEND_PORT` — de sorte que la forme des URL est identique à celle de la production. Le backend s'exécute sous `nodemon` avec `--import ./sentry-instrument.js`, ce qui est sans effet sans DSN backend. Les détails de configuration se trouvent dans [Environnement de développement](/developer/fr/development/dev-environment.md).

## Où effectuer une modification

| Vous souhaitez…                                                  | Aller à                                                                                                                                                       |
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Ajouter un outil à l'interface                                   | `frontend/data/tools.js` — voir [Ajout d'un nouvel outil](/developer/fr/development/adding-a-new-tool.md)                                                     |
| Ajouter une route API                                            | Un nouveau fichier dans `api/`, câblé dans `backend-server.js`                                                                                                |
| Ajouter un utilitaire utilisé uniquement par le backend          | `server/` (un lecteur de jeu de données va dans `server/datasets/`)                                                                                           |
| Ajouter un validateur dont le navigateur a aussi besoin          | `common/`, plus une passerelle dans `frontend/utils/`                                                                                                         |
| Modifier le texte                                                | `frontend/locales/` — voir [i18n](/developer/fr/development/i18n.md)                                                                                          |
| Afficher une bannière promotionnelle ou sponsor sous une section | Un fichier de données dans `frontend/data/banners/` au moment de la compilation — voir [Bannières de section](/developer/fr/configuration/section-banners.md) |
| Ajouter un test                                                  | `tests/` — voir [Tests](/developer/fr/development/testing.md)                                                                                                 |


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.ipcheck.ing/developer/fr/architecture/project-structure.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
