wayBetter Store

(FOSS) Une pull request vaut soumission

Publiez le vôtre.

Un thème, c’est un fichier JSON. Un plugin, c’est un fichier JavaScript. Créez-le, essayez-le dans l’app, puis ajoutez-le à la Boutique : un dossier dans une pull request, ou le fichier dans un ticket si vous n’utilisez pas git. Les deux demandent un compte gratuit sur git.crt.fyi, et rien d’autre.

1

Créez-le

Partez d’un fichier qui fonctionne. Le générateur en écrit un ; la section Créer de l’app elle-même (wayBetter → Créer) propose des exemples et les valeurs du thème en direct.

Un thème

Couleurs, polices, angles, densité, mise en page, arrière-plan, effets. Trois couleurs suffisent ; le reste en découle et le texte reste lisible.

Ou créez-le dans l’app : Apparence → Éditeur de thèmes → Exporter. THEMES.md liste tout ce qu’un thème peut définir.

Un plugin

Une classe avec start() et stop(), et un en-tête qui dit qui l’a créé et ce qu’il utilise.

Ajoutez --ts pour un projet TypeScript. PLUGINS.md décrit l’API, les autorisations et le rechargement à chaud.

hide-trends.plugin.js
/**
 * @name Hide Trends
 * @description Hides the trends box in the right column, so the timeline is the only thing moving.
 * @version 1.0.0
 * @author you
 * @permissions network:none
 */
module.exports = class HideTrends {
  start() { wayBetter.api.injectCSS('hide-trends', '[data-testid="sidebarColumn"] section { display: none }'); }
  stop()  { wayBetter.api.clearCSS('hide-trends'); }
};

La Boutique lit le nom, l’auteur, la version, la description et les autorisations d’un plugin dans cet en-tête, et le nom, l’auteur et la description d’un thème dans son JSON. L’écran d’installation affiche les mêmes valeurs : les deux ne peuvent donc jamais diverger.

2

Essayez-le

La Boutique est facultative. Un fichier qui fonctionne se partage déjà.

  • Déposez le fichier sur la fenêtre wayBetter. Vous obtenez le même écran d’installation qu’un élément de la Boutique : nom, auteur, version, SHA-256, autorisations, code.
  • Activez le mode développeur (Paramètres → Développeur) pendant que vous travaillez : un plugin, un fichier de thème ou custom.css enregistré se recharge dans tous les onglets à la fois.
  • Partagez-le sans la Boutique. Envoyez le fichier, ou un lien waybetter://install vers une URL https sur waybetter.fyi, cdn1.crt.fyi ou un fichier brut sur git.crt.fyi. Il n’est jamais installé sans l’écran d’installation.
3

Ajoutez un dossier

Chaque élément de la Boutique est un dossier sous store/<app>/ dans le dépôt. Le nom du dossier est l’identifiant de l’élément et son adresse ici : /store/plugins/<id>/.

store/x/ — les éléments de wayBetter for X
store/x/plugins/hide-trends/
  hide-trends.plugin.js   the plugin, exactly as it installs
  item.json               { "category": "focus", "tags": ["trends", "sidebar"] }
  preview.svg             optional, 640×400 (.svg or .png); drawn for you without one

store/x/themes/midnight-mint/
  theme.json              the theme, as Appearance → Export writes it
  item.json               { "version": "1.0.0" }
  preview.svg             optional; drawn from the theme without one
category
Plugins : reading, writing, filters, focus ou tools. Thèmes : dark ou light, déduit du mode du thème si vous l’omettez.
tags
Jusqu’à 12 mots que les gens chercheraient.
version
Thèmes uniquement (celle d’un plugin est dans son en-tête). Augmentez-la quand vous modifiez le fichier.
Description
Une ou deux phrases qui disent ce qu’il fait, 50 caractères ou plus. Les 160 premiers deviennent la description de sa page pour les moteurs de recherche.

Voilà toute la soumission. La page, la carte, l’entrée de recherche, l’aperçu du lien, les données structurées et l’entrée du sitemap sont générés à partir du catalogue signé lors de la construction du site. store/README.md contient toutes les règles.

4

Lancez les vérifications

Il n’y a pas de CI hébergée. Les vérifications sont des commandes que vous lancez avant d’envoyer, et qu’un mainteneur relance avant de fusionner.

dans votre clone
git submodule update --init
bun install --frozen-lockfile
bun run check:store      # your folder, against the Store's rules
bun run test             # everything else, including the site's SEO test
  • Identifiants et nomsidentifiant du dossier (a-z 0-9 -, 40 au plus), name.plugin.js, pas de doublon dans une app
  • Taillefichiers d’éléments jusqu’à 2 Mio, aperçus jusqu’à 300 Ko en 16:10
  • L’en-tête@name, @version, une description et une ligne @permissions qui indique network ou network:none
  • Des autorisations honnêtesnetwork:none est refusé quand le code appelle fetch, XMLHttpRequest, WebSocket, EventSource ou sendBeacon ; les appels à l’API protégée doivent être déclarés
  • Pas de code distantpas de eval, new Function ni import() ; pas de scripts ni de fichiers externes dans un aperçu ; pas de @import ni d’URL externes dans le CSS d’un thème
  • Le catalogueles éléments forment un catalogue que les apps acceptent (les règles du framework lui-même), et le catalogue publié correspond toujours à sa signature et à ses empreintes
  • Recherche et partagetitre de page de 60 caractères au plus, description de 50 à 160, tous deux uniques
5

Envoyez-le

Deux façons d'entrer. Les deux demandent un compte git.crt.fyi gratuit : tout le monde peut s'inscrire, et un mainteneur valide chaque nouveau compte à la main.

Pull request

  1. Forkez le dépôt sur git.crt.fyi.
  2. Ajoutez votre dossier sur une branche et lancez les vérifications.
  3. Ouvrez la pull request. Le modèle demande ce qu’il fait et ce qu’il utilise.

Pas de git ? Ouvrez un ticket

  1. Choisissez le modèle Thème ou Plugin.
  2. Joignez le fichier (et un aperçu, si vous en avez un).
  3. Un mainteneur ajoute le dossier pour vous.

Puis un mainteneur signe

La clé de signature de la Boutique est hors ligne par conception : fusionner n’est donc pas publier. Après la fusion, un mainteneur lit le code, lance waybetter store build et waybetter store sign sur la machine qui détient la clé, puis pousse. Le site est reconstruit, votre élément obtient sa page, et chaque app le voit à sa prochaine lecture du catalogue signé.

Tout ce qui figure dans le catalogue signé est garanti par cette clé ; c’est pourquoi une personne lit chaque plugin avant qu’il soit signé.

{ }

Le format du catalogue

Un seul fichier pour toutes les apps wayBetter. Vous ne le modifiez jamais à la main : il est construit à partir des dossiers.

catalog.json (format 2)Ouvert
{ "format": 2, "name": "wayBetter Store", "generatedAt": "2026-09-30T…Z", "items": [
  { "apps": ["x"], "kind": "plugin", "id": "thread-reader", "name": "Thread Reader",
    "author": "wayBetter", "version": "1.2.0", "description": "…",
    "category": "reading", "tags": ["threads"],
    "url": "https://waybetter.fyi/store/plugins/bt-thread-reader.plugin.js",
    "file": "bt-thread-reader.plugin.js", "sha256": "<64 hex>", "size": 10961,
    "preview": "https://waybetter.fyi/store/previews/plugin-thread-reader.svg",
    "permissions": ["ui", "clipboard", "commands", "network:none"] }
] }
  • Signé. catalog.json.sig est une signature Ed25519 des octets exacts de catalog.json. Les apps la vérifient avec la clé publique compilée en elles, puis contrôlent la taille et le SHA-256 de chaque téléchargement.
  • Strict. Des champs inconnus, plus de 500 éléments ou un fichier de plus de 1 Mio font refuser tout le catalogue. store-catalog.schema.json est le JSON Schema ; STORE.md, dans le framework, contient chaque règle.
  • Partagé. Chaque élément indique ses apps. Une app vérifie le fichier entier et ne garde que ses propres éléments.
Aa

Langues

Ce ne sont pas des éléments de la Boutique : les 51 langues sont intégrées à l’app et chargées à la demande.

  • Corrigez ou terminez une traduction dans apps/desktop/locales/<tag>.json, par pull request ou par un ticket avec le fichier modifié en pièce jointe.
  • Vérifiez-la avec bun run i18n:check : clés, espaces réservés, formes du pluriel, pas de balisage. La commande doit afficher 0 error(s).
  • Elle arrive avec la prochaine mise à jour de l’app, pas par la Boutique. TRANSLATING.md décrit la syntaxe des messages et la façon de voir vos mots dans l’app.

Voyez ce qui est déjà là.

Chaque élément de la Boutique montre son code. Les plugins fournis sont les meilleurs exemples d’une bonne utilisation de l’API.