Skip to content

Latest commit

 

History

History
110 lines (75 loc) · 7.74 KB

File metadata and controls

110 lines (75 loc) · 7.74 KB

Pulse Universal — Roadmap

How we go from the validated Vue v2.3.4 monolith to a true multi-framework library, without breaking anything along the way.

Current state — v3.0.0-rc.0 + alpha.24 (shipped on npm, 2026-06-08)

7 / 7 publishable @pulse-music/* packages are LIVE on the npm registry after a 21-tag alpha cycle. Vue v2.3.4 src/lib/ is bit-for-bit identical across 25 consecutive alphas. 139 / 139 unit tests passing across the monorepo, 0 production vulnerabilities, 6 GitHub Actions workflows green (CI + visual + a11y + coverage + release-please + CodeQL).

Package Version on npm Bundle gzip
@pulse-music/types 3.0.0-rc.0 0.1 kB
@pulse-music/core 3.0.0-rc.0 2 kB
@pulse-music/tokens 3.0.0-rc.0 0.6 kB
@pulse-music/web-component 3.0.0-rc.1 8.5 kB
@pulse-music/react 3.0.0-rc.0 1 kB
@pulse-music/svelte 3.0.0-rc.0 0.4 kB
@pulse-music/react-native 3.0.0-rc.1 12 kB
pulse-player (Vue v2.3.4 reference) 2.3.4 14 kB

The phases below are the historical record of how we got here. The forward-looking plan to v3.0.0 stable + Phase 2 monetisation lives in VERSION_STRATEGY.md and PRICING.md. The adoption metrics that gate Phase 2 are in METRICS_TRACKING.md. The condensed one-paragraph-per-alpha narrative is in ALPHA_HISTORY.md.

Cadence discipline (post-rc.0)

The 49-tag in 48-hour alpha cycle was deliberate: an audit-driven loop where every alpha closed an externally-named gap. The same discipline doesn't apply post-publish — the cost of a tag is now an npm publish per affected package, not a free git tag. The forward cadence:

  • rc.X patch: at most one per week. Encourages users to actually integrate before the next version drops. Triggered by real bug reports or adopter-requested API tweaks. Not by maintainer initiative.
  • v3.0.0 stable cut: when the METRICS_TRACKING.md Day 30 target is met (≥ 200 stars + ≥ 1 000 dl/week + ≥ 10 external issues/PRs) AND no critical bug open for 2 consecutive weeks.
  • Post-stable: standard SemVer cadence — patch as bugfix lands, minor as feature batch (monthly), major as breaking-change-with-migration-guide (annually max).

The 49-alpha lineage stays in the git history as transparency — they're not deleted, force-pushed, or squashed. See VERSION_STRATEGY.md for the rationale.

Historical phases (for context — keep scrolling for the forward plan in VERSION_STRATEGY.md)

Phase 0 — Scaffold (v3.0.0-alpha.0) ✅

Lays the monorepo foundation. No code moved. The v2.3.4 Vue codebase at src/lib/ continues to work bit-for-bit identical.

What lands:

  • pnpm-workspace.yaml + npm workspaces configuration in root package.json
  • turbo.json for build orchestration (optional — installs only with pnpm add -D turbo)
  • packages/ with 9 scaffolds: types, core, tokens, web-component, vue, react, react-native, angular, svelte
  • @pulse-music/types is the only package with real code in this alpha — it ships the shared TypeScript types (zero runtime, zero risk)
  • docs/universal/ARCHITECTURE.md, docs/universal/ROADMAP.md, per-framework doc placeholders
  • Vue demo + tests verified to still pass after the workspaces field is added

What doesn't land:

  • Actual code migration. The Vue code stays at src/lib/.
  • No new framework wrappers are implemented yet.
  • No CI changes (existing matrix continues to gate pulse-player root package).

Phase 1 — Extract core + tokens (v3.0.0-alpha.1)

  • @pulse-music/core — port src/lib/useAudioStore.ts into a plain TypeScript PulseEngine class. Strip Vue refs / Pinia plumbing. Re-publish the same actions (toggle, next, prev, loadTrack, seek, setAudioTracks, dispose) and the typed event bus (subscribe<E>).
  • @pulse-music/tokens — move src/lib/shared/variants.css here verbatim. Add base.css (the --pulse-scale system, shadows) and animations.css (the @keyframes from MusicPlayer.vue / MiniPlayer.vue).
  • Add Vitest tests against @pulse-music/core (port the existing tests in tests/useAudioStore.test.ts).
  • Validation gate: @pulse-music/vue's useAudioStore continues to import from the local file (no change for the demo).

Phase 2 — Web Component renderer (v3.0.0-alpha.2)

  • @pulse-music/web-component — write the Lit-based <pulse-player> and <pulse-fab> Custom Elements. Markup, CSS variables, animations — all copied from the validated v2.3.4 MusicPlayer.vue / MiniPlayer.vue. Lit reactive controllers replace Vue refs.
  • Set up Playwright visual regression: render the v2.3.4 demo, render an equivalent page built on <pulse-player>, diff at the pixel level. Goal: zero meaningful diff.
  • Add browser support note: Lit needs Custom Elements v1 (every evergreen browser since 2018) + ES2019.

Phase 3 — Vue refactor (v3.0.0-alpha.3)

  • @pulse-music/vue becomes a thin adapter: <MusicPlayer /> and <MiniPlayer /> now embed <pulse-player> and <pulse-fab> from @pulse-music/web-component instead of owning their own template. useAudioStore() projects @pulse-music/core's state into a Pinia store for API parity.
  • Move src/lib/* into packages/vue/src/ and update the import paths in the demo.
  • Visual regression must show zero pixel diff against tagged v2.3.4. If anything moves, the refactor blocks until it's identical.
  • v2.3.4 stays tagged on main so downstream users can pin to it during their own migration.

Phase 4 — React (v3.0.0-alpha.4)

  • @pulse-music/react<PulsePlayer />, <PulseFab />, usePulseAudio(). ~80 LOC each.
  • apps/demo-react/ — equivalent of the Vue demo, same scenario, same scripted tour.
  • Examples ported from examples/ to examples/react-*/.

Phase 5 — React Native (v3.0.0-alpha.5)

  • @pulse-music/react-native — separate renderer using React Native primitives. Audio engine wraps react-native-audio-api (Swansion) for AnalyserNode compatibility.
  • apps/demo-react-native/ — Expo demo.
  • Document feature parity matrix honestly. Drag-to-resize is dropped (no DOM resize concept on mobile native).

Phase 6 — Public release (v3.0.0)

  • All four primary wrappers stable: Vue, React, Web Components (direct), React Native.
  • npm publish for every package under @pulse-music/ scope.
  • GitHub Pages docs site published.

Phase 7 — Long tail (v3.1.x, v3.2.x)

  • @pulse-music/angular (v3.1.0)
  • @pulse-music/svelte (v3.1.0)
  • @pulse-music/solid (v3.2.0)
  • Future: Qwik, Lit re-export, vanilla JS examples.

Non-goals (deliberately not pursued)

  • Flutter / Swift / Kotlin native ports. The audio engine surface alone would take more effort than the rest of the project combined.
  • A jQuery wrapper. The Custom Elements work directly in any DOM.
  • A "no-build" CDN bundle. The library mode build already targets that use case (<script type="module" src="https://unpkg.com/@pulse-music/web-component">).

Why this sequence

Each phase ships a shippable artefact without breaking previous phases:

  • The Vue demo continues to render identically through phases 0–3 because the visual regression gate enforces zero diff.
  • Each new framework wrapper is additive — it doesn't touch the others.
  • React Native is last among the primary targets because its renderer is the most foreign, and waiting until everything else is stable means we can borrow architecture patterns from the other wrappers.