> ## Documentation Index
> Fetch the complete documentation index at: https://www.chapterjs.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Visite du projet

> À quoi sert chaque fichier de votre projet, la règle unique qui les organise, et comment l’éditeur et le rechargement à chaud vous aident

Votre projet tourne. Avant de le modifier, faites-en le tour : un projet ChapterJS est petit, et une fois que vous savez à quoi sert chaque fichier, vous savez où va chaque chose pour le reste du tutoriel.

**buddy**

**.chapterjs**

**node\_modules**

**public**

**src**

**presence.ts**

**.env**

**.env.example**

**.gitignore**

**package.json**

**tsconfig.json**

## La règle unique : ce qu’un fichier exporte dit ce qu’il est

Tout ce que fait votre bot vit dans `src/`. ChapterJS ne vous demande jamais d’enregistrer quoi que ce soit : il charge chaque fichier de `src/`, et ce que les fichiers **exportent**, fabriqué avec l’une de ses fonctions, est ce que le bot fait tourner. Le modèle a un fichier, `src/presence.ts` : ce que Discord affiche sous le nom de votre bot, « Getting ready ». Ajoutez-en un second, une commande, dans `src/commands/ping.ts` :

```ts src/commands/ping.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { command } from 'chapterjs';

export default command({
  name: 'ping',
  description: 'Répond Pong !',
  async run({ interaction }) {
    await interaction.reply('Pong !');
  },
});
```

Enregistrez : le terminal dit `↻ Reloaded in 12 ms, 1 command, a presence loaded`, puis `↻ Commands updated on My Server`, et `/ping` est sur votre serveur de test. Rien d’autre ne dit « ceci est une commande » : `command()` le dit. Son `name` est ce que les gens tapent après le `/`, et le fichier dit seulement ce que la commande *fait*. Changez `name` en `'hello'`, et la commande devient `/hello` ; déplacez le fichier vers `src/fun/ping.ts`, et rien ne change.

C’est la règle pour tout ce que le framework fait tourner :

| Déclaré avec | Ce que c’est |
| - | - |
| `command({ name, ... })` | Une commande slash : `name: 'ping'` est `/ping`, `name: 'mod ban'` est `/mod ban` |
| `event({ name, ... })` | Une réaction à un événement : `name: 'memberJoin'` tourne quand quelqu’un arrive |
| `button({ ... })`, `select({ ... })`, `modal({ ... })`, `embed(...)` | Un bouton, un menu déroulant, un formulaire ou un embed, nommé par son export : `export const vote = button(...)` est le bouton `vote` |
| `task({ ... })` | Quelque chose que le bot fait tout seul, régulièrement ou à des heures données, nommé par son export |
| `language({ locale, ... })` | Une langue du bot : `locale: 'fr'` est le français |
| `presence({ ... })` | Ce que le bot affiche sous son nom, déclaré une fois |

Un fichier peut en déclarer plusieurs, et un fichier qui n’en déclare aucun n’est que du code : `src/lib/`, `src/db/`, tout ce que vous importez depuis les autres. Les modèles de `create chapterjs` font les deux : votre projet garde un dossier par sorte (`src/commands/`, et plus tard `src/events/`), et `tickets` met tout ce qui touche aux tickets dans `src/tickets/` : la commande, le formulaire, les boutons, et leurs textes dans les deux langues. Un dossier n’est qu’un dossier.

Pourquoi ce choix ? Parce que l’alternative, une liste quelque part qui dit « la commande `/ping` est dans ce fichier, l’événement de bienvenue dans celui-là », est une liste que vous devez tenir à jour à la main. Ici, il n’y a pas de liste. Ajouter une commande, c’est ajouter une déclaration ; en retirer une, c’est la supprimer.

## Le même import partout

Chaque fichier commence par `import { command } from 'chapterjs'`, ou `event`, `button`... Tous viennent du même paquet, `chapterjs`. Il n’y a rien d’autre à importer : pas de client, pas de configuration, pas de fichier du framework. Et chaque fonction sait à quoi s’attendre d’après ce que vous lui donnez : `event({ name: 'memberJoin' })` donne un membre à votre fonction, `event({ name: 'messageCreate' })` un message, avec la même ligne d’import.

## `.chapterjs/` : généré, ignoré, supprimable

Ce dossier est écrit par le framework, et git l’ignore. Il contient ce que votre **projet** ajoute aux types de `chapterjs` : les fichiers de `public/` que `asset()` propose, vos langues, qui typent `t`, et vos commandes. Votre éditeur le lit pour compléter ce que vous tapez et souligner une erreur. Il garde aussi un petit cache (ce qui a été enregistré en dernier auprès de Discord, pour que relancer ne coûte rien) et, plus tard, le bot compilé.

Il est écrit quand vous installez le projet (`postinstall` lance `chapterjs sync`) et à chaque démarrage de `chapterjs dev`. Si votre éditeur dit un jour qu’il ne connaît pas les fichiers de `public/` ou vos textes, lancez `chapterjs sync` (`pnpm chapterjs sync`, ou l’équivalent) et rechargez l’éditeur. Vous pouvez aussi supprimer le dossier : il est reconstruit.

## Essayer l’éditeur

Ouvrez `src/commands/ping.ts` dans votre éditeur, et dans `run`, tapez `interaction.` avec le point. L’éditeur liste tout ce qu’une interaction sait faire : `reply`, `defer`, `edit`, `followUp`, `delete`... Tapez maintenant `interaction.replu('Pong !')` avec une faute de frappe : c’est souligné avant même d’enregistrer, avec la méthode qu’il ne connaît pas.

Voilà ce que veut dire « aucun type à écrire ». Vos fichiers sont en TypeScript, pour que l’éditeur puisse faire cela, mais chaque type vient du framework. Vous n’en écrivez jamais.

> [!NOTE]
>
> Si rien n’est souligné et rien n’est complété, votre éditeur ne lit pas les types. Dans Visual Studio Code, vérifiez que le dossier ouvert est bien le projet lui-même (celui qui contient `package.json`), pas un dossier au-dessus, et lancez `chapterjs sync` une fois.

## Essayer le rechargement à chaud

Lancez le bot (`pnpm dev`) et laissez-le tourner. Changez la réponse dans `src/commands/ping.ts` :

```ts src/commands/ping.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { command } from 'chapterjs';

export default command({
  name: 'ping',
  description: 'Répond Pong !',
  async run({ interaction }) {
    await interaction.reply('Pong ! 🏓');
  },
});
```

Enregistrez. Le terminal dit :

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
↻ Reloaded in 12 ms, 1 command, a presence loaded
```

Utilisez à nouveau `/ping` dans Discord : la nouvelle réponse. Vous ne redémarrez jamais le bot pendant que vous l’écrivez : chaque fichier de `src/` est surveillé, et un enregistrement le recharge, avec chaque fichier qui l’importe.

Cassez maintenant le fichier exprès : supprimez `'Pong ! 🏓')` pour que la ligne devienne `await interaction.reply(;`, et enregistrez.

```text theme={"theme":{"light":"github-light","dark":"vesper"}}
✗ src/commands/ping.ts:6 Expression expected
⚠ Reloaded with an error: that file keeps running its last working version
```

Le bot est toujours en ligne, et `/ping` répond toujours avec la dernière version qui fonctionnait. Corrigez le fichier, enregistrez, et il se recharge. Une erreur ne fait jamais tomber le bot : vous pouvez essayer librement.

## Les autres fichiers

| Fichier | Ce que c’est |
| - | - |
| `public/` | Les images et fichiers qu’envoie votre bot. Vide pour l’instant ; un chapitre suivant s’en sert. |
| `node_modules/` | Les paquets installés par votre gestionnaire de paquets, dont `chapterjs`. Ne le modifiez jamais, ne le commitez jamais. |
| `.env`, `.env.example` | Les valeurs dont votre bot a besoin (la page précédente). |
| `.gitignore` | Ce que git laisse de côté : `.env`, `node_modules/`, `.chapterjs/` et `data/`, les données de vos stores. |
| `package.json` | L’identité de votre projet : son nom, ses dépendances et ses scripts (`dev`, `build`, `start`, `typecheck`). |
| `tsconfig.json` | Les réglages de TypeScript. Il ne fait que pointer vers `.chapterjs/`, où sont les vrais réglages ; laissez-le tel quel. |

`chapterjs` est la seule dépendance de votre bot. `typescript` et `@types/node` sont des dépendances de développement : elles vérifient votre code dans l’éditeur et avant une compilation, et ne sont pas nécessaires pour faire tourner le bot.

## Vos fichiers, votre ordre

À mesure qu’un projet grandit, `src/commands/` se remplit. Comme le framework lit ce que les fichiers exportent et non l’endroit où ils sont, rangez-les à votre façon :

**src**

**fun**

**dice.ts**

**ping.ts**

**moderation**

**shared.ts**

**warn.ts**

* **Un dossier n’est qu’un dossier.** `src/fun/dice.ts` déclare `/dice` aussi bien que `src/commands/dice.ts` le ferait. Discord ne voit jamais vos dossiers.
* **Un fichier qui ne déclare rien est à vous.** `shared.ts` contient le code que plusieurs fichiers partagent ; importez-le comme n’importe quel fichier.
* **Un fichier peut déclarer plusieurs choses.** `warn.ts` peut contenir la commande `/warn`, le bouton qu’elle affiche et l’événement qui l’enregistre, chacun exporté sous son propre nom.

Une sous-commande est une affaire de `name`, pas de dossier : `name: 'mod warn'` est `/mod warn`, où que soit le fichier. C’est utilisé plus tard pour des commandes comme `/mod ban`.

## Récapitulatif

* Ce qu’un fichier exporte dit ce qu’il est : `command({ name: 'ping' })` est `/ping`, et rien ne l’enregistre.
* Chaque fichier importe ses fonctions de `chapterjs`, et chacune sait à quoi s’attendre d’après ce que vous lui donnez.
* `.chapterjs/` contient les types générés ; votre éditeur les lit ; `chapterjs sync` les réécrit.
* Enregistrez un fichier et le bot l’utilise ; un fichier cassé garde sa dernière version qui fonctionnait.
* Les dossiers et les noms de fichiers vous servent à ranger : le framework lit ce que les fichiers exportent.

> [card] [Votre première commande](https://www.chapterjs.org/fr/tutorial/first-command.md)
>
> Écrire /dice de zéro, et voir ce que le framework vérifie pour vous.

> [card] [Guide : Structure du projet](https://www.chapterjs.org/fr/setup/project-structure.md)
>
> Chaque fichier et dossier, en bref.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.