Tout ce qui suit vit sous `duxt` dans votre `app/app.config.ts`. Le
fonctionnement de la fusion, et pourquoi les tableaux remplacent au lieu de
s’ajouter, est dans [Configuration](/getting-started/configuration).

## Site

| Clé                | Par défaut           | Ce qu’elle contrôle                                     |
| :----------------- | :------------------- | :-------------------------------------------------------- |
| `title`            | **aucun**            | Le nom dans la barre de navigation et dans le titre SEO    |
| `logo`              | **aucun**            | Un logo à la place du couple icône et nom — voir ci-dessous  |
| `version`          | **aucune**           | Le badge à côté                                            |
| `organization`     | **aucune**           | Qui publie le site, pour schema.org — voir ci-dessous      |
| `locales`          | les sept             | Quelles langues de la couche ce site sert                  |
| `breadcrumb`       | `true`               | `false` retire le fil au-dessus du titre de page           |
| `pageIcon`          | **aucune**           | Icône des pages qui n'en déclarent aucune — celle de la section l'emporte |
| `packageManagers`  | pnpm, npm, yarn, bun | Quels gestionnaires propose un bloc de commande, dans cet ordre |
| `requestSamples`   | sept sur douze     | Quels échantillons de code propose le client d’essai — voir [Échantillons de requête](/reference/openapi/request-samples) |
| `sampleLanguages`  | **aucune**         | Grammaires Shiki supplémentaires, pour `x-codeSamples` dans un langage qu’aucun échantillon ne nomme |
| `poweredBy`        | activé               | `false` retire la ligne « Powered by duxt » du pied de page |

## Comportement

| Clé | Par défaut | Effet |
| :-- | :-- | :-- |
| `copy.models` | ChatGPT, Claude | Cibles dans l’ordre du menu ; la liste remplace le défaut |
| `contributors.avatarUrl` | modèle GitHub | `{username}` est remplacé pour chaque contributeur |
| `toc.depth` | `3` | Titre le plus profond de la table des matières |
| `toc.scrollOffset` | `96` | Ligne d’activation sous le bord de la fenêtre |
| `search.fuzzy` | `0.35`, `3`, `20` | Seuil Fuse, longueur minimale et limite |
| `search.recentPages` | `5` | Pages récentes ; `0` masque la liste |
| `openapi.exampleDepth` | `6` | Profondeur maximale des exemples dérivés |
| `openapi.schemaDepth` | `8` | Profondeur maximale de l’arbre de schéma |
| `shortcuts.singleCharacter` | `true` | Touches globales `?`, `[` et `]` ; `⌘/Ctrl+K` reste |
| `analytics.track` | **aucun** | Callback indépendant du fournisseur par interaction |

```ts [app/app.config.ts]
export default defineAppConfig({
  duxt: {
    copy: {
      models: [
        {
          label: 'Mon assistant',
          icon: 'simple-icons:openai',
          url: 'https://example.com/new?prompt='
        }
      ]
    },
    contributors: {
      avatarUrl: 'https://github.com/{username}.png?size=96'
    },
    toc: { depth: 4, scrollOffset: 112 },
    search: {
      fuzzy: { threshold: 0.3, minMatchCharLength: 3, limit: 15 },
      recentPages: 8
    },
    openapi: { exampleDepth: 6, schemaDepth: 8 },
    shortcuts: { singleCharacter: false }
  }
})
```

Les listes remplacent leurs valeurs par défaut. Une liste `copy.models` vide
retire les cibles externes, pas les actions de copie et de source.
`search.recentPages: 0` ne conserve aucune nouvelle entrée. Les options fuzzy
ne concernent que les approximations après une recherche Content vide. Sans
callback analytics, rien n’est envoyé ; consentement, fournisseur et stockage
appartiennent au site consommateur.

### `logo`

| Champ     | Type     | Notes                                                        |
| :-------- | :------- | :------------------------------------------------------------ |
| `src`     | `string` | La marque. Sans valeur, l'icône générique reste près de `title` |
| `srcDark` | `string` | Permuté par CSS sous la classe `dark`, pas par script        |
| `alt`     | texte    | Retombe sur `title`                                          |

En définir un, c'est [Donner son identité à votre site](/guides/brand-your-site).

### `organization`

Le nœud `Organization` que les moteurs de recherche et les résumés d'IA lisent
pour nommer une source. Absent tant que vous ne le définissez pas : duxt rend la
documentation d'autrui et ne devine pas de qui.

| Champ  | Type     | Notes                                                           |
| :----- | :------- | :---------------------------------------------------------------- |
| `name` | texte    | Le nom de l'éditeur. Sans lui, rien n'est publié                |
| `url`  | `string` | Son site. Se rabat sur `site.url`                               |
| `logo` | `string` | Absolu, ou un chemin depuis la racine ; carré et d'au moins 112px |


## Annonces

Un avis à l’échelle du site — une version, une migration ou une maintenance.
Tant qu’aucune entrée n’est écrite, rien n’est rendu et aucun espace n’est
réservé.

```ts [app/app.config.ts]
announcements: [
  {
    text: { 'en-GB': 'Version 2 is out.', 'fr-FR': 'La version 2 est disponible.' },
    link: { label: 'Lire les notes', to: '/releases/v2' }
  },
  {
    id: 'march-maintenance',
    text: 'Maintenance prévue dimanche à partir de 09:00 UTC.',
    placement: 'below-header',
    startsAt: '2026-03-01T09:00:00Z',
    endsAt: '2026-03-08T09:00:00Z'
  }
],
announcementOptions: { maxVisible: 1 }
```

La liste est dessinée dans l’ordre : une version et une panne sont deux
annonces, et la fin de l’une ne doit pas retirer l’autre.

| Champ       | Type                                               | Notes                                                            |
| :---------- | :------------------------------------------------- | :--------------------------------------------------------------- |
| `text`      | texte                                              | Littéral, clé i18n ou enregistrement par locale                |
| `link`      | lien                                               | Une action ; les autres appartiennent à la page liée            |
| `placement` | `above-header`, `below-header` ou `above-content`   | Emplacement ; `above-header` par défaut                          |
| `startsAt`  | `string`                                           | Début ; toute valeur comprise par `Date`                        |
| `endsAt`    | `string`                                           | Fin                                                              |
| `id`        | `string`                                           | Identité de fermeture ; dérivée du contenu et du lien sinon   |

### Où elles sont affichées

| Emplacement       | Position                                                         |
| :---------------- | :--------------------------------------------------------------- |
| `above-header`    | Pleine largeur au bord du navigateur, au-dessus de la navigation |
| `below-header`    | Pleine largeur sous la navigation, au-dessus des barres latérales |
| `above-content`   | Dans la colonne du document, avec les avis de version et langue  |

`above-content` appartient à la colonne du document : il apparaît sur les
pages de documentation, pas sur une landing qui ne possède pas cette colonne.

`announcementOptions.maxVisible` limite le nombre d’annonces affichées par
emplacement. Un nombre limite **chaque** emplacement, un objet les limite
séparément (`{ 'above-header': 1 }`) ; `null`, une clé omise ou l’absence de
`maxVisible` signifie illimité. Fermer l’annonce du haut fait remonter la
suivante.

### Quand elles sont affichées

`startsAt` et `endsAt` sont lus dans le **navigateur**, par rapport à l’horloge
du lecteur. L’annonce commence et finit sans déploiement ni rechargement. La
fenêtre est semi-ouverte : visible depuis `startsAt` et jusqu’à `endsAt`.

Ajoutez un décalage lorsque l’instant précis compte
(`2026-03-01T09:00:00Z`). Sans fuseau, l’heure locale du lecteur est utilisée.
Une date invalide est traitée comme absente afin qu’une faute ne masque pas
l’avis silencieusement.

### Fermeture

Une annonce fermée le reste pendant la navigation, les rechargements et les
changements de langue. C’est son **identité** qui est mémorisée :

- avec `id`, cette chaîne indépendante de la locale ; la changer remontre
  l’annonce à tous,
- sans `id`, une valeur dérivée de toutes les variantes de `text` et `link` ;
  changer la phrase crée une nouvelle annonce, réordonner les clés non.

Définissez `id` pour corriger le texte sans le remontrer. Les fermetures ne
vivent que dans `localStorage` et les clés d’annonces retirées sont supprimées.
Comme l’horloge et les fermetures appartiennent au navigateur, la bande est
dessinée après l’hydratation.

La surface du composant est décrite dans
[DuxtAnnouncements](/reference/components/layout/duxt-announcements).

## Navigation et liens

Une entrée de section est un lien, plus un champ qui lui est propre :

| Champ      | Type     | Notes                                                              |
| :--------- | :------- | :------------------------------------------------------------------ |
| `pageIcon` | `string` | Icône des pages de cette section qui n'en déclarent aucune. Prime sur `duxt.pageIcon` ; le frontmatter d'une page l'emporte toujours |

Utile là où une page ne peut porter aucune icône — le frontmatter d'un ADR est
figé à `title`, `description`, `status` et `date`, si bien que le journal des
décisions s'afficherait sans.

| Clé          | Par défaut       | Ce qu’elle contrôle                                          |
| :----------- | :--------------- | :------------------------------------------------------------ |
| `navigation` | une entrée       | Liens de la barre ; une entrée avec `children` devient un menu |
| `sections`   | **vide**         | La deuxième rangée — les parties de premier niveau de la doc   |
| `links`      | **vide**         | Liens à icône à droite de la barre                             |
| `aside`      | le titre seul    | `title` et `links` sous le sommaire                            |
| `footer`     | **vide**         | `copyright` et `legal`                                         |
| `landing`    | une action | La page à `/`             |

La plupart sont livrés vides, pour deux raisons différentes. `links`,
`aside.links`, `footer.legal`, `title`, `version` et le texte de la page
d’accueil désignent un projet précis — un dépôt, une communauté, des mentions
légales, un nom, une version publiée, une phrase sur ce qu’il fait — et
appartiennent à qui exploite le site. `sections` nomme les
parties d’une **arborescence** de documentation, et l’arborescence est la vôtre :
quatre onglets pointant vers des noms de dossier devinés par la couche ne
mèneraient nulle part. Définissez-le une fois que votre documentation a des
sections ; d’ici là, la rangée ne s’affiche pas et la barre latérale montre
l’arbre entier, ce qui est la bonne forme pour une documentation sans sections.

**Une rangée par source.** Une entrée appartient à la source sous le préfixe
d’URL de laquelle elle se trouve, et la rangée affiche les entrées de la source
où se trouve le lecteur — un site dont la documentation est à la racine et qui
publie autre chose sous `/demo` écrit donc une seule liste `sections`, et chaque
zone y dessine sa part. Une section générée sous une zone (`/demo/openapi`)
appartient à cette zone plutôt que d’en être une. Un site à source unique a une
zone, chaque entrée y est, et la rangée est exactement la liste écrite.

### Page d’accueil

La page à `/` dessine trois bandes, et chacune est absente tant que sa clé n’est
pas définie.

| Clé           | Par défaut                    | Ce qu’elle dessine                                 |
| :------------ | :---------------------------- | :--------------------------------------------------- |
| `badge`       | **aucun**                     | La pastille au-dessus du titre — du texte, ou un objet badge |
| `headline`    | **aucun**                     | Le `h1` ; à défaut, `title`                          |
| `description` | **aucune**                    | Le paragraphe en dessous, et la meta description de la page |
| `actions`     | une, « Lire la documentation » | Les boutons du bloc principal ; une action sans `to` pointe vers la première section |
| `command`     | **aucune**                    | Une commande d’installation copiable sous les boutons |
| `preview`     | **aucun**                     | Une page de ce site, intégrée dans une fenêtre de navigateur |
| `features`    | **vide**                      | La grille de cartes                                  |

`command` est une simple `string`, pas du texte : une commande shell est
identique dans toutes les langues, et une commande traduite par erreur ne
s’exécute pas. La couche n’en livre aucune — elle ne sait pas comment s’appelle
votre projet, pour la même raison que `links` est vide.

Il n’y a délibérément pas d’appel à l’action final. Les boutons du bloc
principal sont l’appel ; les répéter sous une grille de cartes demande à un lecteur qui
vient d’arriver de décider deux fois.

`badge` est livré vide pour la même raison que `links` : une pastille au-dessus
du titre dit quelque chose de l’état d’un projet — « beta », « v2 est sortie » —
et la couche ne sait rien de l’état du vôtre. Une chaîne est la forme courte ;
l’objet ajoute une icône, une couleur et une destination.

| Champ de `badge` | Type      | Remarques                                                 |
| :--------------- | :-------- | :--------------------------------------------------------- |
| `label`          | texte     | Obligatoire. `{version}` est remplacé par la `version` du site |
| `icon`           | `string`  | N’importe quel nom Iconify                                  |
| `variant`        | `string`  | `default`, `secondary`, `outline`, `success`, `destructive` |
| `to`             | `string`  | Fait de toute la pastille un lien                           |
| `external`       | `boolean` | Le nouvel onglet                                            |

```ts [app/app.config.ts]
badge: {
  label: '{version} publiée',
  icon: 'lucide:rocket',
  variant: 'success',
  to: 'https://github.com/acme/sdk/releases/latest',
  external: true
}
```

`preview` est une fenêtre vivante, pas une image. Elle intègre une page de **ce**
site dans un cadre de navigateur que le lecteur peut faire défiler, parcourir et
dont il peut changer le thème sans quitter la page d’accueil. Le cadre n’est
monté qu’une fois la bande visible, et jamais pendant le rendu serveur — une
iframe dans le HTML initial, c’est un second chargement complet en concurrence
avec le premier.

| Champ de `preview` | Type     | Remarques                                                 |
| :----------------- | :------- | :---------------------------------------------------------- |
| `to`               | `string` | La page à intégrer ; par défaut la première section          |
| `height`           | `string` | Toute longueur CSS. Par défaut `32rem`, `24rem` sous `sm`    |
| `src`              | `string` | Une capture À LA PLACE de la page vivante                    |
| `srcDark`          | `string` | Sert le mode sombre ; sans lui, `src` sert les deux          |
| `alt`              | texte    | Le texte alternatif de l’image et le nom accessible du cadre |

::callout{type="tip" title="Une capture est l’option la moins coûteuse"}
Le cadre vivant charge l’application une seconde fois. Un site qui préfère ne
pas payer cela définit `src` et obtient la même fenêtre autour d’une image fixe.
::

### Forme d’un lien

| Champ         | Type                | Remarques                                        |
| :------------ | :------------------ | :------------------------------------------------ |
| `label`       | texte               | Obligatoire                                       |
| `to`          | `string`            | Un chemin de documentation est localisé, pas une URL |
| `icon`        | `string`            | N’importe quel nom Iconify, p. ex. `lucide:rocket` |
| `description` | texte               | Affichée dans un menu déroulant de la barre        |
| `external`    | `boolean`           | Le nouvel onglet et la flèche — jamais le routage  |
| `children`    | `DuxtLink[]`        | Transforme une entrée de barre en menu déroulant   |
| `variant`     | variante de bouton  | `landing.actions` uniquement                       |

Tout champ marqué _texte_ accepte un littéral, une clé i18n ou un enregistrement
par locale — voir [Localisation](/concepts/localisation).

## Sources

| Clé             | Lue à            | Ce qu’elle contrôle                          |
| :-------------- | :--------------- | :------------------------------------------- |
| `sources`       | la compilation   | Les sources de documentation                  |
| `sourceOptions` | la compilation   | Comment ces sources deviennent des préfixes   |
| `versions`      | l’exécution      | Remplace les versions déduites quand elles ont besoin de libellés ou de descriptions |

Les deux clés de source ont [leur propre page](/reference/sources). `locales`
est la troisième clé lue à la compilation : modifier l’une des trois impose une
recompilation.

## Le flux

`/rss.xml` est vide tant que `feed.path` ne nomme pas une section :

```ts
feed: { path: '/changelog', title: 'mon projet — publications' }
```

Désactivé par défaut, à dessein. Un flux est une liste de choses qui **se sont
produites**, et une page de référence modifiée n’est pas un événement — un site
qui publie chaque modification comme élément apprend à ses lecteurs à se
désabonner. Les éléments sont ordonnés par la `date` propre à la page, à défaut
par le dernier commit qui l’a touchée, et seule la version par défaut de chaque
source contribue : un changelog versionné ne répète donc pas chaque entrée une
fois par version.


La section vers laquelle il pointe d’ordinaire est un
[journal des versions](/reference/changelog), dont les pages portent chacune une
`date`.

## Généré, pas écrit

| Clé                | Écrit par        | Contient                                         |
| :----------------- | :--------------- | :----------------------------------------------- |
| `resolvedSources`  | la compilation   | Le manifeste : quelle collection sert quel préfixe |
| `layerVersion`     | la compilation   | La version de duxt, pour le pied de page          |
| `layerRepository`  | la compilation   | Le dépôt de duxt, pour le pied de page            |

Définir l’un des trois à la main est écrasé à la compilation suivante.