Skip to main content
Voir en Markdown

Robots d'indexation, sitemaps et flux

Un moteur de recherche, un lecteur de flux et un assistant d'IA lisent chacun une application au travers d'un petit ensemble de fichiers bien connus. Sovrium les dérive tous de la configuration que vous avez déjà écrite : rien à générer à la main, rien à garder synchronisé.

Adresse Servi quand Contenu
/sitemap.xml Toujours Un <url> par page indexable et par enregistrement public, ou un index au-delà de 5 000
/robots.txt Toujours Une politique d'exploration et l'adresse absolue du sitemap
/feed.xml Une page de collection publique déclare rss Un flux RSS 2.0 des enregistrements les plus récents de cette collection
<article>.md Chaque article d'un répertoire de contenu Le Markdown de l'article, sans son frontmatter
/llms.txt, /llms-full.txt L'application a une page de répertoire de contenu Un index et une concaténation pour les assistants d'IA — voir Publier llms.txt

Définir BASE_URL d'abord

Chaque URL de ces fichiers est absolue, et un robot fait confiance à l'origine qu'on lui donne. Sovrium prend cette origine dans la variable d'environnement BASE_URL ; sans elle, il se rabat sur l'hôte par lequel la requête est arrivée, qui derrière un reverse proxy peut être une adresse que personne ne peut atteindre depuis l'extérieur.

La même variable décide si une page publie des alternatives hreflang tout court. Une page dotée d'un canonical absolu prend son origine dans cette URL ; sinon, BASE_URL la fournit (SOVRIUM_BASE_URL pendant sovrium build) ; et sans l'un ni l'autre, la page n'émet aucune alternative, car les moteurs de recherche rejettent les alternatives relatives. Une application multilingue démarrée sans BASE_URL affiche un avertissement au démarrage qui le signale — définissez-la.

/sitemap.xml

Une page est listée lorsqu'elle est lisible anonymement, n'est pas noindex, n'est pas exclue par sitemap: false et ne se trouve pas sous un chemin commençant par /_. Une page de répertoire de contenu se déploie en une entrée par fichier Markdown, et une application multilingue liste chaque page une fois par langue, avec des alternatives hreflang et un x-default pointant vers la langue par défaut.

app.yaml
name: my-site
pages:
  - name: Home
    path: /
    sitemap: { priority: 1.0, changefreq: weekly }
    components:
      - { type: text, element: h1, content: 'Home' }
  - name: Thank you
    path: /thanks
    sitemap: false
    components:
      - { type: text, element: h1, content: 'Thanks for signing up' }

priority et changefreq sont des indications que Google ignore. Elles sont conservées parce que d'autres moteurs les lisent encore, mais elles ne changent ni la fréquence à laquelle Google explore une page ni son classement. Ce que Google utilise, c'est lastmod — et uniquement pour un site dont il a constaté que les dates sont exactes — si bien que Sovrium n'en écrit un que lorsqu'il le connaît : un article de répertoire de contenu porte la date de modification de son fichier Markdown, sous forme d'horodatage ISO 8601 complet tel que 2026-03-14T09:26:53Z. Une page déclarée dans la configuration n'a aucune date que le moteur pourrait connaître : son entrée ne porte donc aucun lastmod plutôt qu'un faux.

Une page de collection telle que /blog/:slug se déploie en une entrée par enregistrement, au slug résolu de l'enregistrement — mais seulement lorsqu'un visiteur anonyme pourrait lire l'enregistrement : sa table doit déclarer permissions: { read: all } et aucune règle de lecture au niveau des lignes, le champ à partir duquel l'adresse est construite doit lui aussi être lisible par tous (une entrée permissions.fields qui le restreint exclut tous les enregistrements), les enregistrements supprimés sont écartés, et le collection.filter propre à la page s'applique. Les enregistrements sont lus par pages de 5 001 lignes, dix pages au plus par collection. Le lastmod d'un enregistrement est son champ updated-at, lorsque la table en possède un. Une collection portant sur une table qui exige une session ne contribue rien, car un robot recevrait une réponse 404. Un sovrium build liste les mêmes enregistrements, lus dans la base de données vers laquelle il pointe — voir plus bas.

Le sitemap est mis en cache 60 secondes. Chaque réponse /sitemap.xml et /sitemap-N.xml est calculée une fois puis servie inchangée pendant une minute : un enregistrement ajouté ou supprimé apparaît donc au plus une minute plus tard ; redémarrer ou recharger l'application repart d'un cache neuf.

Au-delà de 5 000 URL, /sitemap.xml devient un <sitemapindex> qui nomme /sitemap-1.xml, /sitemap-2.xml et ainsi de suite par adresse absolue, chacun contenant au plus 5 000 entrées. Le protocole en autorise 50 000 ; le découpage plus bas garde chaque réponse légère.

/robots.txt

code
User-agent: *
Allow: /
Disallow: /_preview
Sitemap: https://example.com/sitemap.xml

Chaque robot est autorisé partout, avec une ligne Disallow par page dont le chemin commence par /_, suivie de l'adresse absolue du sitemap.

Une page noindex n'est volontairement pas en Disallow. Une page refusée dans robots.txt n'est jamais récupérée : un robot ne verrait donc jamais sa balise noindex — et une URL qu'il connaît déjà par un lien pourrait rester dans l'index, affichée sans description. Laisser la page explorable est ce qui permet à la balise de prendre effet : marquer une page noindex suffit donc à la tenir hors des résultats de recherche.

Sovrium n'a pas de politique par robot. Le fichier nomme un seul user agent, *, et aucune option ne permet d'en écrire un autre. Cela compte pour les robots d'IA, qui s'identifient par leurs propres jetons et se répartissent en deux catégories : les robots qui récupèrent une page pour répondre à une question en temps réel (OAI-SearchBot, Claude-SearchBot, PerplexityBot) et les robots qui collectent du texte pour entraîner un modèle (GPTBot, ClaudeBot, CCBot, Bytespider, plus les jetons Google-Extended et Applebot-Extended, qui contrôlent l'usage pour l'entraînement sans robot distinct). Tous lisent aujourd'hui User-agent: * : une application Sovrium les autorise donc tous. Une demande de politique particulière n'est de toute façon pas respectée par tous les robots : robots.txt est une requête, pas un contrôle d'accès.

/feed.xml

Une page de collection qui déclare rss publie ses enregistrements les plus récents sous forme de flux RSS 2.0 — rss: true pour les vingt éléments par défaut, ou rss: { limit: 25 }. La route répond 404 lorsqu'aucune page ne s'y inscrit. La page à partir de laquelle le flux est construit l'annonce dans son en-tête avec <link rel="alternate" type="application/rss+xml">, intitulé comme le canal du flux : un lecteur de flux à qui l'on donne l'adresse de la page découvre ainsi le flux de lui-même. Les autres pages n'annoncent rien.

Seule une page que tout le monde peut ouvrir peut publier le flux : une page dont l'access exige une connexion ou un rôle ne le construit jamais, même pour un lecteur connecté, car /feed.xml est un unique document mis en cache publiquement pour tous les lecteurs. Lorsqu'une page publique déclare aussi rss, le flux est construit à partir de la première ; lorsqu'aucune ne le fait, la route répond 404, jamais 403, afin de ne pas révéler l'existence d'un flux restreint.

Jumeaux Markdown

Chaque article d'un répertoire de contenu est aussi servi en Markdown : ajoutez .md à son adresse, ou demandez l'article lui-même avec Accept: text/markdown. Le corps est le fichier sans son frontmatter, et un article que le visiteur n'a pas le droit de lire répond 404 sous les deux formes. Le Markdown d'un article public peut être mis en cache par un cache partagé pendant cinq minutes ; le Markdown d'un article dont la page est restreinte par access porte la même politique private, no-cache que son HTML, de sorte qu'aucun cache partagé ne puisse stocker la copie d'un lecteur et la servir à un autre. Comme une même URL répond deux corps, le HTML comme le Markdown négocié portent Vary: Accept, afin qu'un cache ou un CDN placé devant l'application les distingue. Un article sur une page noindex répond avec X-Robots-Tag: noindex sous ses deux formes Markdown, puisqu'un corps Markdown n'a nulle part où porter la balise meta — un hébergeur statique ne peut pas envoyer cet en-tête : gardez donc une collection retenue hors d'un build statique.

Ces jumeaux existent pour les assistants d'IA et pour les lecteurs qui veulent la source. Ce ne sont pas un signal de recherche — Google a indiqué ne pas avoir besoin de fichiers Markdown ni de llms.txt pour indexer un site — mais chaque article annonce son propre jumeau dans son en-tête avec <link rel="alternate" type="text/markdown">, afin qu'un agent lisant le HTML trouve le Markdown sans deviner l'adresse.

Ce qu'écrit sovrium build

Un build statique rend chaque page publique en HTML et, sur demande, les fichiers qui l'entourent :

Fichier Écrit quand
sitemap.xml SOVRIUM_GENERATE_SITEMAP=true
sitemap-1.xml, … Le sitemap dépasse 5 000 adresses
blog/<slug>.html, … Un enregistrement que le sitemap liste
robots.txt SOVRIUM_GENERATE_ROBOTS=true
llms.txt, llms-full.txt L'application les servirait
<article>.md Chaque article public d'un répertoire de contenu

Le build prend son origine dans SOVRIUM_BASE_URL, pas dans BASE_URL. Le jumeau .md de chaque article est écrit à côté de son HTML, à l'adresse à laquelle répond le serveur : un hébergeur statique sert ainsi /docs/getting-started.md comme le fait le serveur. Il n'écrit pas feed.xml, qui n'existe que sur un serveur en cours d'exécution.

Avec le sitemap activé, le build lit les enregistrements de chaque page de collection dans la base de données contre laquelle il s'exécute — DATABASE_URL, comme pour sovrium start — selon les mêmes règles que le sitemap servi décrit plus haut : une table que tout le monde peut lire, aucune règle de lecture au niveau des lignes, un champ d'adresse lisible par tous, les enregistrements supprimés écartés, les mêmes pages de 5 001 lignes et le même plafond. Il les lit une fois et utilise cette lecture deux fois : chaque enregistrement obtient un <url> dans sitemap.xml, et la page de chaque enregistrement est rendue et écrite, à l'adresse où elle est listée (/blog/pricing-change devient blog/pricing-change.html). Chaque adresse annoncée par le sitemap construit est donc un fichier auquel un hébergeur statique peut répondre, et pour les mêmes enregistrements, le sitemap.xml construit est le document que sert le serveur en cours d'exécution, lastmod compris. Au-delà de 5 000 adresses, le build écrit l'index et ses enfants sitemap-N.xml à côté. Les pages d'enregistrement sont écrites telles que rendues, sans la mise en forme des espaces appliquée aux pages déclarées, car une table de milliers de lignes passerait sinon des minutes à les réindenter. Une collection dont la route porte plus d'un paramètre, en dehors de :lang, ne liste aucun enregistrement et n'écrit aucune page d'enregistrement. Sans le sitemap, le build ne lit aucun enregistrement et n'écrit aucune page d'enregistrement.

Pages connexes

Dernière mise à jour 27 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