# Frontend dependency management

MPV Manager keeps its Web UI fully local and offline-capable. htmx and
Alpine.js are declared as exact npm dependencies, then their upstream browser
distributions are copied into `internal/webassets/static/js/` for Go's
`embed` package. The application never loads these libraries from a CDN and
does not need Node.js at runtime.

## Current runtime libraries

| Library | Version | npm package | Embedded file | License |
|---|---:|---|---|---|
| htmx | 2.0.10 | `htmx.org` | `static/js/htmx.min.js` | 0BSD |
| Alpine.js | 3.17.1 | `alpinejs` | `static/js/alpine.min.js` | MIT |

`package.json` and `package-lock.json` are the version and integrity sources
of truth. `scripts/sync-frontend-vendor.mjs` performs byte-for-byte copies from
the installed packages. CI runs its check mode so a dependency bump cannot be
merged with stale embedded assets.

## Install, build, and verify

```bash
# Reproduce the locked dependency tree
npm ci

# Synchronize htmx and Alpine, then rebuild Tailwind
make frontend

# Verify committed browser files match node_modules byte for byte
make frontend-vendor-check

# Test and audit the complete frontend dependency tree
npm test
npm audit --package-lock-only --audit-level=high
```

The committed browser files allow ordinary Go builds to continue without
Node.js. Node.js 22.12+ (or supported newer LTS/current) and npm are required when changing, testing, or auditing
frontend code or dependencies.

## Updating a library

1. Review the upstream changelog and migration guidance.
2. Install the chosen versions exactly, for example:
   `npm install --save-exact htmx.org@2.0.10 alpinejs@3.17.1`.
3. Run `npm run vendor:frontend` and review both the lockfile and browser-file
   diffs.
4. Run `npm outdated`, `npm audit --package-lock-only --audit-level=high`,
   `npm test`, and the relevant browser route regressions.
5. Update this document and `docs/THIRD_PARTY_NOTICES.md` when versions or
   licenses change.

Atlas reads the npm manifests as part of `atlas outdated` and
`atlas security`, so these libraries now participate in the same dependency
tracking as the Go and frontend build dependencies.

## 2026-08-31 Alpine.js review

### Alpine.js 3.16.3 to 3.17.1

The official [3.17.0](https://github.com/alpinejs/alpine/releases/tag/v3.17.0)
and [3.17.1](https://github.com/alpinejs/alpine/releases/tag/v3.17.1)
notes describe a CSP string-literal fix, the opt-in `Alpine.deferInit()` API,
intersect-plugin dwell timing, documentation, and build-dependency maintenance.
MPV Manager uses Alpine core but does not use `deferInit` or the intersect
plugin. The exact npm pin, synchronized `cdn.min.js`, 180 frontend assertions,
npm audit, vendor byte comparison, and Tailwind freshness check all pass.

## 2026-08-28 patch review

### htmx 2.0.8 to 2.0.10

The [official htmx changelog](https://github.com/bigskysoftware/htmx/blob/master/CHANGELOG.md)
lists only compatible fixes in these two releases:

- 2.0.9 corrects `HX-Location` replace behavior and relative history paths,
  removes empty class attributes after htmx state classes, preserves controls
  that were disabled before `hx-disabled-elt`, and adds the failed selector to
  `htmx:oobErrorNoTarget` details.
- 2.0.10 restores an accidentally omitted TypeScript declaration and uses
  `CSS.escape()` more consistently when locating elements during settle.

MPV Manager does not use `HX-Location`, htmx-managed history, `hx-disabled-elt`,
or TypeScript declarations. It does use out-of-band swaps and programmatic
`htmx.ajax()` calls, so the improved OOB diagnostics and safer settle lookup
are beneficial. Existing OOB, refresh, response-error, and route regressions
remain the acceptance gate.

### Alpine.js 3.16.2 to 3.16.3

The [official Alpine.js 3.16.3 release](https://github.com/alpinejs/alpine/releases/tag/v3.16.3)
contains an `x-mask` plugin fix, an `x-modelable` documentation clarification,
and an upstream PostCSS build-dependency update. MPV Manager does not load the
mask plugin or use `x-mask`/`x-modelable`. Its core `cdn.min.js` is byte-for-byte
identical to 3.16.2 after normalizing the embedded version string, so this is a
metadata-only runtime update for the directives used here (`x-data`, `x-model`,
`x-show`, and related core behavior).

## Browser integration tooling

The Tailwind 4.3.3 CLI's watcher is narrowly overridden to
`@parcel/watcher` 2.6.0 in `package.json`. The newer watcher uses `picomatch`
instead of `micromatch`/`braces`, removing the chain affected by
[GHSA-vfj7-8cjw-p6xm](https://github.com/advisories/GHSA-vfj7-8cjw-p6xm).
Tailwind itself stays at the locked version. The
[watcher release](https://github.com/parcel-bundler/watcher/releases/tag/v2.6.0)
retains the subscription API and adds regular-expression ignores. Lockfile
installation, CSS generation and incremental watch behavior are checked alongside
the normal frontend and browser gates. Reassess this scoped override when
Tailwind updates its pinned watcher; do not suppress the npm audit gate.

`@playwright/test` is an exact development dependency for `npm run test:browser`.
Its Chromium download is used only for QA and CI; it is not embedded in the
application. Vitest 5 remains the unit/factory test runner. The browser suite
uses a Go test binary supplied by `test:linux` in CI and runs the same fixtures
natively on Windows and macOS. See [Testing](TESTING.md#browser-job-and-lifecycle-integration).
