> 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

MyIP est un dépôt unique qui embarque **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 l'application SPA compilée depuis `dist/`, effectue un proxy de `/api` vers le backend, gère le fallback d'historique SPA |
| Serveur API      | `backend-server.js`  | `11966` (`BACKEND_PORT`)  | L'application Express 5 — chaque `/api/*` route, garde-fous, 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/>statique dist/ + fallback 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"]

    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 frontend doit être joignable 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             | L'application SPA Vue 3 — composants, routeur, store Pinia, locales, registre d'outils                                                       |
| `api/`      | Node                   | Un module gestionnaire Express par route, rien d'autre                                                                                       |
| `common/`   | Node **et** navigateur | Code partagé par les deux moitiés : validateurs, l'enveloppe fetch, garde-fous, journaliseur, services MaxMind / CAIDA, le schéma du rapport |

`common/` est la seule couche qui franchit la frontière. Les modules dont le navigateur a aussi besoin (`valid-ip.js`, `fetch-with-timeout.js`, `report-schema.js`) restent exempts de `fs` et `process` accès, et sont réexportés via de minces passerelles dans `frontend/utils/` afin que le code de l'app continue d'importer `@/utils/...`. Les éléments propres à Node qui casseraient cette règle vivent dans leur propre fichier — par exemple, l'User-Agent amont est construit dans `common/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 middlewares, cacheable()
├── frontend-server.js      Serveur statique + proxy /api + fallback d'historique SPA
├── sentry-instrument.js    Initialisation Sentry du backend, chargée via `node --import`
├── ecosystem.config.cjs    Définitions des processus pm2 (porte l'option --import)
├── index.html              Entrée Vite / coque de l'SPA
├── vite.config.js          Config de build : alias, chunks manuels, proxy de dev
├── Dockerfile              Build en deux étapes (voir ci-dessous)
│
├── frontend/               SPA Vue 3  → voir Frontend
│   ├── App.vue             Coque légère : fournisseurs globaux + <router-view>
│   ├── main.js             Initialisation + init dynamique conditionnée par l'environnement
│   ├── store.js            Store principal Pinia
│   ├── router/             Table des routes
│   ├── data/               Registres statiques : outils, sections, réalisations, bases de données IP
│   ├── components/         Accueil / StandaloneTool / sections / advanced-tools / ui
│   ├── composables/        Logique `useXxx` aware de Vue
│   ├── utils/              Aides agnostiques au framework (bus d'événements, getips/, …)
│   └── locales/            en / zh / fr / ru + sous-paquets à la demande
│
├── api/                    Un gestionnaire par route  → voir Backend
│
├── common/                 Code partagé
│   ├── guards.js           Middleware de validation des paramètres
│   ├── fetch-with-timeout.js  fetchWithTimeout (5 s) / fetchUpstream (8 s)
│   ├── logger.js           singleton pino
│   ├── maxmind-service.js  Lecteurs GeoLite2 locaux + recherche
│   ├── maxmind-updater.js  Téléchargement planifié de GeoLite2
│   ├── caida-updater.js    Téléchargement planifié de as2org / as-rel
│   ├── as-org-db.js        Recherche CAIDA AS → organisation
│   ├── as-rel-db.js        Relations CAIDA AS (graphe p2c)
│   ├── service-status-*.js Liste des fournisseurs, sondeur, transformation de réponse
│   ├── maxmind-db/         GeoLite2-City.mmdb · GeoLite2-ASN.mmdb
│   ├── as-org-db/          as-org2info.txt
│   └── as-rel-db/          as-rel2.txt
│
├── tests/                  Spécifications du lanceur de tests Node (`node --test`)
└── dist/                   Sortie de build (générée, non commitée)
```

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

**Appel API.** Dans le backend, la requête traverse la chaîne de middlewares dans `backend-server.js` — optionnel `pino-http`, limiteur de débit, ralentisseur, analyseur du corps JSON, le `no-store` par défaut, le garde-fou global du referer, puis les gardes des paramètres par route et le gestionnaire. Le gestionnaire effectue au plus un appel amont, via `fetchUpstream`. Détails dans [Backend](/developer/fr/architecture/backend.md).

{% hint style="warning" %}
`backend-server.js` monte aussi `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 build

`pnpm build` exécute Vite, qui émet `dist/`:

* `@` se résout en `frontend/`.
* `manualChunks` découpe les dépendances lourdes dans leurs propres chunks (`vendor` pour vue / vue-router / vue-i18n, plus `chart`, `speedtest`, `svgmap`, `browser-detect`) et extrait les helpers de source IP et d'authentification dans `utils-getips` / `utils-auth`.
* Les polices vont dans `dist/fonts/`, tout le reste avec hachage de contenu sous `dist/assets/`.
* Les cartes source sont générées uniquement lorsque `SENTRY_AUTH_TOKEN` est défini, en tant que `masquées` cartes, et sont supprimées de `dist/` après l'envoi — voir [Surveillance des erreurs](/developer/fr/configuration/error-monitoring.md).

Docker construit en deux étapes. L'étape de build installe avec `pnpm install --frozen-lockfile` et exécute `pnpm run build`; l'étape de production copie uniquement `node_modules`, `package.json`, `dist/`, les deux fichiers serveur, `sentry-instrument.js`, `api/` 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 l'application SPA sur `FRONTEND_PORT` lui-même (pas de `dist/`, pas de `frontend-server.js`) et effectue un proxy `/api` vers `BACKEND_PORT` — donc la forme de l'URL est identique à 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 sont dans [Environnement de développement](/developer/fr/development/dev-environment.md).

## Où faire une modification

| Vous voulez…                   | Accédez à                                                                                                 |
| ------------------------------ | --------------------------------------------------------------------------------------------------------- |
| 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/`, branché dans `backend-server.js`                                          |
| Ajouter un validateur partagé  | `common/`, plus un pont dans `frontend/utils/` si le navigateur en a besoin                               |
| Modifier le texte              | `frontend/locales/` — voir [i18n](/developer/fr/development/i18n.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 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/architecture/project-structure.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.
