A manifest is one JSON object. name and fields are required; everything else has a sensible default.
socket.json
1234567891011121314{ "$schema": "https://slash.tools/socket/v1.json", "name": "launch-party", "title": "Launch party", "description": "Live reactions and a guestbook for launch day.", "origins": ["https://example.com", "http://localhost:3000"], "auth": { "anonymous": true, "tokens": true }, "limits": { "connections": 5000, "connectionsPerMinute": 30 }, "fields": { "here": { "type": "presence" }, "reactions": { "type": "map", "shape": { "emoji": "enum(🎉|🔥|❤️)" } }, "guestbook": { "type": "list", "write": "signed-in", "shape": { "message": "string(280)" }, "keep": 500 } }}PropTypeDescription
namestring, requiredThe socket's id: 1–40 lowercase letters, digits and hyphens. Data is kept per name, so renaming starts a new socket.titlestringA display name, up to 80 characters.descriptionstringUp to 500 characters.originsstring[]Page origins allowed to connect, like https://example.com (scheme and host, no path). Leave it out to allow any page. Browsers always send their origin; scripts can set any, so this guards against other sites, not determined clients.auth.anonymousbooleanLet pages in without a token. Default true.auth.tokensbooleanAccept visitor tokens signed by your backend, so those visitors count as signed in. Default false. See Access & Tokens.limits.connectionsintegerOpen connections at once; 0 for no cap. Defaults to the server's setting (the app's Max Connections).limits.connectionsPerMinuteintegerNew connections per IP per minute. Defaults to the server's setting (60).fieldsobject, required1–32 fields, keyed by name: a letter, then letters, digits and _ (up to 40). See Field Types.Start a manifest with "$schema": "https://slash.tools/socket/v1.json" and editors like VS Code autocomplete and check it as you type. The dashboard, the app and the server each validate it again before using it, and list every problem at once rather than the first.
Changing a manifest is safe. Fields that keep their name and type keep their data (a list is trimmed to a smaller keep, a counter clamped to new bounds); new fields start empty; removed fields are dropped. Every page reconnects to pick up the change — the client does that on its own.