Update docs, examples, and version for v2.3.0

- Bump package.json and Webamp.VERSION to 2.3.0
- Move changelog Unreleased items into 2.3.0 section
- Update "unreleased" references in docs to v2.3.0
- Switch all examples from renderWhenReady to renderInto
- Update multipleMilkdropPresets to use stable @^2 instead of @next
- Update lazy example to webamp@^2.3.0
- Update release skill with version bump and changelog steps

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jordan Eldredge 2026-06-15 20:42:10 -07:00
parent d7b0cee444
commit 6c3dd2a793
17 changed files with 63 additions and 115 deletions

View file

@ -0,0 +1,23 @@
---
name: release
description: Cut a new webamp npm release
---
# Release webamp to npm
## Steps
1. Create and push a git tag: `git tag v{X.Y.Z} && git push origin v{X.Y.Z}`
2. CI (`.github/workflows/ci.yml`) builds, tests, publishes
3. Monitor: `gh run list --limit 3` then `gh run watch <id> --exit-status`
4. Verify: `npm view webamp versions --json | tail -5`
## How it works
- Bump `version` in `packages/webamp/package.json` and `Webamp.VERSION` in `packages/webamp/js/webampLazy.tsx` to match the new version
- Don't bump ani-cursor or winamp-eqf versions — CI sets those from the git tag
- All 3 packages (webamp, ani-cursor, winamp-eqf) get the same version
- Tagged releases publish to `latest`; master pushes publish `0.0.0-next-{sha}` to `next`
- Uses npm provenance (OIDC)
## Post-release
- Update changelog: move "Unreleased" items into a new versioned section, then comment out the Unreleased section (`<!-- ... -->`)
- Update docs (features reference version numbers — replace "unreleased" with the new version)

View file

@ -7,7 +7,7 @@
<title>Webamp</title>
</head>
<body>
<div id="app"></div>
<div id="app" style="height: 100vh; position: relative"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View file

@ -17,6 +17,6 @@
"butterchurn-presets": "3.0.0-beta.4",
"jszip": "^3.10.1",
"music-metadata": "^11.6.0",
"webamp": "^2.2.0"
"webamp": "^2.3.0"
}
}

View file

@ -54,4 +54,4 @@ const webamp = new Webamp({
},
});
webamp.renderWhenReady(document.getElementById("app")!);
webamp.renderInto(document.getElementById("app")!);

View file

@ -6,8 +6,8 @@
</head>
<body>
<div id="app" style="height: 100vh">
<!-- Webamp will attempt to center itself within this div -->
<div id="app" style="height: 100vh; position: relative">
<!-- Webamp will render as a child of this div -->
</div>
<script type="module">
import Webamp from "https://unpkg.com/webamp@^2/butterchurn";
@ -35,7 +35,7 @@
],
});
webamp.renderWhenReady(document.getElementById("app"));
webamp.renderInto(document.getElementById("app"));
</script>
</body>
</html>

View file

@ -6,8 +6,8 @@
</head>
<body>
<div id="app" style="height: 100vh">
<!-- Webamp will attempt to center itself within this div -->
<div id="app" style="height: 100vh; position: relative">
<!-- Webamp will render as a child of this div -->
</div>
<script type="module">
/**
@ -31,7 +31,7 @@
},
],
});
webamp.renderWhenReady(document.getElementById("app"));
webamp.renderInto(document.getElementById("app"));
</script>
</body>
</html>

View file

@ -6,8 +6,8 @@
</head>
<body>
<div id="app" style="height: 100vh">
<!-- Webamp will attempt to center itself within this div -->
<div id="app" style="height: 100vh; position: relative">
<!-- Webamp will render as a child of this div -->
</div>
<script type="module">
import Webamp from "https://unpkg.com/webamp@^2";
@ -34,7 +34,7 @@
});
// Returns a promise indicating when it's done loading.
webamp.renderWhenReady(document.getElementById("app"));
webamp.renderInto(document.getElementById("app"));
</script>
</body>
</html>

View file

@ -6,13 +6,11 @@
</head>
<body>
<div id="app" style="height: 100vh">
<!-- Webamp will attempt to center itself within this div -->
<div id="app" style="height: 100vh; position: relative">
<!-- Webamp will render as a child of this div -->
</div>
<script type="module">
// The `requireButterchurnPresets` config option is not yet available in a stable release.
// for now you need to install a pre-release version of Webamp to use it.
import Webamp from "https://unpkg.com/webamp@0.0.0-next-41cfbbb/butterchurn";
import Webamp from "https://unpkg.com/webamp@^2/butterchurn";
const webamp = new Webamp({
initialTracks: [
{
@ -39,7 +37,7 @@
});
// Returns a promise indicating when it's done loading.
webamp.renderWhenReady(document.getElementById("app"));
webamp.renderInto(document.getElementById("app"));
</script>
</body>
</html>

View file

@ -6,8 +6,8 @@
</head>
<body>
<div id="app" style="height: 100vh">
<!-- Webamp will attempt to center itself within this div -->
<div id="app" style="height: 100vh; position: relative">
<!-- Webamp will render as a child of this div -->
</div>
<script type="module">
import Webamp from "https://unpkg.com/webamp@^2";
@ -51,7 +51,7 @@
});
// Returns a promise indicating when it's done loading.
webamp.renderWhenReady(document.getElementById("app"));
webamp.renderInto(document.getElementById("app"));
</script>
</body>
</html>

View file

@ -6,8 +6,8 @@
</head>
<body>
<div id="app" style="height: 100vh">
<!-- Webamp will attempt to center itself within this div -->
<div id="app" style="height: 100vh; position: relative">
<!-- Webamp will render as a child of this div -->
</div>
<script type="module">
import Webamp from "https://unpkg.com/webamp@^2";
@ -56,7 +56,7 @@
});
// Returns a promise indicating when it's done loading.
webamp.renderWhenReady(document.getElementById("app"));
webamp.renderInto(document.getElementById("app"));
</script>
</body>
</html>

View file

@ -13,7 +13,7 @@ Create a DOM element somewhere in your HTML document. This will be used by Webam
:::tip
**Webamp will not actually insert itself as a child of this element.** It will will insert itself as a child of the body element, and will attempt to center itself within this element. This is needed to allow the various Webamp windows to dragged around the page unencumbered.
If you want Webamp to be a child of a specific element, use the [`renderInto(domNode)`](./06_API/03_instance-methods.md#renderintodomnode-htmlelement-promisevoid) method instead _(available in unreleased version)_. Note that the target element must have a non-static CSS position (e.g., `position: relative`) for this to work correctly.
If you want Webamp to be a child of a specific element, use the [`renderInto(domNode)`](./06_API/03_instance-methods.md#renderintodomnode-htmlelement-promisevoid) method instead _(since v2.3.0)_. Note that the target element must have a non-static CSS position (e.g., `position: relative`) for this to work correctly.
:::
## Initialize Webamp instance

View file

@ -257,7 +257,7 @@ const webamp = new Webamp({
### `requireButterchurnPresets?: () => Promise<Preset[]>`
**Since** [unreleased](../12_changelog.md#unreleased)
**Since** [v2.3.0](../12_changelog.md#230)
Milkdrop (Butterchurn) presets to be used. If not specified, the default presets
included in the bundle will be used.

View file

@ -239,7 +239,7 @@ Webamp will wait until it has fetched the skin and fully parsed it, and then ren
A promise is returned which will resolve after the render is complete.
**Since** [Unreleased](../12_changelog.md#unreleased)
**Since** [v2.3.0](../12_changelog.md#230)
```ts
const container = document.getElementById("webamp-container");

View file

@ -1,5 +1,6 @@
# Changelog
<!--
## Unreleased
_These changes are not yet published to NPM with an official version number._
@ -7,6 +8,13 @@ _These changes are not yet published to NPM with an official version number._
:::tip
If you want access to the changes in this section before they are officially released you can do `npm install webamp@next`, or use it via CDN at `https://unpkg.com/webamp@next`.
:::
-->
## 2.3.0
:::info
This is the current version of Webamp.
:::
### Improvements
@ -20,10 +28,6 @@ If you want access to the changes in this section before they are officially rel
## 2.2.0
:::info
This is the current version of Webamp.
:::
### Improvements
- Added new [`webamp/butterchurn`](./06_API/00_entrypoints.md#webampbutterchurn) entrypoint which includes Milkdrop window by default. This is the recommended entrypoint for users who want a fully featured Webamp and are not particularly concerned about bundle size.

View file

@ -48,7 +48,7 @@ export interface InjectableDependencies {
}
class Webamp {
static VERSION = "2.2.0";
static VERSION = "2.3.0";
_actionEmitter: Emitter;
_root: ReactDOM.Root | null;
_disposable: Disposable;

View file

@ -1,6 +1,6 @@
{
"name": "webamp",
"version": "2.2.0",
"version": "2.3.0",
"description": "Winamp 2 implemented in HTML5 and JavaScript",
"files": [
"built",

87
pnpm-lock.yaml generated
View file

@ -89,8 +89,8 @@ importers:
specifier: ^11.6.0
version: 11.6.0
webamp:
specifier: ^2.2.0
version: 2.2.0(@types/react-dom@18.2.24)(@types/react@18.2.74)
specifier: ^2.3.0
version: 2.3.0
devDependencies:
typescript:
specifier: ~5.8.3
@ -3126,11 +3126,6 @@ packages:
engines: {node: '>=18'}
hasBin: true
'@redux-devtools/extension@3.3.0':
resolution: {integrity: sha512-X34S/rC8S/M1BIrkYD1mJ5f8vlH0BDqxXrs96cvxSBo4FhMdbhU+GUGsmNYov1xjSyLMHgo8NYrUG8bNX7525g==}
peerDependencies:
redux: ^3.1.0 || ^4.0.0 || ^5.0.0
'@remix-run/router@1.5.0':
resolution: {integrity: sha512-bkUDCp8o1MvFO+qxkODcbhSqRa6P2GXgrGZVpt0dCXNW2HCSCqYI0ZoAqEOSAjRWmmlKcYgFvN4B4S+zo/f8kg==}
engines: {node: '>=14'}
@ -4420,9 +4415,6 @@ packages:
resolution: {integrity: sha512-84xBncKNPBK8Ae89F65+SyVcOihrIbm/3N7to+GpRBHEUXGjA3ydWTMpcRW6jmFzkBQ/eqYy/y+J+NBpJWYjBg==}
engines: {node: '>= 14.0.0'}
ani-cursor@0.0.5:
resolution: {integrity: sha512-gGxst72lG9TOwEfbVpX9vHhzUGw+4Ee2XB6AfYq5JP+bxBtpAjgnTBepCVxYF5t1TPrWHN23nWqLTflJOA3/ag==}
ansi-align@3.0.1:
resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==}
@ -7098,9 +7090,6 @@ packages:
fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
fscreen@1.2.0:
resolution: {integrity: sha512-hlq4+BU0hlPmwsFjwGGzZ+OZ9N/wq9Ljg/sq3pX+2CD7hrJsX9tJgWWK/wiNTFM212CLHWhicOoqwXyZGGetJg==}
fsevents@2.1.3:
resolution: {integrity: sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@ -7715,9 +7704,6 @@ packages:
immediate@3.0.6:
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
immutable@4.3.7:
resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==}
import-cwd@3.0.0:
resolution: {integrity: sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==}
engines: {node: '>=8'}
@ -11277,11 +11263,6 @@ packages:
redux-sentry-middleware@0.1.8:
resolution: {integrity: sha512-xubpYH9RgE31tZUESeRW5agwQa19Yd6Gy+4iO09raW/2TITPO5fhJdXpVwJfpGMbIYhEmHFqE2wD5Lnz7YtAeA==}
redux-thunk@2.4.2:
resolution: {integrity: sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==}
peerDependencies:
redux: ^4
redux-thunk@3.1.0:
resolution: {integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==}
peerDependencies:
@ -12456,9 +12437,6 @@ packages:
resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
engines: {node: ^18.0.0 || >=20.0.0}
tinyqueue@1.2.3:
resolution: {integrity: sha512-Qz9RgWuO9l8lT+Y9xvbzhPT2efIUIFd69N7eF7tJ9lnQl0iLj1M7peK7IoUGZL9DJHw9XftqLreccfxcQgYLxA==}
tinyqueue@3.0.0:
resolution: {integrity: sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==}
@ -13230,8 +13208,8 @@ packages:
web-vitals@0.2.4:
resolution: {integrity: sha512-6BjspCO9VriYy12z356nL6JBS0GYeEcA457YyRzD+dD6XYCQ75NKhcOHUMHentOE7OcVCIXXDvOm0jKFfQG2Gg==}
webamp@2.2.0:
resolution: {integrity: sha512-XzKr65Z4d+4rxA1J//aPkZRqvPS0aqAxpryNKaWt/EDQ4uCJadxjr966QElagH+iZxWMCDekW5dV/dTx5b+WPQ==}
webamp@2.3.0:
resolution: {integrity: sha512-boxinZWebj6jd5y82ot0xBqBJsKeyBY6uIBMdcZ7XwhRkm+q67dCnxbt939fEvRQjx4IQ3PLHEu+R968NIkQJw==}
webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
@ -13357,9 +13335,6 @@ packages:
wildcard@2.0.1:
resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==}
winamp-eqf@1.0.0:
resolution: {integrity: sha512-yUIb4+lTYBKP4L6nPXdDj1CQBXlJ+/PrNAkT1VbTAgeFjX8lPxAthsUE5NxQP4s8SO4YMJemsrErZ49Bh+/Veg==}
winston-transport@4.7.0:
resolution: {integrity: sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==}
engines: {node: '>= 12.0.0'}
@ -16695,12 +16670,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@redux-devtools/extension@3.3.0(redux@5.0.1)':
dependencies:
'@babel/runtime': 7.27.6
immutable: 4.3.7
redux: 5.0.1
'@remix-run/router@1.5.0': {}
'@remix-run/server-runtime@1.15.0':
@ -18294,11 +18263,6 @@ snapshots:
'@algolia/requester-fetch': 5.32.0
'@algolia/requester-node-http': 5.32.0
ani-cursor@0.0.5:
dependencies:
byte-data: 18.1.1
riff-file: 1.0.3
ansi-align@3.0.1:
dependencies:
string-width: 4.2.3
@ -21496,8 +21460,6 @@ snapshots:
fs.realpath@1.0.0: {}
fscreen@1.2.0: {}
fsevents@2.1.3:
optional: true
@ -22388,8 +22350,6 @@ snapshots:
immediate@3.0.6: {}
immutable@4.3.7: {}
import-cwd@3.0.0:
dependencies:
import-from: 3.0.0
@ -26804,10 +26764,6 @@ snapshots:
redux-sentry-middleware@0.1.8: {}
redux-thunk@2.4.2(redux@5.0.1):
dependencies:
redux: 5.0.1
redux-thunk@3.1.0(redux@5.0.1):
dependencies:
redux: 5.0.1
@ -28315,8 +28271,6 @@ snapshots:
tinypool@1.1.1: {}
tinyqueue@1.2.3: {}
tinyqueue@3.0.0: {}
tinyrainbow@2.0.0: {}
@ -29176,36 +29130,7 @@ snapshots:
web-vitals@0.2.4: {}
webamp@2.2.0(@types/react-dom@18.2.24)(@types/react@18.2.74):
dependencies:
'@redux-devtools/extension': 3.3.0(redux@5.0.1)
'@sentry/browser': 5.9.1
ani-cursor: 0.0.5
butterchurn: 3.0.0-beta.5(patch_hash=dn4lya4siqyl4wmtq4serjeoma)
butterchurn-presets: 3.0.0-beta.4
classnames: 2.5.1
fscreen: 1.2.0
invariant: 2.2.4
jszip: 3.10.1
lodash: 4.17.21
milkdrop-preset-converter-aws: 0.1.6
music-metadata: 11.6.0
music-metadata-browser: 0.6.6
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
react-redux: 8.1.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(redux@5.0.1)
redux: 5.0.1
redux-sentry-middleware: 0.1.8
redux-thunk: 2.4.2(redux@5.0.1)
reselect: 3.0.1
strtok3: 10.3.1
tinyqueue: 1.2.3
winamp-eqf: 1.0.0
transitivePeerDependencies:
- '@types/react'
- '@types/react-dom'
- react-native
- supports-color
webamp@2.3.0: {}
webidl-conversions@3.0.1: {}
@ -29422,8 +29347,6 @@ snapshots:
wildcard@2.0.1: {}
winamp-eqf@1.0.0: {}
winston-transport@4.7.0:
dependencies:
logform: 2.6.0