Skip to main content
This page is the get_authoring_guide tool rendered for people. The MCP server returns the same content as JSON.

Workflow

You (the agent) draft the JSON; your user publishes it. Produce a widget or theme following this guide, hand the JSON to your user, and direct them to https://widgentic.dev — sign in, open the widget, theme, or Data schemas designer, use Import, review, and save. The entry appears in their own MCP catalog on the next tool call with their API key.
There is deliberately NO MCP tool to register widgets or themes: API keys are read-only credentials that travel into third-party hosts, so writes require the user’s authenticated session in the designer. Do not look for or request a registration tool.
Call list_widgets to see what already exists (avoid kind collisions), list_schemas for the user’s saved shared data schemas, list_themes for registered themes, and list_theme_tokens for token semantics and presets.

Widget entry

A widget is one JSON object: { kind, template, descriptor }.

Descriptor fields

Reserved kinds

A custom kind must not collide with the built-in kinds: card, table, tree, custom, group. Identifiers match ^[a-zA-Z0-9._-]+$.

Shared data schema entry

A shared data schema is one JSON object: { name, label?, description?, schema } — defined once, referenced by many widgets via descriptor.dataSchemaRef. The user imports it in the Data schemas section at widgentic.dev. Draft the entry, hand it to your user for Import in the Data schemas section, THEN draft widgets referencing it by name — the reference validates against the saved schema when the user saves the widget.

Theme entry

A theme entry is one JSON object: { name, label?, description?, tokens }.

Custom variables

Names match ^x-[a-z0-9][a-z0-9-]*$. A custom variable x-foo becomes —wg-x-foo on the themed scope; reference it from widget styles as var(—wg-x-foo).

Value safety

Token values are plain CSS values. Rejected: ’;’, ’{’, ’}’, ’<’, ’>’, ‘url(’ and ‘expression(’ (case-insensitive, whitespace-tolerant). Keep values to colors, lengths, and font stacks. The full token table is on Theme tokens.

Styles

descriptor.styles is { “<selector>”: { “<cssProperty>”: “<value>” } } — each declaration is a separate key/value pair, e.g. { “.wg-roster-row”: { “display”: “flex”, “gap”: “var(—wg-spacing)” } }. Every selector (and every comma-separated part) must target a .wg- class, e.g. ‘.wg-card .wg-xcard-head’. Selectors, properties, or values matching [;{}<>@\\] — or containing ‘url(’ or ‘expression(’ — are dropped. Property names must match ^-?[a-zA-Z][a-zA-Z-]*$ (letters and hyphens, optionally leading ’-’); anything else is dropped. Reference theme tokens with var(—wg-<token>) and custom variables with var(—wg-x-<name>); prefer tokens over literals so themes restyle the widget. Every registry token is always DEFINED at render time (defaults, overridden by the active theme), so bare var(—wg-<token>) is safe — no fallback needed. Custom x-* variables are defined only by themes that set them, so give those a fallback: var(—wg-x-foo, <value>).

Data schema

Supported subset: type (object/array/string/number/integer/boolean/null, or an array of those), properties, required, items, enum, pattern. Unknown keywords are ignored. pattern is a bounded regex: max 256 chars, no nested quantifiers, applied only to strings and capped input length; unsafe or invalid patterns are ignored rather than enforced. Kinds with a dataSchema fail fast with dotted paths (e.g. data.lines.0.amount); schema-less kinds render leniently.

Data modeling

PREFER binding only properties declared in descriptor.dataSchema — schema-declared data is validated with dotted paths, so agents get correctable errors instead of silently blank output. A ‘$meta.x’ bind path exists (reads the payload’s meta) but meta is NOT covered by dataSchema validation: avoid it, or reserve it for genuinely out-of-band display like a caller-supplied heading. If the widget needs a title, declare `title` as an optional schema property instead. When the user names a SAVED schema, set descriptor.dataSchemaRef to its name (shape from list_schemas) and bind those properties — do NOT reconstruct the schema inline: the copy forks the moment the user edits the shared one. The template node forms and safety rules are on Template DSL; per-user limits on Limits.