0054. Icons of one's own are added from the editor as a project pack
Status: accepted (custom-icons change, 23 October 2026). Extends decisions 0014 and 0041.
Context
Section titled “Context”A project could already ship its own icons (decision 0014): an SVG file in
assets/icons/<prefix>/<name>.svg, or an Iconify file, is a pack the registry resolves for
icon "<prefix>:<name>", the sanitiser checks, every exporter embeds as paths and the cloud stores
as text. Nobody could get there from the editor: the icon picker had no way to add a file, a file
called My Logo.svg became an icon whose name the grammar refuses, a new pack was an error until
assets/licenses.json named its licence, an SVG folder pack had no labels or categories so it
never appeared in the Libraries panel, and the problems of the asset files were printed by the
command line only. The owner asked on 2026-10-22 for “the possibility of adding new icons”.
Decision
Section titled “Decision”- Add icon… writes a project pack, its licence and its library, in one undo step. At the foot
of the icon picker and of the Libraries panel, in a file of a project, it opens the system’s file
chooser for SVG files (from the canvas’s own page: the playground is one, VS Code’s webview lets
one open it) and a dialog: the pack’s prefix (
projectby default), the licence of a new pack (Own work isLicenseRef-Project, a few SPDX identifiers, or one typed), and a row per file with its preview, the name it gets and what is wrong. Adding writesassets/icons/<prefix>/<name>.svgper icon, the pack’s entry inassets/licenses.jsonwhen it has none, and an item per icon inassets/libraries/project.json(the Project library, a category per pack), so the icon is found, listed and licensed at once. Selected elements take the first icon in the same step; with none, the icon tool is armed with it. - The session checks, the dialog shows.
checkIconsanswers, as the prefix and the names are typed, the name offered (made of the file’s:My Logo (1).svgisMy-Logo-1, a taken one gets-2), a preview through the sanitiser and each problem;addIconschecks again and answers the icons added with the files to write. A prefix is refused when it is a built-in pack’s, a plugin’s, an Iconify file’s of the project or an alias ofproject.json. A file no icon can be made of (one the sanitiser refuses, a raster, one over 256 KB) is left out with its reason; a bad prefix, name or licence keeps the dialog from confirming. - The files go beside the steps. The request is steps over files (decision 0051) with an
assetspart: the new files and the changes of the JSON files of the assets.ProjectSessions.planAssetStepsplans them first, as overlays, then the steps, refuses a new file whose path is taken, and keeps a JSON file’s indentation.planStepsis unchanged. In the playground the step is one of the project’s undo stack: undo takes the files away, redo writes them again. - SVG only, names a reference can write. A raster stays an
imageof a free composition. A file already in a pack whose name a reference cannot write is left out with the warningasset.unusable-name, whose hint names the file to rename it to. - The assets’ problems are shown where the others are. The playground counts them on the file and its folders (a folder has problems of its own, a pack without licence), and an asset file opened lists its own; VS Code publishes them in its Problems view.
- Guests of a live session may add icons when they may edit: the files are sanitised text, written through the room like any edit. Images stay refused to them, being uploaded as blobs.
Alternatives considered
Section titled “Alternatives considered”- An Iconify file per prefix: smaller folders, but each addition rewrites one growing file and a diff shows path data instead of one new file.
- A path or a data URI as an
iconvalue: references with spaces or data would break completion, the lock and the Iconify convention. - A
writeFilekind of step insideplanSteps: every consumer of the steps would have to tell the kinds apart. - A host request for the files (
showOpenDialog, a shell input): two implementations of the same chooser, and the texts going through the host for nothing. - Writing
LicenseRef-Projectsilently: a person adding a vendor’s icons would mislabel them.
Consequences
Section titled “Consequences”- An icon added from the editor is an ordinary project pack: the command line, the exporters, the player, the catalog and the cloud need no change.
- New public surface:
slugifyIconName,isIconNameandICON_NAMEin the assets package;iconFilePathandPROJECT_LIBRARY_FILEin the project package and the warningasset.unusable-name; the canvas messagescheckIconsandaddIconsand their answers,CanvasRender.project,AssetSteps,ProjectSessions.planAssetSteps,changedAssetFile,checkIconPrefix,checkIconFilesandaddIconsin the editor package. The language stays 0.2.