Summary
Implement palette and scheme support for drawings: load GIMP Palette (.gpl) files from a user-managed library, and let each drawing turn a palette into a named color scheme.
The design is fully decided and recorded in ADR-0002 (see PR #3, doc/adr/ADR-0002-Palettes-and-Schemes.md). Read it first; this issue is the implementation handoff and does not repeat the full rationale.
Background: Palette vs Scheme
- Palette: an ordered set of colors (optionally named), stored as a
.gpl file in the user's library. Re-usable, carries no semantics.
- Scheme: a palette plus a mapping of user-chosen role names (
bg, main, accent, ...) to the palette's colors. Created in drawing code, used there, never stored.
The flow in a drawing: load palette → map roles in drawing code → use scheme's named colors.
Scope of this issue
.gpl parser — our own, minimal, against the official spec (formalized 2023, MUST-level rules): https://developer.gimp.org/core/standards/gpl/
- First line MUST be
GIMP Palette
- Optional
Name: line (UTF-8, stripped), optional Columns: line (0-255, cosmetic only)
- Old, header-less format: if line 2 is not
Name:, colors start at line 2 and the palette name is the file basename (spec-prescribed fallback)
- Color lines:
r g b integers 0-255, then optional color name (rest of line, stripped)
# comment lines and empty lines are ignored
- Known replacement if ours proves insufficient: anypalette (multi-format, no TS types, browser-oriented) — do not add it now, the parser is an implementation detail behind the public API
- Palette library — user-managed; opinionated default
./palettes/ in the drawing project (same convention as saves/). Vormen reads, never writes. No palettes shipped with the library. Users can copy any existing .gpl (GIMP, Inkscape, Lospec exports, public collections) there.
- Palette identity — palette name from the embedded
Name: header; filename basename fallback for old-format files. Names must be unique in the library; the loader fails loudly on duplicates or missing palettes.
- Scheme creation in drawing code — an API to load a palette by name and map roles to its colors (by color name and/or index). Roles are free-form, user-chosen names. Exact API shape (function/class, module location,
scheme.get("bg") vs scheme.bg) is deliberately postponed in the ADR — decide during implementation, keep the public API small per AGENTS.md.
- Settings integration — a drawing declares a
scheme setting whose value is a palette name; CLI override: --setting.scheme=wet-tokyo (singular setting., matching the existing runner convention in src/vormen/vormen.ts). Note: the setting selects a palette; the scheme exists only after the drawing assigns roles.
- Colors as strings — expose colors as
#RRGGBB strings, passed directly to svg.js fill/stroke/gradients. Full color utilities (HSL/RGB/OKLCH, lighten(10), etc.) are explicitly out of scope (postponed in the ADR).
Test fixtures required
At least two .gpl files for unit and/or integration tests:
- one with a proper
Name: header and named colors (new format)
- one old-format file (no
Name: line) to exercise the filename-basename fallback
Constraints (from AGENTS.md / ADR-0002)
- Tests first; each module has unit tests, each feature an integration test
deno run check:all must pass with no errors or warnings
- Keep the public API minimal; do not export what has no use outside the module
- No new dependencies (no
anypalette, no color libraries)
- Do not add manual lint/typing overrides
- Document the feature in README (new module section) and add Palette/Scheme to
doc/glossary.md (the glossary already mentions "Color: Color manipulation and palettes" — extend it with the canonical terms)
- Postponed by the ADR (do not build): storing schemes, sidecar files, color manipulation utilities, serve-mode swatch widget,
create-vormen scaffolding of palettes/, user-level palette dir, listing available palettes
References
Summary
Implement palette and scheme support for drawings: load GIMP Palette (
.gpl) files from a user-managed library, and let each drawing turn a palette into a named color scheme.The design is fully decided and recorded in ADR-0002 (see PR #3,
doc/adr/ADR-0002-Palettes-and-Schemes.md). Read it first; this issue is the implementation handoff and does not repeat the full rationale.Background: Palette vs Scheme
.gplfile in the user's library. Re-usable, carries no semantics.bg,main,accent, ...) to the palette's colors. Created in drawing code, used there, never stored.The flow in a drawing: load palette → map roles in drawing code → use
scheme's named colors.Scope of this issue
.gplparser — our own, minimal, against the official spec (formalized 2023, MUST-level rules): https://developer.gimp.org/core/standards/gpl/GIMP PaletteName:line (UTF-8, stripped), optionalColumns:line (0-255, cosmetic only)Name:, colors start at line 2 and the palette name is the file basename (spec-prescribed fallback)r g bintegers 0-255, then optional color name (rest of line, stripped)#comment lines and empty lines are ignored./palettes/in the drawing project (same convention assaves/). Vormen reads, never writes. No palettes shipped with the library. Users can copy any existing.gpl(GIMP, Inkscape, Lospec exports, public collections) there.Name:header; filename basename fallback for old-format files. Names must be unique in the library; the loader fails loudly on duplicates or missing palettes.scheme.get("bg")vsscheme.bg) is deliberately postponed in the ADR — decide during implementation, keep the public API small per AGENTS.md.schemesetting whose value is a palette name; CLI override:--setting.scheme=wet-tokyo(singularsetting., matching the existing runner convention insrc/vormen/vormen.ts). Note: the setting selects a palette; the scheme exists only after the drawing assigns roles.#RRGGBBstrings, passed directly to svg.jsfill/stroke/gradients. Full color utilities (HSL/RGB/OKLCH,lighten(10), etc.) are explicitly out of scope (postponed in the ADR).Test fixtures required
At least two
.gplfiles for unit and/or integration tests:Name:header and named colors (new format)Name:line) to exercise the filename-basename fallbackConstraints (from AGENTS.md / ADR-0002)
deno run check:allmust pass with no errors or warningsanypalette, no color libraries)doc/glossary.md(the glossary already mentions "Color: Color manipulation and palettes" — extend it with the canonical terms)create-vormenscaffolding ofpalettes/, user-level palette dir, listing available palettesReferences
doc/adr/ADR-0002-Palettes-and-Schemes.md.gplspec: https://developer.gimp.org/core/standards/gpl/src/settings/settings.ts,src/vormen/vormen.ts.gpl(for realistic fixtures): https://github.com/denilsonsa/gimp-palettes