Skip to main content
Voir en Markdown

Routage et chemins

Le path d'une page est l'URL à laquelle elle répond. Il est comparé littéralement, sauf s'il contient un segment :param ou *, auquel cas il devient un motif.

Formes de chemin

Forme Exemple Correspond à
Racine / La page d'accueil.
Statique /about Ce chemin exact, et rien d'autre.
Imbriquée /settings/billing Un nombre quelconque de segments statiques.
Dynamique /blog/:slug Un segment, capturé sous le nom slug.
Catch-all /docs/:rest* Le reste du chemin, capturé sous rest — doit être le dernier segment.
Joker /files/* Tout ce qui se trouve sous /files/, sans nom de capture.

Un chemin doit correspondre à ^/[a-z0-9-_/:*]*$ : il commence par /, et seules les minuscules sont admises. /users/:userId est rejeté — écrivez /users/:userid, ou mieux, /users/:id.

Segments dynamiques

Un segment :param capture exactement un segment de chemin — jamais au-delà d'un /. /blog/:slug correspond à /blog/hello mais pas à /blog/2026/hello ; utilisez /blog/:slug* pour ce dernier cas.

Les routes dynamiques sont généralement associées à un bloc collection, afin qu'une seule définition de page génère une route par enregistrement :

app.yaml
pages:
  - name: Blog Post
    path: /blog/:slug
    collection: { table: posts, slugField: slug }
    components:
      - { type: text, element: h1, content: '$record.title' }

Voir Collections et markdown pour le contrat de collection.

Routes de détail d'enregistrement

Pour servir un seul enregistrement à une URL sans générer une route par enregistrement, associez un segment dynamique à une source de données en mode single. param nomme le segment de chemin d'où lire l'identifiant :

app.yaml
pages:
  - name: Task
    path: /tasks/:id
    dataSource:
      table: tasks
      mode: single
      param: id
    components:
      - { type: text, element: h1, content: '$record.title' }
      - { type: text, content: '$record.description' }

Une requête dont le paramètre ne correspond à aucun enregistrement renvoie un 404.

Le segment de langue

Sovrium ne préfixe jamais un chemin qui se résout déjà. Lorsque app.languages est configuré, le runtime lit le premier segment du chemin et, s'il correspond à un code de langue configuré, celui-ci devient la langue active pour la résolution des traductions $t:.

Les routes localisées sont donc déclarées explicitement — une page par langue, chacune portant son propre segment :

app.yaml
pages:
  - { name: home-en, path: /en, components: [{ type: hero, content: 'hero.title' }] }
  - { name: home-fr, path: /fr, components: [{ type: hero, content: 'hero.title' }] }

Le seul endroit où un préfixe est ajouté est la branche 404. Un chemin sans préfixe qui ne se résout sur aucune page, mais se résoudrait une fois préfixé, reçoit un 302 vers /{lang}{chemin} au lieu d'un 404 — voir URL sans segment de langue.

Barres obliques finales

Les chemins de pages sont écrits sans barre oblique finale (path: '/about'), et cette forme sans barre est la forme canonique : c'est elle que visent tous les liens internes, les alternatives hreflang et les entrées de sitemap émis par le moteur. Une requête qui arrive avec une barre oblique finale est normalisée vers elle par un 301, puis résolue à nouveau.

Requête Réponse
/about/ 301/about
/en/docs/ 301/en/docs — la locale d'arrivée est conservée
/docs// 301/docs — les barres répétées s'effondrent en un seul saut
/ 200 — la racine est exemptée
/en/ 200 — la racine de langue nue est exemptée
/nope/ 404, sans en-tête Location

La chaîne de requête entrante est reportée sur la cible à l'octet près : le suivi de campagne d'un lien entrant survit donc au saut.

Les deux exemptions ne sont pas cosmétiques. /en fait déjà l'objet d'un 301 vers /en/ (voir Langues) ; retirer la barre de /en/ pour revenir à /en ferait donc rebondir le navigateur indéfiniment entre les deux formes. Seule la racine de langue nue est exemptée — /en/docs/ est normalisé comme n'importe quel autre chemin.

La forme canonique doit se résoudre. Un 301 n'est émis que si le chemin sans barre finale répond réellement — directement, ou via le repli sur les chemins sans préfixe. /nope/ reste donc un 404 net plutôt que de devenir un 301 vers un 404, qui gaspille la redirection, échoue quand même et conduit un robot d'indexation dans une impasse.

Une page peut aussi être déclarée avec une barre oblique finale : path: '/docs/' est légal, et une requête vers /docs/ est alors servie sur place plutôt que normalisée. La configuration fait autorité.

Ordre de résolution

Une requête entrante est traitée par le premier élément correspondant :

  1. Un fichier réel du répertoire public.
  2. Une règle de redirection.
  3. Un chemin de page — comparé exactement, y compris une barre oblique finale écrite dans le path.
  4. La normalisation de la barre oblique finale — un 301 vers le chemin sans barre, lorsque celui-ci se résout.
  5. Le repli de langue sur les chemins sans préfixe — un 302 vers /{lang}{chemin}, lorsque celui-ci se résout.
  6. Le fourre-tout 404.

Les étapes 4 et 5 ne s'exécutent que là où l'étape 3 a décliné : toute URL qui se résout aujourd'hui continue donc de se résoudre à l'octet près. Elles se composent également : /docs/ reçoit un 301/docs, et la requête suivante reçoit un 302/en/docs.

Les deux fonctionnent uniquement en mode serveur. sovrium build n'émet aucune redirection, de sorte qu'un site hébergé statiquement répond à /about/ et /docs selon ce que son hébergeur est configuré pour faire.

Pages connexes

Dernière mise à jour 1 septembre 2026

Cette documentation a été rédigée avec de l'IA : des erreurs ou du contenu obsolète sont donc possibles. Sovrium est en bêta. Les contributions et corrections sont les bienvenues.

Construit avec Sovrium