Publishing - SocketSVC Docs
SocketSVC Docs

Publishing

Getting an addon to players through GitHub releases, and why not Modrinth

Addons go to GitHub releases. Not Modrinth: that project page is the core mod — client, server and proxy — and a page carrying a dozen optional extras makes the thing somebody came to install harder to find.

That is enforced, not remembered: scripts/modrinth_release.py refuses outright to upload anything named socketsvc-addon-*.

Declaring what a release carries

A release becomes index entries by carrying an addons.json asset beside the jars:

addons.json
{
  "addons": [
    {
      "id": "cinema",
      "name": "Cinema",
      "version": "1.2.0",
      "kind": "mod",
      "description": "Screens that play a stream",
      "file": "socketsvc-addon-cinema-1.2.0+mc1.21.11.jar",
      "minecraft": "1.21.11",
      "loader": "fabric",
      "side": "client"
    }
  ]
}
FieldMeaning
id[a-z0-9][a-z0-9_-]{0,63} — a folder name and a config key as well as a name
kindaddon to hot-load, mod for an ordinary loader mod
filethe asset in this release carrying the jar
minecraft / loaderomit for something that fits every game, which a pure addon usually does
sideclient (the default) or server; the client manager only offers client ones

The release also needs the checksums.txt that scripts/publish_manifest.py already writes. An entry whose jar has no checksum is dropped from the index rather than served — the client refuses anything it cannot verify, so serving it would only produce an install button that cannot work. The same goes for an entry naming a jar the release does not carry.

What the index does with it

The update service reads every release, keeps the newest version of each id, and serves them at /v1/addons and /addons.json. A malformed entry is skipped and named; one bad row costs that addon and nothing else.

Players point at an index with addonIndexEndpoint, which defaults to SocketSVC's own service — the same place, and the same decision, as the updater.

Every entry's url is the service's own /v1/download/<tag>/<asset> route, which redirects to GitHub for a public repository and streams the bytes for a private one.

That keeps the client's rule intact: an index may only serve from its own host. Combined with a server being able to name only an id, there is no path by which a server chooses where a player's game fetches code from.

The checksum is what makes the redirect safe

The host check governs what an index may declare, not where bytes finally come from — a redirect can go anywhere. The mandatory sha256, checked before a single class is loaded, is the guard that actually holds.