Complete schema for manifest.json — metadata, permissions, and the Chalk element definition
Every plugin must include a manifest.json at its root. The manifest serves two purposes: it describes the plugin to the internote runtime (version, permissions) and it declares the Chalk element schema the parser uses to validate any internote that uses your plugin.
id (string; required). Unique identifier for the plugin. Lowercase, hyphens only. Must match the last path segment of the registry URL — e.g., particle-sim in plugins.internote.dev/particle-sim.name (string; required). Human-readable display name shown in the marketplace.version (string; required). Semantic version string, e.g. 1.0.0.author (string; required). Your email address or display name.description (string; required). One sentence describing what the plugin does.preview (string; optional). Filename of a preview image (PNG or GIF, max 2 MB) at the plugin root. Shown in the marketplace listing.permissions (string[]; required). Capabilities beyond basic rendering your plugin uses. See Permissions below.chalk (object; required). The Chalk element schema — the element name and the attributes educators use in Chalk.Declare each capability your plugin uses. Omitting a permission you use causes the plugin to be rejected during review.
"storage" — plugin calls internote.storage.*"network" — plugin makes fetch or WebSocket requests to external URLsThe element name educators use in Chalk files. Must be lowercase with hyphens allowed and no spaces. Must match the id field.
A map of attribute names to their definitions. Each entry becomes a named attribute on the Chalk element. The Chalk parser validates attribute values against this schema when loading the file.
Attribute definition fields:
type (string; required). One of: string, number, boolean, dimensions, colour.label (string; optional). Display name for the settings panel UI in the editor.description (string; optional). Tooltip or supplementary documentation shown in the editor.default (any; optional). Value used when the attribute is omitted in Chalk.required (boolean; default: false). If true, the Chalk parser reports an error when this attribute is missing.min (number; optional). Minimum valid value. Only applies to number type.max (number; optional). Maximum valid value. Only applies to number type.Attribute types map to Chalk value syntax as follows:
string → bare value or quoted: label: Click menumber → numeric literal or parameter variable: gravity: 2.5 or gravity: gboolean → true or false: loop: truedimensions → tuple: size: (600, 400)colour → colour name: colour: tealDeclares the child element types that can appear inside the plugin's body {} or detail [] blocks. Each key is an element name; the value defines its attributes and which blocks it is allowed in.
Child element definition fields:
attributes (object; optional). Attribute schema for the child element — same structure as chalk.attributes.allowedIn (string[]; required). Which blocks accept this element: "body", "detail", or both.Other plugins can also be allowed as child elements by referencing their registry URL as the key:
The Chalk parser validates child elements against this schema. Children that are other plugins are fetched and validated against their own manifests in turn.
When the Chalk parser encounters @plugin(src: ...) it fetches the manifest, reads chalk.element to register the element name, and uses chalk.attributes to validate every subsequent use of that element in the file. Errors are shown inline in the editor.
The runtime also validates attrs at render time when the internote is viewed by a student. An element with a missing required attribute or an out-of-range value renders as an error state rather than crashing the internote.