Release notes
Everything shipped in srcdev-hair-treatments, newest first. Check here before upgrading, especially for anything marked Breaking. Found a bug? Let us know via the contact form.
v1.2.0
September 11, 2026
v1.2.0
Changed
createHairTreatments—licenseKeycan now be passed inline on the config object (createHairTreatments({ licenseKey })), matching how every other setting is already passed; the old two-argument form (createHairTreatments(config, licenseKey)) still works. Fixes two real consumers who guessed the inline form and silently shipped unlicensed.
v1.1.3
September 10, 2026
v1.1.3
New
config.text.recommendations— the Results colour-recommendation card's method/notes/details copy (previously hardcoded inmatrix.ts) is now configurable per hair-colour combination, alongside newconfig.text.recommendationFallback,texturedHairNote, andsameShadeNoteFormatfields, so the whole card can be localised like the rest of the wizard
Fixed
- The Results recommendation card showed hardcoded English text regardless of locale — the underlying suitability classification (which combinations are "great" vs "not-recommended") stays internal, but every string shown to the user is now sourced from config
v1.1.2
September 10, 2026
v1.1.2
New
config.text.labels— a handful of UI strings that were still hardcoded directly in component templates (the "no cut today" skip option, the hair-type-excluded note, the treatment-conflict message, and the granular shade catalog's "All Shades" tab) are now config-driven like the rest of the wizard's copy, so they can be localised or overridden
Fixed
- The "Powered by GuideMyHair" link now shows on every step for a non-Premium license (including trial), not just the Results screen
- Consuming apps on Node versions below 24 could hit a missing
@oxc-transformbinding on deploy (e.g. Vercel) —engines.node >= 24.0.0is now declared inpackage.json
v1.1.1
August 19, 2026
v1.1.1
New
remoteCheck.ts— logs a one-time (per page load)console.warnwhen the periodic remote license check-in fails, distinguishing a Content-Security-Policyconnect-srcblock from a genuine network error/timeout (previously indistinguishable to script, and both silently ignored — the check still fails open either way, this only adds visibility). A CSP block gets a message naming the exact fix (addhttps://guidemyhair.comtoconnect-src); a non-2xx response is flagged as a guidemyhair-side issue, not the consumer's.
Documentation
- Documented the
connect-srcrequirement, and why a failed remote check never downgrades functionality (the plan itself is already cryptographically authoritative in the signed license token), in.claude/skills/private/licensing.md.
v1.1.0
August 18, 2026
v1.1.0
New
behaviour.theme— switch the component's colour treatment via config:"default"(existing dark brand-coloured canvas),"monochrome-light"(white canvas, foreground darkening to near-black), or"monochrome-dark"(same dark-canvas/light-text layout as"default", with brand hue removed). Neither monochrome theme carries any hue anywhere the default theme uses brand colour — both use a new dedicated chroma-0 grey ramp (--mono-00…--mono-10, added todist/tokens.css) instead of--brand-*, so they stay fully desaturated even if you've customised your app's--brand-*tokens.behaviour.sharpCorners— settrueto square off every rounded corner (option cards, buttons, panels, the license watermark). Deliberately circular/pill shapes (the circle swatch, the checkmark badge, progress dots/bars) are unaffected.- Storybook: new Theme select and Sharp corners boolean controls, plus
MonochromeLightTheme,MonochromeDarkTheme, andSharpCornersstories. - The colour recommendation on the Results step now notes when you've picked the exact same granular shade for both your natural and dream colour (e.g. Jet Black → Jet Black) — e.g. "You've selected your current shade (Jet Black) — this refreshes rather than changes your colour" — instead of silently presenting it as if it were a meaningful colour change.
Fixed
- The option button and colour-swatch outline is now invisible at rest and only appears on hover/focus, instead of showing a static ring at all times.
- A selected option's swatch ring no longer reverts to the generic hover colour instead of staying checked-green when the option is both selected and hovered at once.
- The header's progress bar was a fixed 12rem width regardless of the step label's actual rendered text width, so on longer labels ("Step 7 of 7 — Results") it read as an underline that stopped partway through the text instead of spanning it. Now always matches the label's width.
- Removed a redundant, visually-duplicated progress line above the step content that repeated the header's own progress label. The screen-reader announcement of step changes moves onto the header's progress label itself (
aria-live="polite") rather than a separate hidden element — if you've replaced theheaderslot with custom markup, add the samearia-live="polite" aria-atomic="true"to your own progress text to keep step changes announced (documented in README). - The "No cut today" / "I don't want any treatments" cards had their label and sublabel visually misaligned (label sitting low, sublabel's text stranded at the top of an oversized box) — both now share one vertical centre with the icon.
Changed
- Several
--option-*/--option-swatch-*default values changed as part of the outline-visibility fix above — if you've overridden any of these, or hardcoded them elsewhere (e.g. in your own docs), check against the new defaults in README's "Overriding Styles" reference:--option-outline-width/--option-swatch-outline-width:1px→2px--option-swatch-border-width:3px→1px--option-outline-color/--option-swatch-outline-color: now theme-driven (var(--_outline-default), transparent) rather than a fixed value--option-outline-offset-hover:calc(0.1 * var(--_rem))(~1px) →0
- Per-step swatch style overrides in the Dream Colour, Natural Colour and Results steps were removed — they duplicated what are now the shared defaults above.
v1.0.1
August 17, 2026
v1.0.1
Fixed
TreatmentConsultant— root element collapsed to near-0 width in consumers usingcontainer-type: inline-size, since size containment blocks the shrink-to-fit calculationmargin-inline: autorelies on to center it; now sets an explicitinline-size: 100%so containment has nothing to break, whilemax-inline-sizeandmargin-inline: autokeep capping and centering it as before
v1.0.0
August 16, 2026
v1.0.0
New
- Redesign — reordered the wizard to ask Natural Colour before Hair Type (feedback was that leading with hair type felt backwards); added a persistent header (brand/title + live progress) and per-step explainer content above each selection step to fill the previously-sparse early steps
- Granular shade catalogs — Natural Colour and Dream Colour can now opt into a tabbed catalog of ~40 named shades each (
behaviour.naturalColourMode/dreamColourMode: "granular") instead of the broad 7-item grid, backed by real photography (43 dream + 34 natural shades) and a newscripts/convert-shade-images.mjspipeline; gated to Premium plans, silently falling back to the basic grid below that - Grey coverage — new independent question on the Natural Colour step (
config.greyCoverageOptions), tracked and shown on Results but excluded from suitability/autoAdvance logic - Retina images — shade/hair-type images gained an optional
image2x, rendered viasrcset, cutting standard-DPR download size roughly 3x with no change for consumers who don't provide a retina asset OptionSwatch(renamed fromCircleSwatch) — now supportscircle/square/portrait/landscapeshapes via avariantprop, plus new hover tokens for border/outline width and image scale; a newbehaviour.swatchVariantconfig option sets the shape wizard-wideApplicationTypeOptionfoil-placement warnings — Highlights, Lowlights, and T-Section now warn for curly/coily hair (placement needs adjusting for shrinkage/curl pattern), using the samewarnForHairTypes/warningspattern already used by cuts
Fixed
- Results summary card order now matches actual step order, and the summary grid no longer leaves a half-empty trailing row
- Granular catalog no longer hard-blocks the wizard when its shade list is empty on a Premium license (falls back to the basic grid instead)
- Results summary thumbnails now get a real
srcset, not justsrc - Raw
remliterals inTreatmentConsultant.vue/OptionButton.vuethat caused misaligned label/sublabel on the "no cut today" option — a newscripts/check-raw-rem.mjslint check (wired intonpm run lintand CI) catches this class of regression going forward
Changed
--option-border/--option-outlineshorthand tokens split into-width/-colorpairs so consumers can override just one independently- Circle promoted to the implicit default swatch shape (no modifier class emitted)
ShadeTabsdroppedrole="tablist"/tabARIA in favour ofaria-pressedon plain buttons, matching the existing toggle-button-group pattern rather than implying unimplemented roving-tabindex keyboard nav- Vivid Red bumped from
#E31B23(read as natural auburn) to#FF1E1Efor clearer separation from the natural palette
v0.4.0
August 11, 2026
v0.4.0
New
- Plain HTML embed build —
dist/embed.jsis a standalone entry point for sites with no bundler and no Vue app of their own. Vue is bundled in, so a single<script type="module">tag is all that's needed. Every[data-hair-treatments]element on the page auto-mounts its ownTreatmentConsultantinstance, configured per-element viadata-config(JSON) anddata-license-key. Thechange/completeVue emits are bridged to native, bubblinghair-treatments:change/hair-treatments:completeCustomEvents. Ships alongside a newdist/embed-style.css(exported from the package) and atokens.cssrequirement, same as the main build. - "Powered by GuideMyHair" badge — a discrete link now appears bottom-right of the results screen for Basic and Standard license plans. Premium licenses, and any unlicensed/invalid state (already covered by the existing watermark), don't show it.
Documentation
embedskill — new consumer skill covering the plain-HTML/CDN embed flow: usage, multiple instances, per-element config, license key, event bridging, and known limitations. Cross-linked fromsetup.mdandindex.md.licensingskill (private) — new developer-facing skill documenting the license verification architecture, the repo split with the siblingguidemyhairsales site, and where plan-gated UI (like the powered-by badge) hooks in.treatment-consultantskill — documents thelicenseKeyprop and the licensing/plan behaviour (watermark vs. powered-by badge vs. Premium).
Tests
- Added embed-focused Vitest coverage: DOM auto-mounting, the double-mount guard,
data-configJSON parsing (valid and invalid),data-license-keypassthrough, andchange/completeevent dispatch.
v0.3.1
August 3, 2026
v0.4.0
Added
- Periodic remote license revocation check. On top of the existing local JWT verification (signature, expiry, domain),
TreatmentConsultantnow does a cached, best-effort check-in against guidemyhair's license API to catch a license that's been canceled or expired server-side even though its token is still validly signed and unexpired.- Checked once per 24 hours per license key (cached in
localStorage), not on every page load. - Fails open: a network error or an unreachable guidemyhair never revokes a locally-valid license — only an explicit "inactive" response from the server does. A customer's site is never broken by our uptime.
- New
"revoked"license status, with its own watermark message ("This license is no longer active.").
- Checked once per 24 hours per license key (cached in
Notes
- No prop or config changes — this is transparent to existing consumers of
licenseKey. - Requires the corresponding
guidemyhairserver endpoint (/api/license/verify), which is already live.
v0.3.0
August 2, 2026
v0.3.0
New
licenseKeyprop — RS256 JWT-based license verification (via a newlicenseKeyprop or matching plugin option). Unlicensed usage now renders a visible watermark overlay instead of silently working. Verification runs client-only, checking signature, expiry, and domain (wildcard +wwwsupport,localhostalways allowed), and re-checks automatically wheneverlicenseKeychanges after mount.
Documentation
- README — documented the
<ClientOnly>workaround needed for a Nuxt SSR crash (this package has no SSR render; the wizard has no SEO value, so it should be rendered client-only in Nuxt) - README — noted that omitting the plugin's
createHairTreatmentsinstall triggers a Vueinject()warning, visible in the server terminal on SSR or the browser console on client navigation depending on how the route was reached
v0.2.4
July 6, 2026
v0.2.4
Features
- Split the single font token into a 3-tier system for finer typographic control:
--treatment-consultant-font-body(renamed from--treatment-consultant-font-family) — default text, sublabels, notes--treatment-consultant-font-heading— step titles, Results title, section titles, suitability label--treatment-consultant-font-label(new) — small uppercase UI chrome (progress status, option labels), defaults tofont-bodyso it's a no-op unless overridden (75579c3)
Chores
- Rename
--treatment-consultant-font-displayto--treatment-consultant-font-headingfor clarity (75579c3)
Docs
- Update README, Storybook demo, and skill docs for the new font token names (75579c3)
Breaking: consumers overriding --treatment-consultant-font-family must rename it to --treatment-consultant-font-body. Consumers overriding --treatment-consultant-font-display must rename it to --treatment-consultant-font-heading.
v0.2.3
July 6, 2026
v0.2.3
Features
- Add global app configuration plugin (
createHairTreatments/HAIR_TREATMENTS_CONFIG_KEY) (#1) (c6ccf34) - Add i18n text support and merge the config/types split into a single canonical module (a46cddf)
- Add shared
OptionButtonatom, used across all selection steps and results summary cards (2a70f97, ee01972, b620f94) - Add colour ramps and rename CSS custom properties to semantic names (
--brand-*,--success-*,--warning-*,--error-*) (ce2fb63) - Add fluid typography scale and make component sizing self-contained via
--_unit, independent of the host app's root font-size (dbceae7) - Wire up accent font and update default font family (dbceae7, 39dd4ae)
Fixes
- Align Results step option buttons with the styling used by other steps (2e92116)
Chores
- Remove unused font file (8bfd77d)
Tests & Docs
- Add component integration tests for
TreatmentConsultant(26fa50a) - Add Playwright visual regression tests for the new
OptionButtonatom (b620f94) - Update tests, README, and Storybook/skills docs to match the above changes (6360533, ee01972)
Breaking: consumers overriding CSS custom properties directly must update to the new semantic token names (--brand-*, --success-*, --warning-*, --error-*).
v0.2.2
June 7, 2026
v0.2.2 — Hair type images & edit-from-results
New features
Hair type image swatches
Hair type options now support an image?: string field on HairTypeOption. Default images are bundled with the package and displayed as circular crops in both the Hair Type step and the results summary card, with object-fit: cover for non-square sources. Falls back to the existing pattern text (|||, ∿∿∿ etc.) when no image is provided.
Bundled image assets
All default images (hair type swatches and colour swatches) are now shipped with the package under public/images/. Copy them into your app's public directory with:
```bash
cp -r node_modules/srcdev-hair-treatments/public/images/. public/images/
```
Edit from results Summary cards on the results step are now clickable — tapping one navigates directly back to that step. This enters an edit mode where:
autoAdvanceis suppressed regardless of config- A Back to Results button appears in the navigation bar alongside Back / Next, allowing the user to jump straight back without stepping through every subsequent step
- Edit mode clears automatically on returning to results
text.navigation.backToResults
New text config key (default: "Back to Results") for the edit-mode shortcut button label.
Bug fixes
- Results summary hair type card now shows the hair type's own visual representation instead of a generic scissors icon
v0.2.1
June 7, 2026
v0.2.1
New
behaviour.showCutStep— new config flag (defaulttrue); set tofalseto skip the Cut step entirely, mirroring the
existingshowTreatmentsSteppattern- Hair Type image swatches —
StepHairTypenow displays a.webpimage per hair type;HairTypeOptiongains an optional
imagefield;defaultConfigships four bundled images (straight, wavy, curly, coily) - Results step — return to any step — clicking a summary item on the Results step now navigates directly back to that step;
ConsultantNavigationexposes the action anduseTreatmentConsultanthandles the jump logic
Documentation
release-notesskill — new: documents the standard format and process for generating release notes for this project
v0.2.0
June 6, 2026
v0.2.0
New
ConsultationSelectionsemit —TreatmentConsultantnow emitsupdate:selectionson every step change, giving consuming apps read-only visibility into the wizard state (hairType,naturalColour,desiredColour,applicationType,cut,treatments) without needing to manage the state themselves
Changed
TreatmentConsultantis now the only component — the basic variant has been removed; the advanced wizard (previouslyTreatmentConsultantAdvanced) is now the canonicalTreatmentConsultantexport- Step components extracted — each wizard step (
StepHairType,StepNaturalColour,StepDreamColour,StepApplicationType,StepCut,StepTreatments,StepResults,ConsultantNavigation) is now a separate file usingprovide/injectviaconsultantKey; no public API change - CSS class names simplified — dropped the
treatment-consultant__BEM prefix from all internal classes; CSS nesting under.treatment-consultant {}provides the specificity. Shared styles consolidated into the parent component. CSS bundle reduced from ~55 kB to 20.5 kB (gzip: 3.05 kB)
v0.1.8
April 4, 2026
- Steps buttons updates (5802db6)
- Bemify some css classes, consuming app generic classes can apply classes (7cff765)
v0.1.7
April 3, 2026
- Bugfix - Step to final not available under specific circumstances (67f229c)
v0.1.6
April 3, 2026
- Add exclusions and warning for cuts based on hair types (7387875)
- Bugfix - Icon missing from treatment selected in results summary (6da11d4)
- TreatmentConsultantAdvanced - Add cuts step (5582f58)
- Applications added to results summary (012883b)
v0.1.5
April 3, 2026
- TreatmentConsultantAdvanced - New component added and file structure refactor (d7ac79c)
- Add prices if required (acc0475)
- settings update (a812b5a)
- fix(ci): add emnapi optional deps to lock file for Linux CI (909de48)
v0.1.4
March 31, 2026
- Skills updated (0a7b673)
- Skills - updated (c8603e7)
v0.1.3
March 30, 2026
- Publish issue - css missing (2b05a22)
v0.1.2
March 30, 2026
- Fix - types not being exported (5f56a95)
v0.1.1
March 30, 2026
- release-it - prepare for release to npm (edeb20f)
- Claude memory updated (f9a3ea7)
- Package - Major version bumped plus fix some test breakages (9062454)
- Packages - all up to date and version pinned (1a593cc)
- Tests - fix issues due to recent updates (5e2148d)
- Scroll to top on step change and make treatments (last step) single column (221bc62)
- Steps transition updated to mirror main content (acaf3ce)
- Steps button update transition (2015d86)
- Steps alignment < 768px (5d6f5c9)
- Steps - Button styles for < tablet 768px (fa98821)
- global font size reset to base 10 for 1rem (4eb7702)
- npm run dev spins up Storybook as this is used for component only development. (4a4ab87)
- Add licensing and commercialisation plan (72daa57)
- Add configure-treatments skill for consumer developers (437ff2c)
- Split skills into public/ and private/ directories (d9142ab)
- Update CLAUDE.md with accurate architecture and testing notes (e061a9d)
- Fix TS error in matrix.test.ts (5f94026)
- Add CI workflow and README badges (ecd1caa)
- Add unit tests — 98 tests across 4 suites (74c3b83)
- feat: add swatch images for Storybook development (1196db4)
- feat: ship Claude Code skills with package (df14878)
- docs: add README with installation, config, and development guide (fb40871)
- refactor: extract composable, config, and matrix from TreatmentConsultant (89b2378)
- feat: initial project setup and TreatmentConsultant component migration (f249dd9)