Skip to content

fix: track current HELiX in scaffold templates + fix upgrade & doctor#200

Merged
himerus merged 1 commit into
mainfrom
fix/helix-version-drift
May 15, 2026
Merged

fix: track current HELiX in scaffold templates + fix upgrade & doctor#200
himerus merged 1 commit into
mainfrom
fix/helix-version-drift

Conversation

@himerus

@himerus himerus commented May 15, 2026

Copy link
Copy Markdown
Contributor

The bug (caught by the Pulse implementation test)

Every scaffold template hardcoded its own @helixui/library / @helixui/tokens range — most at ^1.0.0 / ^0.3.0, two to three majors behind current HELiX (3.9.1). The pins were set once and never tracked HELiX's releases, so 4 of 5 production templates (react-next, react-vite, svelte-kit, astro) and every experimental template scaffolded apps that started silently stale.

A second runtime regression surfaced in the same investigation: HELiX 3.x's <hx-icon> resolves sprite sheets from a cross-origin jsDelivr CDN by default, which the browser blocks — every scaffolded page that rendered an icon threw console errors.

What changed for consumers

  • Single source of truth. New scaffolds pin @helixui/library / @helixui/tokens at ^3.9.1 and @helixui/icons at ^1.0.1, all from src/helix-versions.ts — future HELiX bumps are a one-line change. Every app template that consumes @helixui/library now also declares the @helixui/icons peer that 3.x requires.
  • Self-hosted icon sprites. App templates (astro, svelte-kit, react-next, react-vite — flat and monorepo) now emit scripts/copy-helix-icons.mjs (a postinstall step that copies the sprites into public/icons/static/icons/ for SvelteKit) and call setBasePath('/icons') in the runtime loader before @helixui/library loads, so <hx-icon> resolves same-origin.
  • doctor drift checks. create-helix doctor gains @helixui/library and @helixui/tokens drift checks — an existing scaffold that has fallen majors behind is now told, with create-helix upgrade named as the fix. The checks follow a monorepo scaffold into apps/web/, are skipped under --quick, and skip @helixui/tokens for Drupal scaffolds (the Drupal preset surface intentionally stays on the 0.x token contract — not migrated in this release). checkHelixIcons now fails rather than silently skipping when @helixui/library@3.x is present but its @helixui/icons peer is not, and checkAppIconSprites catches a pre-v0.9.2 app that renders <hx-icon> on the 3.x contract without sprite wiring.
  • upgrade fixed end to end. --offline is honored and backed by the on-disk registry cache (graceful degradation, partial-failure backfill); peerDependencies are read and written alongside dependencies / devDependencies; version comparison is semver-aware and never proposes a downgrade (even for unparseable ranges like 4.x); when it bumps @helixui/library into 3.x it adds the now-required @helixui/icons peer; it raises a stale @helixui/icons pin to the create-helix floor even with no registry data; and it leaves @helixui/tokens untouched for Drupal projects.
  • The vanilla template's CDN <script> tags are pinned to a concrete version instead of @latest.

Existing scaffolds are not broken — run create-helix doctor to see drift, then create-helix upgrade to move onto current HELiX.

Verification

  • npm run verify (lint + format + type-check) — clean
  • Full test suite — 3243 passing, 8 pre-existing skips (+35 new tests across doctor drift, icon-peer migration, the Drupal token exemption, resolved-vs-declared major detection, and the sprite-wiring check)
  • E2E scaffold + install + build — all 16 framework templates green
  • Full Playwright/visual sweep — green on the new 3.x pins (this is what caught the jsDelivr regression; it's clean after the sprite-self-hosting fix)
  • Reviewed clean by the codex review gate (0 findings)

Release

Patch — create-helix@0.9.2. Changeset included (.changeset/fix-helix-version-drift.md).

create-helix scaffolded every app onto a 2–3 major-stale HELiX core:
templates hardcoded @helixui/library ^1.0.0 / @helixui/tokens ^0.3.0
(latest: 3.9.1). The pins were set once and never tracked HELiX's
releases — surfaced by the Pulse implementation test. Bumping to 3.x
then exposed a runtime regression the build step never catches: HELiX
3.x's <hx-icon> resolves sprites from a cross-origin jsDelivr CDN the
browser blocks, so every scaffolded page threw console errors.

Version pins:
- New src/helix-versions.ts — single source of truth for the @helixui/*
  pins (^3.9.1 / ^3.9.1 / ^1.0.1) + major floors for the doctor checks.
- Repoint all 16 templates + the react-next/react-vite/astro/sveltekit
  monorepo apps/web emitters + presets/loader.ts at the constants.
  Every app template now also declares the @helixui/icons peer
  @helixui/library@3.x requires — declared directly in TEMPLATES so the
  registry, `create-helix info`, and the public API match scaffold output.
- Pin the vanilla template's CDN tags to a concrete version, not @latest.

@helixui/icons same-origin sprites (astro, svelte-kit, react-next,
react-vite — flat + monorepo):
- New src/scaffold/_shared/helix-icons-setup.ts centralizes the fix:
  emit scripts/copy-helix-icons.mjs (a postinstall that copies the
  bundled sprite SVGs into public/icons/ — static/icons/ for sveltekit),
  and call setBasePath('/icons') in the runtime loader before
  @helixui/library loads. react-vite uses an async IIFE to avoid a
  top-level await that would break `vite build`.
- Gitignore the postinstall-generated sprite dir.

doctor:
- Add checkHelixLibrary / checkHelixTokens drift checks (offline,
  major-floor compare) — a scaffold majors behind current HELiX now gets
  told, with `create-helix upgrade` as the remediation.
- All three @helixui/* package checks resolve the consumer's
  node_modules, so they sit behind the --quick gate (scaffold-but-don't-
  install CI gets `skip`, not a false `fail`).
- resolveHelixManifestDir: the checks follow a monorepo scaffold into
  apps/web instead of silently skipping at the workspace root.
- checkHelixIcons enforces the real ^1.0.1 floor (versionAtLeast), not
  major-only — catches a 1.0.0 install that doesn't satisfy the peer.
- Fix a latent checkHelixIcons resolution bug: createRequire().resolve
  of a subpath throws against modern exports-gated packages; read the
  package.json from node_modules directly instead.

upgrade:
- Honor --offline (was parsed but dead), backed by the network.ts
  registry cache with graceful degradation + partial-failure backfill.
- Read + write peerDependencies alongside deps/devDeps so wc-storybook
  scaffolds stay internally consistent.
- semver-aware version comparison so upgrade never proposes a downgrade.

tests: per-framework icons-setup integration coverage (flat + monorepo),
doctor drift/quick/monorepo coverage, upgrade offline/cache/peerDeps/
semver coverage; bump the E2E cleanup-hook timeout so the parallel sweep
stays a deterministic gate.
@himerus himerus merged commit ed3c93b into main May 15, 2026
19 checks passed
@himerus himerus deleted the fix/helix-version-drift branch May 15, 2026 02:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant