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

FieldTypeRequiredDescription
type'icon-set'yesDoc-kind discriminant.
namestringyesLower-kebab icon-set identity. Must match the descriptor parent directory. Example: 'outline'.
displayNamestringyesHuman-readable name shown by npx @astryxdesign/cli experimental icon --list. Example: 'Acme Outline'.
descriptionstringyesOne-line summary shown by npx @astryxdesign/cli experimental icon --list.
maintainedbooleanyesWhether the owning package actively maintains this set.
licensestringyesSPDX license expression for the artwork. Example: 'MIT'.
An icon-set descriptor at icons/outline/outline.doc.mjs
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

FieldTypeRequiredDescription
schemaVersion1yesData-file format version.
modulestringyesThe 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}noThe upstream library and version the file was generated from. Omit it for a set with no upstream.
generatedstringnoThe 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}noA 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'}.
variantsstring[]noThe 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}noThe variant each icon's own export draws; one of variants. Example: {variant: 'outline'}.
themeMapstringnoThe export that maps each built-in icon definition to its artwork, keyed by exactly the built-in definitions in map. Example: 'themeIcons'.
mapRecord<string, string>noWhich 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"}.
iconsIconSetIcon[]yesEvery icon in the set.
icons[].idstringyesLower-kebab identity, unique in the set. Example: 'trash'.
icons[].exportstringyesThe 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[].modulestringnoThe import specifier, when it differs from the set's module.
icons[].wordsstring[]yesLower-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?}[]noOther 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'}[]noReviewed 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.
A data file at icons/outline/outline.icons.json
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

FieldTypeRequiredDescription
type'icon-definition'yesDoc-kind discriminant.
namestringyescamelCase identity: the key a data file's map uses. Must match the file name. Example: 'delete'.
descriptionstringyesOne sentence: what an icon with this definition is for. Example: 'Delete something permanently.'.
wordsstring[]yesLower-case terms a person might search for; at least one. Example: ['trash', 'bin', 'discard'].
builtIntruenoOnly on Astryx's own definitions: the definition is a shared icon name Core renders, so every icon set maps it.
stability'experimental'noMarks the definition as experimental: the icon-definitions listing shows it as [experimental]. Omit it for a definition you mean to keep.
A set's own definition at icon-sets/outline/definitions/rotate.doc.mjs
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.