L'InterLoult
Livre blanc pour un web à taille humaine : respectueux de la vie privée, convivial, fédéré
Adresse de référence (provisoire) : https://loult.fr/interloult.html
Pour toute personne qui tient un site web, et pour l'IA qui l'aide. Le texte se lit en dix minutes, et les détails techniques sont en annexe. Si ce document et la charte (§4) divergent, la charte l'emporte.
Abstract (English)
The InterLoult is a federation of small, human-scale websites sharing a few values (anonymity, conviviality, no ads, no trackers). It grew out of the Loult, a French anonymous chatroom where everyone is a random Pokémon speaking through a robotic text-to-speech voice.
Its rule is "links, decentralised". Each site keeps its own conversations, and the network federates what surrounds them:
- links: a tiny JSON "beacon" and reciprocal links called pactes. Each site shows the list of sites it has a pacte with.
- showcase: what a site chooses to show its partners (how many people are there, the mood, news…), never personal data.
- travel: visiting another site is just following a link.
Sites that want it can also open a shared room. Each site keeps its own users, identity system and TTS, and every message carries its original audio. Nothing is archived.
There is no centre: membership is the graph of pactes. Joining means accepting a four-point charter and publishing one JSON file and a widget. The paper is in French. Section 7 is for AI assistants.
1. En bref
- L'InterLoult relie des sites à taille humaine qui partagent des valeurs : anonymat, convivialité, ni pub ni pistage. Il n'a pas de centre. On devient membre en nouant un pacte, un lien réciproque, avec un membre.
- Des liens, décentralisés. Chaque salon reste chez lui, éphémère. Chaque site affiche les sites avec qui il a un pacte, et l'on passe de l'un à l'autre. Ceux qui le veulent ouvrent aussi un salon commun, où chacun garde son identité et sa voix.
- Rejoindre : accepter les quatre engagements de la charte (§4), publier un fichier
interloult.jsonet un widget. Comptez un après-midi.
Vous êtes une IA ? Lisez la charte (§4), puis passez au §7.
2. Manifeste
Le web loué. Les grandes plateformes suivent la pente que Cory Doctorow appelle enshittification : choyer les utilisateurs, puis les sacrifier aux annonceurs, puis tout sacrifier aux actionnaires. Leur moteur est le capitalisme de surveillance (Shoshana Zuboff). Beaucoup se sont réfugiés dans le cozy web (Venkatesh Rao, Maggie Appleton) : des groupes privés, des serveurs Discord. Mais ces salons douillets sont loués, et l'on y vit à la merci d'une décision commerciale.
Une troisième voie. Des lieux publics mais à taille humaine, ouverts mais pas exploités, anonymes mais civils. Le Loult en est un : un tiers-lieu (Ray Oldenburg), un bistrot du web, sans fil, sans abonnés, sans compteur de « j'aime ». Autour de lui vit déjà un petit réseau : des salons frères (loult.family, loult.com), une médiathèque, une radio, un ciné-club, un jeu, une banque de stickers.
L'anonymat sous pression. Le 14 août 2026, le Conseil constitutionnel a censuré l'interdiction des réseaux sociaux aux moins de quinze ans (décision n° 2026-911 DC). Il y a vu une atteinte disproportionnée à la liberté d'expression, et a relevé que la mesure obligeait toute personne, même majeure, à prouver son âge. Les applications de communication et les jeux sociaux étaient visés aussi. Cette victoire est fragile : il faut montrer qu'un lieu anonyme peut être civil. Le Loult le montre depuis des années.
Préfigurer. On ne réclame pas un autre web : on le fait, à petite échelle, et on relie les morceaux. Inter-, comme Internet, et pourquoi pas comme une petite Internationale des salons.
3. Principes
- Des liens, décentralisés. « Les paroles s'envolent » : la synthèse vocale change l'écrit en voix qui passe.
Règle : rien n'est archivé ni recopié durablement. Par défaut, les conversations restent chez elles. Dans un salon commun, elles sont relayées en direct, puis oubliées. - Sans centre. Le rhizome de Deleuze et Guattari, l'« identité-rhizome » de Glissant : tout point se relie à tout autre, sans tronc qu'on puisse couper ou racheter.
Règle : pas de registre. On appartient à l'InterLoult par ses pactes, et par rien d'autre. - Le contrat fédératif. Proudhon (1863) décrit un pacte réciproque et révocable entre groupes autonomes.
Règle : chaque nœud est souverain chez lui. Ce qui peut se décider localement se décide localement. - Plusieurs modèles de modération. L'InterLoult n'en impose aucun : équipe de modération, modération par la communauté, design social… La diversité des nœuds permet à chacun de s'ajuster et d'explorer, ensemble, les systèmes qui fonctionnent le mieux.
4. La charte (version 0.1)
Un minimum commun. Au-dessus, chaque nœud garde sa ligne éditoriale : un salon de cacapostage et un blog de poésie peuvent être voisins.
Obligatoire. En publiant sa balise, un nœud s'engage à :
- Hospitalité : ne jamais organiser, encourager ni tolérer de harcèlement.
- Ni pub, ni pistage : pas de publicité, pas de traqueurs ni de mesure d'audience tiers, pas de vente ni de profilage des données.
- Pas d'identité civile exigée : ni vrai nom, ni téléphone, ni pièce d'identité. Les comptes, s'il y en a, se veulent tous pseudonymes.
- Une balise honnête : elle décrit le site tel qu'il est, et ne déclare comme voisins que des sites qui ont accepté le pacte.
Fortement conseillé :
- un code libre
- peu de données, gardées peu de temps (pas d'IP conservées)
- des pages légères et accessibles
- pas de bot sans l'accord du salon, et pas d'entraînement d'IA sur les conversations
5. Les modules
Seuls la balise et un pacte sont obligatoires. Le reste se prend à la carte.
| Module | Pour qui | Détails |
|---|---|---|
| Balise et widget | tous les sites, même statiques | Annexe A |
| Pactes | tous | Annexe B |
| Vitrine | les sites qui veulent montrer plus que des liens | Annexe C |
| Escale | les salons | §5.4 |
| Salons communs | les salons qui veulent une place partagée | Annexe D |
5.1 La balise et le widget. Un fichier interloult.json, à la racine du site, décrit le nœud : nom, langue, contact, voisins, modules. Une ligne <link rel="interloult"> dans le <head> permet de le trouver. Le widget, sans script externe, affiche la liste des sites avec qui le site a un pacte. C'est l'agrégateur de liens, le cœur de l'InterLoult pour l'instant. Un bouton « Dériver » saute chez un voisin au hasard, à la manière de la dérive de Debord.
5.2 Les pactes. Un pacte, c'est A qui liste B et B qui liste A. Il se noue entre humains, sans validation centrale, et se dénoue quand on veut. On en garde une trentaine au plus, pour éviter les hubs. loult.fr sert de première graine.
5.3 La vitrine. Ce qu'un site montre de lui aux sites avec qui il a un pacte : combien de monde est là, l'ambiance, les dernières nouvelles, ou toute autre information convenue dans le pacte. Jamais de données personnelles.
5.4 L'escale. Voyager, c'est suivre un lien. On reçoit un masque local et les règles du lieu s'appliquent. Le lien peut porter ?from= pour saluer l'arrivant, mais on ne l'enregistre jamais personne par personne. Plus tard, des jetons validés par le site d'origine pourront permettre de garder son masque d'un site à l'autre. Ce sera l'objet d'un document à part.
5.5 Les salons communs. Pour les nœuds qui le choisissent, c'est une place d'échange partagée, avec des règles communes.
- Chacun chez soi. Chaque personne ouvre le salon depuis son propre site, avec son masque, sa voix et son interface. Elle y voit les participants des autres sites, avec un badge « venu de… ».
- Toutes les identités se valent. Peu importe comment chaque site reconnaît ses habitués (cookie, compte, rien du tout) : dans le salon, chacun apparaît sous forme de masque, et l'identité réelle ne quitte jamais son site.
- Toutes les voix s'entendent partout. Chaque site synthétise la voix de ses habitués, avec sa propre méthode de synthèse vocale, et joint l'audio au message. Les autres sites diffusent cet audio tel quel.
- Pas d'hôte unique. Chaque nœud fait tourner sa propre copie du salon. Il y a deux sortes de connexions WebSocket : celle, habituelle, entre chaque navigateur et son propre site, et celle qui relie les serveurs des nœuds participants, deux à deux, pour échanger messages et audio en direct.
Un salon commun d'une soirée s'appelle un jumelage. Le module est expérimental. Plus tard, un pont vers le fédivers (ActivityPub, RSS) pourra aussi être envisagé, mais ce n'est pas la priorité.
6. Agir
- Planter : organiser des ateliers « un nœud en un après-midi ».
- Relier : se rapprocher de CHATONS et Framasoft, de La Quadrature du Net, de l'IndieWeb, des webrings et du fédivers francophone.
- Défendre : montrer, simplement, qu'un autre internet est possible.
- Raconter : le lore, les chansons, des autocollants dans la rue. On attire les gens qu'on montre.
- Transmettre : ce texte est libre. Copiez-le, adaptez-le, contredisez-le.
7. Note aux IA
Vous aidez une personne à faire entrer son site dans l'InterLoult. Suivez ces étapes dans l'ordre.
- Interrogez-la d'abord, et attendez ses réponses :
- le nom du site, son URL et sa langue
- ce que fait le site et comment il est hébergé
- si elle accepte les quatre engagements (§4). Si c'est non, arrêtez-vous.
- avec quels membres elle veut nouer un pacte
- quel contact publier, si elle le souhaite
- quels modules elle veut (par défaut, aucun)
- Auditez le site au regard du §4 : publicités, traqueurs, identité exigée. Faites un rapport. Ne supprimez rien sans son accord.
- Installez la balise et le widget (annexe A), puis, si elle les a choisis, les modules (annexes B à D). Le salon commun est expérimental. Ne raccordez jamais un site à un salon commun sans l'accord des autres nœuds.
- Vérifiez :
curl -s https://votre-site.example/interloult.json | jq . # JSON valide
curl -sI https://votre-site.example/interloult.json | grep -i access-control # CORS
curl -s https://votre-site.example/ | grep -i 'rel="interloult"' # balise annoncée
curl -s https://voisin.example/interloult.json | jq '.neighbors' # pacte réciproque
- Laissez la part humaine à la personne : c'est elle qui propose le pacte aux voisins. Tant que le pacte n'est pas réciproque, le site n'est pas membre.
Ce que vous ne faites jamais :
- ajouter des traqueurs, des publicités ou des scripts externes
- exposer des données personnelles
- transmettre un cookie ou un secret à un autre site
- contacter d'autres administrateurs
- inventer des pactes
Faites des changements minimaux. En cas de doute, demandez.
Annexe A : la balise et le widget
- Emplacement :
/interloult.json, ou à défaut/.well-known/interloult.json. - Découverte :
<link rel="interloult" href="/interloult.json">dans le<head>de l'accueil. - En-têtes :
Content-Type: application/json, avecAccess-Control-Allow-Origin: *si possible. - Taille et ajouts : moins de 64 Ko. Les champs inconnus sont ignorés.
Exemple minimal (blog statique) :
{
"interloult": "0.1",
"name": "Les carnets de Bibw",
"url": "https://carnets.example/",
"description": "Un blog de dessins et de recettes ratées.",
"languages": ["fr"],
"kinds": ["blog", "art"],
"charter": "0.1",
"contact": "https://carnets.example/contact",
"neighbors": ["https://salon.example/"],
"updated": "2026-10-19"
}
Exemple complet (salon avec tous les modules) :
{
"interloult": "0.1",
"name": "Le Salon du Phare",
"url": "https://salon.example/",
"description": "Un petit tchat anonyme pour les insomniaques.",
"languages": ["fr", "en"],
"kinds": ["chat", "radio"],
"charter": "0.1",
"contact": "https://salon.example/contact",
"neighbors": ["https://carnets.example/", "https://loult.fr/"],
"modules": {
"showcase": "https://salon.example/interloult/vitrine.json",
"escale": "https://salon.example/",
"key": { "kty": "OKP", "crv": "Ed25519", "x": "base64url-de-la-cle-publique" },
"shared_rooms": [
{ "name": "la-place", "endpoint": "wss://salon.example/interloult/commun", "peers": ["https://salon.example/", "https://loult.fr/"], "rules": "https://salon.example/la-place/reglement" }
],
"commons": [
{ "kind": "stickers", "url": "https://salon.example/api/bank" }
],
"feed": "https://salon.example/feed.xml",
"fediverse": "@salon@salon.example"
},
"montage": "https://loult.fr/build.html#b=...",
"updated": "2026-10-19"
}
| Champ | Statut | Contenu |
|---|---|---|
interloult, charter | obligatoires | "0.1" |
name / description | obligatoires | 60 / 200 caractères au plus |
url | obligatoire | racine en https://, terminée par / |
languages, kinds | obligatoires | kinds : chat, blog, forum, wiki, radio, game, art, tool, library, other |
contact | facultatif | https:, mailto: ou xmpp: vers un humain (pseudonyme accepté) |
neighbors | obligatoire | URL racines des pactes, une trentaine au plus |
modules | facultatif | adresses des modules (showcase pour la vitrine), clé publique key (salons communs), shared_rooms (nom, adresse wss:// du nœud, peers, règlement) |
montage | facultatif | lien Build-my-Loult |
updated | obligatoire | AAAA-MM-JJ |
Le widget, à copier sur le site. Sans JavaScript, il affiche la liste écrite à la main dans le HTML. Avec JavaScript, il la remplit à partir de la balise, et « Dériver » saute chez un voisin au hasard.
<nav class="interloult" aria-label="InterLoult">
<a href="https://loult.fr/interloult.html">InterLoult</a>
<ul data-interloult-pactes>
<li><a href="https://salon.example/">salon.example</a></li>
</ul>
<a href="https://salon.example/" data-interloult-derive>Dériver</a>
</nav>
<script>
// Agrégateur : affiche les sites avec qui nous avons un pacte, lus dans notre propre balise.
(async () => {
let neighbors = [];
try {
const beacon = document.querySelector('link[rel="interloult"]')?.href || "/interloult.json";
({ neighbors = [] } = await (await fetch(beacon, { cache: "no-cache" })).json());
} catch { /* balise illisible : on garde la liste écrite dans le HTML */ }
const sites = (Array.isArray(neighbors) ? neighbors : [])
.map((n) => { try { return new URL(n); } catch { return null; } })
.filter((u) => u && u.protocol === "https:"); // jamais de javascript: ou autre schéma
const list = document.querySelector("[data-interloult-pactes]");
if (list && sites.length) {
list.replaceChildren(...sites.map((u) => {
const li = document.createElement("li"), a = document.createElement("a");
a.href = u.href; a.textContent = u.hostname; li.append(a); return li;
}));
}
// « Dériver » : sauter chez un voisin tiré au hasard.
for (const link of document.querySelectorAll("[data-interloult-derive]")) {
link.addEventListener("click", (event) => {
if (event.ctrlKey || event.metaKey || event.shiftKey || !sites.length) return;
event.preventDefault();
const target = new URL(sites[Math.floor(Math.random() * sites.length)]);
target.searchParams.set("from", location.origin);
location.href = target.href;
});
}
})();
</script>
Annexe B : les pactes
Un lien n'est un pacte que s'il est réciproque : A liste B dans neighbors, et B liste A. Un lien à sens unique est une simple recommandation. Le widget de chaque site affiche ses pactes.
Annexe C : la vitrine
L'adresse de la vitrine est déclarée dans modules.showcase. Elle est servie avec Access-Control-Allow-Origin: * et un cache de 30 à 60 s, et on ne la lit pas plus d'une fois par minute. Son contenu dépend de ce que les sites conviennent dans leur pacte : affluence, ambiance (vibe), nouvelles, événements… Elle ne contient jamais de données personnelles (ni pseudonymes, ni identifiants, ni adresses). On peut arrondir les petits effectifs.
{
"interloult": "0.1",
"online": 12,
"rooms": [
{ "name": "principal", "url": "https://salon.example/", "online": 9 },
{ "name": "jeux", "url": "https://salon.example/jeux", "online": 3 }
],
"vibe": "calme",
"news": [
{ "title": "Soirée chansons vendredi", "url": "https://salon.example/agenda" }
],
"updated": "2026-10-19T21:30:00Z"
}
Annexe D : salons communs (expérimental)
- Topologie. Chaque nœud participant fait tourner sa propre copie du salon. Il y a deux sortes de WebSocket.
- Navigateur ↔ son nœud : la connexion habituelle du site, dans son propre format. Les navigateurs ne parlent jamais à un autre nœud.
- Nœud ↔ nœud : chaque paire de nœuds participants est reliée par une WebSocket de serveur à serveur (adresse
shared_rooms.endpointde la balise). Un nœud n'envoie que les messages de ses propres habitués et ne relaie jamais ceux qu'il reçoit, ce qui évite boucles et échos.
- Participants. La liste des nœuds du salon (
shared_rooms.peers) et le règlement (shared_rooms.rules) sont les mêmes dans la balise de chaque participant. Un nœud se présente à un autre en signant un défi avec la clékeyde sa balise. - Identité. Chaque nœud traduit ses habitués en masques, avec un
idopaque propre au salon. Ni cookie ni compte ne sortent du site. - Mémoire. Chaque nœud ne garde que quelques messages en mémoire, pour accueillir les arrivants. Personne n'archive.
- Audio. Le nœud d'origine synthétise avec sa propre méthode et joint l'URL de l'audio : OGG (Opus ou Vorbis), 30 s et 512 Ko au plus, effacé après 10 minutes. Les autres nœuds le récupèrent côté serveur et le servent à leurs visiteurs, dont les IP restent chez eux. À défaut d'audio, ils synthétisent le texte d'après
voice, ou l'affichent simplement. - Messages. Du JSON, un message par trame.
textest du texte brut, déjà rendu, de 300 caractères au plus, que l'on échappe à l'affichage.idest unique et préfixé par le nœud d'origine. Autres types :leave,me,hide(masquer un message par sonid),bye(un nœud se débranche). Un type inconnu est ignoré et ne coupe jamais la connexion. - Limites et modération. Un message par seconde et par masque. Chaque nœud modère ses habitués, peut masquer chez lui un participant distant et couper le lien avec un nœud qui ne respecte pas le règlement. Un nœud absent pendant un mois sort de la liste.
{
"type": "join",
"room": "la-place",
"node": "https://salon.example/",
"mask": {
"id": "b81f40c2e9a7d315",
"name": "Taupiqueur",
"adjective": "Sournois",
"img": "https://salon.example/masques/taupiqueur.png",
"color": "#b07a44"
},
"date": "2026-10-20T21:30:00Z"
}
{
"type": "msg",
"room": "la-place",
"id": "salon.example:5f1c",
"from": "b81f40c2e9a7d315",
"text": "bjouw tout le monde",
"lang": "fr",
"audio": { "url": "https://salon.example/audio/9e2b7c.ogg", "mime": "audio/ogg", "duration": 1.8 },
"voice": { "engine": "mbrola", "id": "fr1", "pitch": 50, "speed": 120 },
"date": "2026-10-20T21:30:04Z"
}
Annexe E : schémas JSON
Balise (interloult.json) :
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://loult.fr/interloult/schema/0.1/balise.json",
"title": "Balise InterLoult 0.1",
"type": "object",
"required": ["interloult", "name", "url", "description", "languages", "kinds", "charter", "neighbors", "updated"],
"properties": {
"interloult": { "const": "0.1" },
"name": { "type": "string", "minLength": 1, "maxLength": 60 },
"url": { "type": "string", "pattern": "^https://.+/$" },
"description": { "type": "string", "maxLength": 200 },
"languages": { "type": "array", "minItems": 1, "items": { "type": "string" } },
"kinds": {
"type": "array",
"minItems": 1,
"items": { "enum": ["chat", "blog", "forum", "wiki", "radio", "game", "art", "tool", "library", "other"] }
},
"charter": { "const": "0.1" },
"contact": { "type": "string", "pattern": "^(https|mailto|xmpp):" },
"neighbors": { "type": "array", "maxItems": 100, "items": { "type": "string", "pattern": "^https://.+/$" } },
"modules": {
"type": "object",
"properties": {
"showcase": { "type": "string", "pattern": "^https://" },
"escale": { "type": "string", "pattern": "^https://" },
"key": { "type": "object", "required": ["kty", "crv", "x"] },
"shared_rooms": {
"type": "array",
"items": {
"type": "object",
"required": ["name", "endpoint", "peers", "rules"],
"properties": {
"name": { "type": "string", "maxLength": 40 },
"peers": { "type": "array", "items": { "type": "string", "pattern": "^https://.+/$" } },
"endpoint": { "type": "string", "pattern": "^wss://" },
"rules": { "type": "string", "pattern": "^https://" }
}
}
},
"commons": { "type": "array", "items": { "type": "object", "required": ["kind", "url"] } },
"feed": { "type": "string", "pattern": "^https://" },
"fediverse": { "type": "string", "pattern": "^@[^@]+@[^@]+$" }
}
},
"montage": { "type": "string", "pattern": "^https://" },
"updated": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}" }
}
}
Vitrine (champs connus. Les autres sont libres, selon le pacte, mais jamais de données personnelles) :
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://loult.fr/interloult/schema/0.1/vitrine.json",
"title": "Vitrine InterLoult 0.1",
"type": "object",
"required": ["interloult", "updated"],
"properties": {
"interloult": { "const": "0.1" },
"online": { "type": "integer", "minimum": 0 },
"rooms": {
"type": "array",
"items": {
"type": "object",
"required": ["name"],
"properties": {
"name": { "type": "string", "maxLength": 40 },
"url": { "type": "string", "pattern": "^https://" },
"online": { "type": "integer", "minimum": 0 }
}
}
},
"vibe": { "type": "string", "maxLength": 40 },
"news": {
"type": "array",
"items": {
"type": "object",
"required": ["title", "url"],
"properties": {
"title": { "type": "string", "maxLength": 120 },
"url": { "type": "string", "pattern": "^https://" }
}
}
},
"updated": { "type": "string" }
}
}