The manifest
A plugin's manifest is the phantom field in its package.json. The app, phantom-plugin validate and the store all use the same checker.
{
"name": "phantom-plugin-room-watch",
"version": "1.0.0",
"phantom": {
"id": "you.room-watch",
"title": "Room watch",
"description": "Says who comes and goes in your room.",
"author": "You",
"runs": "each-game",
"permissions": {
"game": "read",
"notifications": true,
"optional": ["notifications"]
},
"config": {
"buddiesOnly": {
"type": "boolean",
"name": "Only buddies",
"scope": "player",
"default": false
}
},
"contributes": {
"panels": [{ "id": "log", "title": "Room watch", "icon": "users" }]
}
}
}Fields
| Field | What it is | |
|---|---|---|
id | required | The plugin's id, like you.name. Lower case, dots allowed. It stays the same across versions. |
title | required | The name shown in Plugins and the store. |
description | required | One or two sentences, up to 280 characters. |
author | required | Who made it. Shown under the name. |
icon | A PNG or SVG inside the package, shown in Plugins. | |
changelog | What changed in this version, up to 2000 characters of Markdown. See changelog. | |
api | The plugin API versions it works with, as a semver range. Defaults to ^0.2.0. | |
minPhantom | The oldest Phantom release it runs on, such as "1.5.0". phantom-plugin pack fills it in from what your bundle uses, so you only write one to ask for a later release. An older Phantom refuses to install or run it and says "Needs Phantom 1.5 or newer". | |
runs | each-game (the default) runs a copy of the logic for each game it's allowed on. single runs one copy that sees all those games and picks. | |
maxGames | The most games it can run on at once, 1 to 8. Useful for a plugin that should only ever play one account. | |
requires | What the game must have reached before setup runs. See requires. | |
clientDeploys | The game client builds it was made for, by deploy number ("1829"). If set, Phantom warns on other builds. Matters most for plugins that use flash. | |
servers | The game servers it is made for: "animal-jam", "private" (Phantom's private server), or both. ["private"] makes a plugin for the private server alone, and ["private", "animal-jam"] one free on the private server; free accounts can run either there. See servers. | |
permissions | What it needs. See Permissions. | |
config | The settings: an object of items keyed by the name your code reads them by. They reach the plugin typed, as ctx.config. See Settings. | |
preferences | The same settings written as form fields. config and preferences together hold up to 40. Phantom stores them, draws the form and tells you when one changes. See Preferences. | |
contributes | What it adds: pages, panels, widgets, commands and themes. |
changelog
What changed in this version, in your words. Phantom shows it under the plugin in Updates before the player updates, on your plugin's store page beside every version, and on the plugin once it's installed.
"version": "1.2.0",
"phantom": {
"changelog": "- Watches den doors as well as room doors.\n- Stops counting the same player twice.\n- Fixed the log emptying when the game reconnects."
}It belongs to the version, not the plugin, so write a new one for every release. A version published without one is shown as having no notes. It's Markdown, rendered like a README, and meant for a short list. Raw HTML in it is never rendered.
Published versions are never rewritten, so a version keeps the notes it was published with.
servers
Which game servers the plugin is made for. Leave it out and it runs on both Animal Jam's own servers and Phantom's private server.
"phantom": {
"servers": ["private"]
}| Value | Where it runs |
|---|---|
| left out | Every game: Animal Jam and the private server. A plan is needed. |
["private"] | Private server games only. Free for players, with or without a plan. |
["private", "animal-jam"] | Every game. Free on the private server; a plan for Animal Jam. |
["animal-jam"] | Animal Jam games only, never the private server. A plan is needed. |
Phantom, not your code, keeps a ["private"] plugin on the private server, for every account. It never runs in an Animal Jam game, its frames are never given one, and anything it asks of a game not on the private server is refused with GAME_NOT_ALLOWED, like a game the player didn't pick. Players without a Phantom plan can install, set up and run it; every other plugin needs a plan.
["private", "animal-jam"] is for a plugin that works on Animal Jam too. Players without a plan can install and run it, and Phantom keeps it on the private server for them exactly like a ["private"] plugin: no Animal Jam games, and none of Animal Jam's web addresses. With a plan it runs on both, and it's let into or taken out of Animal Jam games as soon as a plan starts or ends. Leaving servers out never makes a plugin free.
The store tags both kinds Private server, and players can filter by that tag. Each name may appear once, and the list can't be empty. See Plugins for the private server.
permissions
"permissions": {
"game": "act",
"packets": "read",
"realtime": false,
"network": ["api.example.com"],
"clipboard": false,
"notifications": true,
"microphone": false,
"optional": ["game:act", "notifications"]
}game is read to see the game and draw over it, or act to also act as the player. packets is read to hear the game's traffic, or send to also send and change it. realtime talks to copies of the plugin on other computers and needs game as well. Any field can be left out, and isn't asked for. optional lists scopes the plugin can run without, such as game:act or notifications; each must also be asked for above. microphone hears the player's microphone (never the camera). It's always optional without being listed there, and starts off until the player turns it on (The microphone). Permissions has every scope as the player sees it.
contributes
| Kind | Up to | Fields |
|---|---|---|
pages | 10 | id, title, icon, description |
panels | 10 | id, title, icon, description |
widgets | 6 | id, title, icon, description, size and minSize ({ "w", "h" } on the canvas's grid) |
commands | 40 | id, title, description, icon, keywords (up to 10), arguments (form fields, up to 10), view (whether it opens a component) |
themes | 40 | id, title, description, mode (light or dark), colors (twenty #rrggbb colours; see Themes) |
Icons are Lucide names, such as users or swords.
A widget is a tile on the canvas. size is its starting size, in columns of the canvas's 24 and rows of 40 pixels, up to 12 by 8; the player resizes it from there. minSize is the smallest they can drag it, and can't be bigger than size. Leave either out and Phantom picks one. See Widgets.
Themes are only data. A plugin that only adds themes doesn't need src/index.ts, dist/plugin.js or any permissions, and Phantom gives it no frames. Any other plugin has code, even one that adds nothing and only runs in the background.
requires
What the game must have reached before your setup runs. Phantom waits, shows the player what your plugin is waiting for, then runs setup.
"phantom": {
"requires": ["game", "hud"],
"permissions": { "game": "read" }
}The names are game, room, language, hud, interface and shops. Phantom reads each from the game, so your manifest has to ask for "game": "read" (or act), or it's refused. room is the exception, since Phantom already knows which room each game is in.
definePlugin({ requires }) adds to this rather than replacing it. Only an each-game plugin can be held back, so a single plugin that declares requires is refused; it waits with ctx.ready instead. See Waiting for the game.