Icon set files
Experimental. Every field of the files an icon set is made of: the descriptor, the data file, and an icon definition.IconSetDoc
Experimental: may change or be removed in a patch release. The strongly typed descriptor for one icon set an integration ships: what a person writes about the set. The set's icons, and what each one means, live in the <name>.icons.json data file beside it.
Applies to: <iconSetsRoot>/<name>/<name>.doc.mjs
| Field | Type | Required | Description |
|---|---|---|---|
| type | 'icon-set' | yes | Doc-kind discriminant. |
| name | string | yes | Lower-kebab icon-set identity. Must match the descriptor parent directory. Example: 'outline'. |
| displayName | string | yes | Human-readable name shown by npx @astryxdesign/cli experimental icon --list. Example: 'Acme Outline'. |
| description | string | yes | One-line summary shown by npx @astryxdesign/cli experimental icon --list. |
| maintained | boolean | yes | Whether the owning package actively maintains this set. |
| license | string | yes | SPDX license expression for the artwork. Example: 'MIT'. |
js/** @type {import('@astryxdesign/cli/authoring').IconSetDoc} */export default {type: 'icon-set',name: 'outline',displayName: 'Acme Outline',description: 'Outline icons with rounded strokes.',maintained: true,license: 'MIT',};
Point the manifest's experimental.iconSets field at the folder that holds your sets. Each lower-kebab folder under it is one set, named by the folder, and holds <name>.doc.mjs, <name>.icons.json, and any license notice files. The manifest never lists sets or icons.
Write the descriptor as one default-exported object of literal strings and booleans under a /** @type {import('@astryxdesign/cli/authoring').IconSetDoc} */ comment, with nothing else in the file. Discovery reads it, and the data file, without executing them or the icon module.
The data file is described by npx @astryxdesign/cli docs cli/experimental/icon-set-files icon-set-data. Run npx @astryxdesign/cli integration check to prove every export it names exists in the module and that the theme map agrees with the built-in entries of map.
IconSetData
Experimental: may change or be removed in a patch release. An icon set's data file: which icons exist, the export that draws each one, the words a person might search for, and which icon draws each icon definition (map). npx @astryxdesign/cli experimental icon, template icon mapping, and the checks read this file and nothing else.
Applies to: <iconSetsRoot>/<name>/<name>.icons.json
| Field | Type | Required | Description |
|---|---|---|---|
| schemaVersion | 1 | yes | Data-file format version. |
| module | string | yes | The import specifier every export is read from: the set's own package name, or one of its package.json exports subpaths. Never a file path. Example: '@acme/outline-icons'. |
| source | {package: string, version: string} | no | The upstream library and version the file was generated from. Omit it for a set with no upstream. |
| generated | string | no | The module npx @astryxdesign/cli experimental icon add writes, as a ./ path from the package root: one export per icon, a re-export of a library component or the adapter applied to a library export, and themeIcons, the theme map, from the built-in entries of map. The CLI writes its declaration file beside it. The package's entry re-exports it. Example: './icon-sets/outline/outline.generated.js'. |
| adapter | {module: string, export: string} | no | A function in the package, (source) => Component, that turns a library export that is not a component (icon data, an SVG string or URL) into one. module is a ./ path from the package root. Example: {module: './src/adapt.js', export: 'adapt'}. |
| variants | string[] | no | The named looks the set offers, in lower-kebab case, such as outline and solid. Icon size is never a variant: CSS sets it. Omit it when the set has one look. Example: ['outline', 'solid']. |
| default | {variant?: string} | no | The variant each icon's own export draws; one of variants. Example: {variant: 'outline'}. |
| themeMap | string | no | The export that maps each built-in icon definition to its artwork, keyed by exactly the built-in definitions in map. Example: 'themeIcons'. |
| map | Record<string, string> | no | Which of this set's icons draws each icon definition: definition name to icon id. Keys are Astryx's definitions (npx @astryxdesign/cli docs cli/experimental/icon-definitions) or ones the set declares in its definitions folder, one file per definition. One icon may draw several definitions; each definition maps to one icon. Every built-in definition must be mapped. Example: {"close": "x", "delete": "trash", "remove": "trash"}. |
| icons | IconSetIcon[] | yes | Every icon in the set. |
| icons[].id | string | yes | Lower-kebab identity, unique in the set. Example: 'trash'. |
| icons[].export | string | yes | The named export that draws the icon's default variant, named <Name>Icon: a React component that takes SVG props and draws with currentColor. Example: 'TrashIcon'. |
| icons[].module | string | no | The import specifier, when it differs from the set's module. |
| icons[].words | string[] | yes | Lower-case terms a person might search for, the words of the icon's own name included; at least one. Do not copy the words of the definitions map names the icon for: search already matches the icon by them. Example: ['trash', 'delete', 'remove', 'bin']. |
| icons[].variants | {variant, export, module?}[] | no | Other variants of the icon: each names one of variants, never the default, and the export that draws it. At most one export per variant. |
| icons[].matches | {set, export, variant?, confidence: 'exact' | 'strong' | 'likely'}[] | no | Reviewed equivalents of this icon in other icon sets or libraries, such as {set: 'lines', export: 'CrossIcon', variant: 'solid', confidence: 'exact'}. When a copied template imports a matched icon from that installed set, exact and strong matches are used before any other rule; a likely match is only suggested. A match never names this set itself. |
js{"schemaVersion": 1,"module": "@acme/outline-icons","generated": "./icon-sets/outline/outline.generated.js","variants": ["outline", "solid"],"default": {"variant": "outline"},"themeMap": "themeIcons","map": {"close": "x", "delete": "trash"},"icons": [{"id": "x", "export": "XIcon", "words": ["close", "cancel", "dismiss"]},{"id": "trash","export": "TrashIcon","words": ["trash", "delete", "remove", "bin"],"variants": [{"variant": "solid", "export": "TrashSolidIcon"}]}]}
A file that fails this schema, repeats an id, gives an icon no words, has a map key that is not camelCase or a map value that is not an icon id in the file, or names a variant variants does not declare is invalid, and its set is withdrawn from every surface until it is fixed. npx @astryxdesign/cli doctor names the reason.
A template declares the icon definition each icon it imports draws. With a project icon set, each declared icon maps to the icon whose matches name it with exact or strong confidence (for an icon another installed set ships), else to the icon this file's map names for its definition. Nothing is guessed from names or words.
Write it with the CLI: npx @astryxdesign/cli experimental icon add registers one icon and its map entry, npx @astryxdesign/cli experimental icon map changes an entry, and npx @astryxdesign/cli experimental icon new-set --from wraps a whole library.
IconDefinitionDoc
Experimental: may change or be removed in a patch release. One thing an icon can stand for, such as close or delete. Astryx ships one file per definition; an icon set adds its own in the same format. A set's data file map registers which of its icons draws each definition.
Applies to: <iconSetsRoot>/<set>/definitions/<name>.doc.mjs
| Field | Type | Required | Description |
|---|---|---|---|
| type | 'icon-definition' | yes | Doc-kind discriminant. |
| name | string | yes | camelCase identity: the key a data file's map uses. Must match the file name. Example: 'delete'. |
| description | string | yes | One sentence: what an icon with this definition is for. Example: 'Delete something permanently.'. |
| words | string[] | yes | Lower-case terms a person might search for; at least one. Example: ['trash', 'bin', 'discard']. |
| builtIn | true | no | Only on Astryx's own definitions: the definition is a shared icon name Core renders, so every icon set maps it. |
| stability | 'experimental' | no | Marks the definition as experimental: the icon-definitions listing shows it as [experimental]. Omit it for a definition you mean to keep. |
js/** @type {import('@astryxdesign/cli/authoring').IconDefinitionDoc} */export default {type: 'icon-definition',name: 'rotate',description: 'Rotate an image or shape.',words: ['turn', 'spin'],};
A set's own definitions sit in a definitions folder in the set's directory, one file per definition. Its map registers icons for them like for Astryx's. npx @astryxdesign/cli docs cli/experimental/icon-definitions lists every definition: Astryx's, and, in a project that sets experimental.iconSet, those of each installed set. A definition file refuses a field it does not know.
IconDefinitionDoc is static metadata: one default-exported object of literal fields directly under a /** @type {import('@astryxdesign/cli/authoring').IconDefinitionDoc} */ comment. Discovery reads it without executing it.
To share a definition with every set, copy its file into Astryx's definitions folder in a pull request.