Cookies
We use cookies to understand how this site is used. You can accept or reject them: see our Cookie Policy for details.
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.
October 13, 2026
import { de } from "srcdev-hair-treatments/locales/de", then pass { text: de }. Covers every string in the wizard, including option labels, cut and application warnings, and colour recommendationsimport { enUS } from "srcdev-hair-treatments/locales/en-US", then pass { text: enUS }. The built-in copy is British English; this pack switches it to US spelling (color, gray, -ize) and US terms (fringe → bangs, Blow Dry → Blowout), and carries only the strings that differsetup skill: built-in locale pack list now includes de and en-US, with a note on how en-US relates to the default British copyOctober 13, 2026
behaviour.swatchLayout: "scroll-mobile" / "scroll-tablet" turn the Hair Type, Natural Colour and Dream Colour steps into a single horizontally scrolling row below 640px / 1024px of component width; the selected swatch is kept in view. Also available as a swatch-layout-<name> class, with --swatch-scroll-visible to tune cards per rowbehaviour.theme presets, "blush" and "champagne" (light) and "plum" and "ink" (dark), that look the same whatever your brand tokens are--accent-* colour ramp: a new optional token ramp for the selected state (selected option outline and tint, check badge); falls back to --brand-* when not supplied"default", black or white in the monochrome themes. If you tuned --success-* to restyle selection, move that to --accent-*--_surface, --_border, --_ring, --_text), with -subtle, -disabled and -selected variants replacing -active, -inactive and -checked. Update any overrides of the old --_ namessm by default, xs below a 768px component width); --option-font-size still overrides bothOctober 3, 2026
srcdev-hair-treatments/locales/fr) now includes text.tryOn, so the virtual try-on takeover no longer falls back to English on French sites; a new test fails if any tryOn key is missing a French translationtext.progress.stepFormat) is unchanged. Sites that haven't overridden these strings will see the reworded textOctober 3, 2026
behaviour.experimentalTryOn, off by default): preview shades from config.shades on a live webcam feed using client-side MediaPipe hair segmentation, with no image or video data leaving the browser. It opens as a full-viewport modal dialog (native <dialog>, focus-trapped, Escape to close) from a header icon button and a Dream Colour CTA. Not license-gatedbehaviour.tryOnShowShadeImages, behaviour.tryOnModelPath and behaviour.tryOnWasmBaseUrl to control palette photos and self-host the model/wasm; --treatment-consultant-tryon-controls-gap / -margin-block-end tokens for control spacingbehaviour.fullBleedHeader / behaviour.fullBleedHero: run the header and step hero edge to edge of the component (both default true); canvas padding is now applied per row so rows can opt outConsultantHeader is now a full-width banner with the progress track along its bottom edge; depth and background via --treatment-consultant-header-block-size / -header-background--treatment-consultant-hero-block-size, -hero-scrim-colour, -hero-text-colourcontrast-color() text (--option-label-scrim-colour, --option-label-overlay-colour)behaviour.fullBleedHeader: false and behaviour.fullBleedHero: false to keep the previous inset look.consultant-hero-description wrapper and its <hr> are gone, so update any consumer CSS targeting them--_font-size-sm below a 768px component width (a consumer-set --option-font-size still wins)<h2> top margin, so headings sit slightly higher on every stepheader slot content still gets the hero's own copy of the progress label over its image, so progress text in a custom header now appears twicestyleClassPassthrough classes are carried onto the teleported try-on takeover, so per-instance overrides apply there too (<style scoped> overrides still need :global())header slot note on the duplicated progress labeltreatment-consultant skill: updated for try-on, full-bleed flags, the hero banner layout and overlaid swatch labelsstyle-override skill: updated with new tokens, per-row canvas padding, and the scoped-style limitation for the try-on takeoversetup / embed skills: updated with try-on model setup, CSP / Permissions-Policy headers, and the embed model-path overrideSeptember 29, 2026
text.options: localise option labels, descriptions, notes and warnings by id (text.options.<list>.<id>) for hair types, natural colours, desired colours, shades, natural shades, grey coverage, treatments, application types and cuts. Anything you don't supply falls back to the option's own label, so this is fully backwards compatible.import { fr } from "srcdev-hair-treatments/locales/fr" and pass it as { text: fr } through the config prop for a complete French translation. Available on every licence tier.OptionTextConfig, LabelOptionText, DescribedOptionText, TreatmentOptionText and WarnableOptionText are now exported.config prop no longer resets option exclusions or custom options set in createHairTreatments(). Translated labels now live under text, which merges, instead of in option arrays, which replace wholesale. Locale packs also leave your brand name and booking link untouched.setup skill: new "Translating option labels" and "Built-in locale packs" sections, with guidance to keep the config prop to text when combining it with plugin config.September 19, 2026
--treatment-consultant-tryon-controls-gap and --treatment-consultant-tryon-controls-margin-block-end tokens so consumers can restyle the try-on control spacing independently of the shared spacing scalestyle-override skill — documents the two new try-on spacing tokensSeptember 19, 2026
Teleport) instead of being confined to the widget's own box on the page.getUserMedia race that could leave the camera running indefinitely with no way to turn it off, if try-on was closed while the permission prompt was still pending.treatment-consultant.md, embed.md, index.md skills — new: full virtual try-on coverage (behaviour flags, setup, an embed-specific note on overriding the model path).licensing.md skill — updated: documents try-on as the deliberate exception to granular-catalog plan-gating, and corrects a stale note about the shared eligibility-check helper.September 17, 2026
OffscreenCanvas support check was removed, since segmentation only ever draws to regular <canvas> elements and never used it.September 17, 2026
behaviour.showTryOn.public/models/ asset copied the same way as public/images/ — see README's "Images & Models" section) so consumers who never open try-on see no bundle-size impact.StepDreamColour.vue and StepNaturalColour.vue) into a shared isGranularModeEligible helper.September 11, 2026
createHairTreatments — licenseKey can 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.September 10, 2026
config.text.recommendations — the Results colour-recommendation card's method/notes/details copy (previously hardcoded in matrix.ts) is now configurable per hair-colour combination, alongside new config.text.recommendationFallback, texturedHairNote, and sameShadeNoteFormat fields, so the whole card can be localised like the rest of the wizardSeptember 10, 2026
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@oxc-transform binding on deploy (e.g. Vercel) — engines.node >= 24.0.0 is now declared in package.jsonAugust 19, 2026
remoteCheck.ts — logs a one-time (per page load) console.warn when the periodic remote license check-in fails, distinguishing a Content-Security-Policy connect-src block 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 (add https://guidemyhair.com to connect-src); a non-2xx response is flagged as a guidemyhair-side issue, not the consumer's.connect-src requirement, 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.August 18, 2026
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 to dist/tokens.css) instead of --brand-*, so they stay fully desaturated even if you've customised your app's --brand-* tokens.behaviour.sharpCorners — set true to 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.MonochromeLightTheme, MonochromeDarkTheme, and SharpCorners stories.aria-live="polite") rather than a separate hidden element — if you've replaced the header slot with custom markup, add the same aria-live="polite" aria-atomic="true" to your own progress text to keep step changes announced (documented in README).--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) → 0August 17, 2026
TreatmentConsultant — root element collapsed to near-0 width in consumers using container-type: inline-size, since size containment blocks the shrink-to-fit calculation margin-inline: auto relies on to center it; now sets an explicit inline-size: 100% so containment has nothing to break, while max-inline-size and margin-inline: auto keep capping and centering it as beforeAugust 16, 2026
behaviour.naturalColourMode/dreamColourMode: "granular") instead of the broad 7-item grid, backed by real photography (43 dream + 34 natural shades) and a new scripts/convert-shade-images.mjs pipeline; gated to Premium plans, silently falling back to the basic grid below thatconfig.greyCoverageOptions), tracked and shown on Results but excluded from suitability/autoAdvance logicimage2x, rendered via srcset, cutting standard-DPR download size roughly 3x with no change for consumers who don't provide a retina assetOptionSwatch (renamed from CircleSwatch) — now supports circle/square/portrait/landscape shapes via a variant prop, plus new hover tokens for border/outline width and image scale; a new behaviour.swatchVariant config option sets the shape wizard-wideApplicationTypeOption foil-placement warnings — Highlights, Lowlights, and T-Section now warn for curly/coily hair (placement needs adjusting for shrinkage/curl pattern), using the same warnForHairTypes/warnings pattern already used by cutssrcset, not just srcrem literals in TreatmentConsultant.vue/OptionButton.vue that caused misaligned label/sublabel on the "no cut today" option — a new scripts/check-raw-rem.mjs lint check (wired into npm run lint and CI) catches this class of regression going forward--option-border/--option-outline shorthand tokens split into -width/-color pairs so consumers can override just one independentlyShadeTabs dropped role="tablist"/tab ARIA in favour of aria-pressed on plain buttons, matching the existing toggle-button-group pattern rather than implying unimplemented roving-tabindex keyboard nav#E31B23 (read as natural auburn) to #FF1E1E for clearer separation from the natural paletteAugust 11, 2026
dist/embed.js is 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 own TreatmentConsultant instance, configured per-element via data-config (JSON) and data-license-key. The change/complete Vue emits are bridged to native, bubbling hair-treatments:change/hair-treatments:complete CustomEvents. Ships alongside a new dist/embed-style.css (exported from the package) and a tokens.css requirement, same as the main build.embed skill — 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 from setup.md and index.md.licensing skill (private) — new developer-facing skill documenting the license verification architecture, the repo split with the sibling guidemyhair sales site, and where plan-gated UI (like the powered-by badge) hooks in.treatment-consultant skill — documents the licenseKey prop and the licensing/plan behaviour (watermark vs. powered-by badge vs. Premium).data-config JSON parsing (valid and invalid), data-license-key passthrough, and change/complete event dispatch.August 3, 2026
TreatmentConsultant now 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.localStorage), not on every page load."revoked" license status, with its own watermark message ("This license is no longer active.").licenseKey.guidemyhair server endpoint (/api/license/verify), which is already live.August 2, 2026
licenseKey prop — RS256 JWT-based license verification (via a new licenseKey prop 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 + www support, localhost always allowed), and re-checks automatically whenever licenseKey changes after mount.<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)createHairTreatments install triggers a Vue inject() warning, visible in the server terminal on SSR or the browser console on client navigation depending on how the route was reachedJuly 6, 2026
--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 to font-body so it's a no-op unless overridden (75579c3)--treatment-consultant-font-display to --treatment-consultant-font-heading for clarity (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.
July 6, 2026
createHairTreatments / HAIR_TREATMENTS_CONFIG_KEY) (#1) (c6ccf34)OptionButton atom, used across all selection steps and results summary cards (2a70f97, ee01972, b620f94)--brand-*, --success-*, --warning-*, --error-*) (ce2fb63)--_unit, independent of the host app's root font-size (dbceae7)TreatmentConsultant (26fa50a)OptionButton atom (b620f94)Breaking: consumers overriding CSS custom properties directly must update to the new semantic token names (--brand-*, --success-*, --warning-*, --error-*).
June 7, 2026
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:
autoAdvance is suppressed regardless of configtext.navigation.backToResults
New text config key (default: "Back to Results") for the edit-mode shortcut button label.
June 7, 2026
behaviour.showCutStep — new config flag (default true); set to false to skip the Cut step entirely, mirroring theshowTreatmentsStep patternStepHairType now displays a .webp image per hair type; HairTypeOption gains an optionalimage field; defaultConfig ships four bundled images (straight, wavy, curly, coily) ConsultantNavigation exposes the action and useTreatmentConsultant handles the jump logicrelease-notes skill — new: documents the standard format and process for generating release notes for this projectJune 6, 2026
ConsultationSelections emit — TreatmentConsultant now emits update:selections on 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 themselvesTreatmentConsultant is now the only component — the basic variant has been removed; the advanced wizard (previously TreatmentConsultantAdvanced) is now the canonical TreatmentConsultant exportStepHairType, StepNaturalColour, StepDreamColour, StepApplicationType, StepCut, StepTreatments, StepResults, ConsultantNavigation) is now a separate file using provide/inject via consultantKey; no public API changetreatment-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)April 4, 2026
April 3, 2026
April 3, 2026
April 3, 2026
March 31, 2026
March 30, 2026
March 30, 2026
March 30, 2026