wayBetter Store

(FOSS) Una pull request è una candidatura

Pubblica il tuo.

Un tema è un file JSON. Un plugin è un file JavaScript. Crealo, provalo nell’app, poi aggiungilo allo Store: una cartella in una pull request, oppure il file in una issue se non usi git. Entrambe le strade richiedono un account git.crt.fyi gratuito, e nient’altro.

1

Crealo

Parti da un file che funziona. Lo scaffolder ne scrive uno; la sezione Crea dell’app (wayBetter → Crea) ha esempi e i valori del tema in tempo reale.

Un tema

Colori, font, angoli, densità, layout, sfondo, effetti. Tre colori bastano; il resto viene derivato e il testo resta leggibile.

Oppure costruiscilo nell’app: Aspetto → Creatore di temi → Esporta. THEMES.md elenca tutto ciò che un tema può impostare.

Un plugin

Una classe con start() e stop(), e un’intestazione che dice chi l’ha fatto e cosa usa.

Aggiungi --ts per un progetto TypeScript. PLUGINS.md contiene l’API, i permessi e il ricaricamento in tempo reale.

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'); }
};

Lo Store legge nome, autore, versione, descrizione e permessi di un plugin da questa intestazione, e nome, autore e descrizione di un tema dal suo JSON. La schermata di installazione mostra gli stessi valori, così i due non possono mai divergere.

2

Provalo

Lo Store è facoltativo. Un file che funziona è già condivisibile.

  • Trascina il file sulla finestra di wayBetter. Ottieni la stessa schermata di installazione di un elemento dello Store: nome, autore, versione, SHA-256, permessi, codice.
  • Attiva la modalità sviluppatore (Impostazioni → Sviluppatori) mentre lavori: un plugin, un file di tema o custom.css appena salvato si ricarica in tutte le schede contemporaneamente.
  • Condividilo senza lo Store. Invia il file, oppure un link waybetter://install a un URL https su waybetter.fyi, cdn1.crt.fyi o a un file raw su git.crt.fyi. Non viene mai installato senza la schermata di installazione.
3

Aggiungi una cartella

Ogni elemento dello Store è una cartella sotto store/<app>/ nel repository. Il nome della cartella è l’id dell’elemento e il suo indirizzo qui: /store/plugins/<id>/.

store/x/ — gli elementi di 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
Plugin: reading, writing, filters, focus o tools. Temi: dark o light, ricavato dal mode del tema quando lo ometti.
tags
Fino a 12 parole che le persone cercherebbero.
version
Solo per i temi (quella di un plugin è nella sua intestazione). Aumentala quando modifichi il file.
Descrizione
Una o due frasi che dicono cosa fa, di almeno 50 caratteri. I primi 160 diventano la descrizione della sua pagina nei motori di ricerca.

La candidatura è tutta qui. La pagina, la scheda, la voce di ricerca, l’anteprima del link, i dati strutturati e la voce nella sitemap vengono generati dal catalogo firmato quando il sito viene compilato. store/README.md contiene tutte le regole.

4

Esegui i controlli

Non c’è una CI ospitata. I controlli sono comandi che esegui prima di inviare, e che un maintainer esegue di nuovo prima del merge.

nel tuo 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
  • Id e nomiid della cartella (a-z 0-9 -, fino a 40), name.plugin.js, nessun duplicato in un’app
  • Dimensionefile degli elementi fino a 2 MiB, anteprime fino a 300 KB in 16:10
  • L’intestazione@name, @version, una descrizione e una riga @permissions che indica network o network:none
  • Permessi onestinetwork:none viene rifiutato quando il codice chiama fetch, XMLHttpRequest, WebSocket, EventSource o sendBeacon; le chiamate alle API protette vanno dichiarate
  • Nessun codice remotoniente eval, new Function o import(); niente script o file esterni in un’anteprima; niente @import o URL esterni nel CSS di un tema
  • Il catalogogli elementi vengono compilati in un catalogo che le app accettano (le regole del framework stesso), e il catalogo pubblicato corrisponde ancora alla sua firma e ai suoi hash
  • Ricerca e condivisionetitolo della pagina fino a 60 caratteri, descrizione da 50 a 160, entrambi univoci
5

Invialo

Due modi per entrare. Entrambi richiedono un account git.crt.fyi gratuito: chiunque può registrarsi, e un maintainer approva a mano ogni nuovo account.

Pull request

  1. Fai un fork del repository su git.crt.fyi.
  2. Aggiungi la tua cartella in un branch ed esegui i controlli.
  3. Apri la pull request. Il modello chiede cosa fa e cosa usa.

Niente git? Apri una issue

  1. Scegli il modello Tema o Plugin.
  2. Allega il file (e un’anteprima, se ce l’hai).
  3. Un maintainer aggiunge la cartella per te.

Poi un maintainer firma

La chiave di firma dello Store è offline per scelta, quindi fare il merge non significa pubblicare. Dopo il merge un maintainer legge il codice, esegue waybetter store build e waybetter store sign sul computer che custodisce la chiave, e fa il push. Il sito viene ricompilato, il tuo elemento ottiene la sua pagina, e ogni app lo vede alla successiva lettura del catalogo firmato.

Tutto ciò che sta nel catalogo firmato è garantito da quella chiave, ed è per questo che una persona legge ogni plugin prima che venga firmato.

{ }

Il formato del catalogo

Un solo file per tutte le app wayBetter. Non lo modifichi mai a mano: viene generato dalle cartelle.

catalog.json (formato 2)Aperto
{ "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"] }
] }
  • Firmato. catalog.json.sig è una firma Ed25519 sui byte esatti di catalog.json. Le app la verificano con la chiave pubblica compilata al loro interno, poi controllano dimensione e SHA-256 di ogni download.
  • Rigoroso. Campi sconosciuti, più di 500 elementi o un file oltre 1 MiB fanno rifiutare l’intero catalogo. store-catalog.schema.json è lo JSON Schema; STORE.md nel framework contiene ogni regola.
  • Condiviso. Ogni elemento indica il proprio apps. Un’app verifica l’intero file e tiene solo i propri elementi.
Aa

Lingue

Non sono elementi dello Store: tutte le 51 lingue sono integrate nell’app e caricate su richiesta.

  • Correggi o completa una traduzione in apps/desktop/locales/<tag>.json, con una pull request o con una issue a cui alleghi il file modificato.
  • Controllala con bun run i18n:check: chiavi, segnaposto, forme plurali, nessun markup. Deve stampare 0 error(s).
  • Arriva con il prossimo aggiornamento dell’app, non tramite lo Store. TRANSLATING.md spiega la sintassi dei messaggi e come vedere le tue parole nell’app.

Guarda cosa c’è già.

Ogni elemento dello Store mostra il proprio codice. I plugin inclusi sono i migliori esempi di come usare bene l’API.