Publishing & sharing your mod
There's no central mod store (yet). Sharing a TSPML mod today means hosting files somewhere public and sharing a link, which the portal's URL import turns into a one-click install, and the portal's share links turn into a whole-setup install.
The URL-import layout
Host your mod's files together, anywhere static:
my-mod/
mod.json # the manifest
entrypoint.js # the BUILT entrypoint (mod.json's "entrypoint" points here)
mixins.json # only if declared in mod.json's "mixins"The importer fetches mod.json, then resolves entrypoint (and each mixin config) relative to the manifest's URL. So one link, to mod.json, is the whole install instruction.
Hosting that works
The fetch happens directly from the player's browser, so the host must send CORS headers:
| Host | Works? |
|---|---|
raw.githubusercontent.com (a file in a public repo) | yes, the recommended default |
| GitHub Pages | yes |
| Most static hosts (Netlify, Vercel, Cloudflare Pages) | yes |
| A URL shortener or an HTML page ABOUT the file | no, the URL must serve the raw file |
A single-file mod is even simpler: share a link to the bare .js file and the importer synthesizes a manifest around it.
Updates reach players through the reload button
When you push a new build to the same URL, players don't have to re-import: the portal's reload button re-fetches every URL-imported mod from its source. The re-fetch bypasses the browser's HTTP cache; note that GitHub's raw CDN adds its own cache of about five minutes that can't be bypassed from the browser, so rapid iteration is smoother on hosts without that cache.
Share links: shipping a whole setup
Players can bundle your mod (and others) into a share link with the portal's share button: a portal URL carrying one mods= parameter per enabled URL-imported mod, capped at 16.
What this means for you as a publisher:
- The link carries URLs only, never code. Your hosting stays the distribution channel; the link is just pointers.
- Only URL-imported mods can ride a link. If you want your mod to be shareable, publish it at a URL rather than distributing files to paste.
- Recipients always see a confirmation list first. A share link never auto-installs; the recipient sees each mod URL and confirms before anything is fetched. Your mod's URL is its identity in that list, so a clear repo/path name helps people trust what they're importing.
A publishing checklist
idis your namespace: lowercase[a-z0-9-], globally unique, stable across versions. Prefix your keybind ids and any globals with it.versionis semver: bump it on every release.targetsstates the game versions you tested, e.g.[">=0.6.0 <0.7.0"]. When PolyTrack ships a version outside your range, your mod is soft-disabled with a clear report instead of breaking mysteriously. That's a feature; keep the range honest.- Ship the built JS, not TypeScript. The manifest's
entrypointmust point at a real fetchable file. - Return a disposer and undo everything you set up. Players toggle mods, and a mod that leaks listeners on disable feels broken.
- Set
vanillaSafehonestly:falseif your mod touches physics or timing. It's a warn-only label, but it's the difference between an informed player and a banned one. - A README helps: what the mod does, its keybinds, and its
mod.jsonURL for importing. - Remember the source button. Players can inspect your mod's exact fetched contents in the portal before and after trusting it. Readable built output is a courtesy that pays off.
Versioning and dependencies
mod.json supports relations between mods (depends, recommends, suggests, conflicts, breaks, provides) with npm semver ranges. The loader topologically sorts the load order and soft-disables what can't be satisfied. Details: mod.json manifest.
What's coming
A mod/modpack registry is on the roadmap (#80): short IDs that resolve to mod URLs, and modpacks, a saved list of mod links installable as a unit. The registry will store links only, never mod code; hosting stays wherever you publish. Share links are the first slice of this design, and the portal's Add-form already has the "mod/modpack ID" slot reserved.