Button: variantes subtle (primary/secondary, se mantienen iguales por decisión del usuario), glass (antes secondaryOnGlow, con font-normal propio), accent, strong (cta-strong/ink, sustituye los overrides `!` del hero de Inicio), danger. Usa los tokens --color-btn* de P1 en vez de bg-[var(--mf-btn-...)]. Radio unificado a rounded-control. IconButton: añade shape (square/round), size (xs/sm/md/lg), tone (muted/subtle/plain), pressed (aria-pressed + text-accent), href/reload (enlaces), surface (fondo permanente + hover a surface-hover en vez del alias `hover` genérico, que coincide con surface-2 y no daba contraste). PlayButton nuevo: un solo sitio para los SVG de play/pausa, variantes strong/glass, as="span" para overlays no interactivos. Sustituye el botón principal de TransportControls, el overlay de MixTile y el círculo de "Mejor resultado" en Explorar. Migra a IconButton: cerrar cola, "Crear playlist" (Sidebar), Me gusta (TrackInfo, con pressed), cola (PlayerExtras), atrás (TopBar), login (MobileHeader) y las acciones de fila en tablas (quitar/añadir, size xs). BackLink usa size-icon-sm y quita un hover duplicado. Decisión (sin bloquear): se elimina el botón "adelante" decorativo de TopBar y el icono AlignJustify decorativo de PlayerExtras (código muerto visual). Los botones de TransportControls (shuffle/prev/next/ repeat) se dejan sin migrar a propósito: hoy no tienen fondo ni hit-box propios y IconButton siempre aplica una caja de tamaño fijo — migrarlos habría añadido una píldora de hover visible no verificable sin Docker en esta sesión. Verificado con npm run check/build.
web-player
Musify's web client: SvelteKit 2 (adapter-node), Svelte 5 runes, Tailwind 4,
TypeScript. Authentication is server-side OIDC against Zitadel (openid-client
and jose) with an encrypted session cookie; the backend is called from load
functions and form actions through a typed openapi-fetch client.
Development
npm install
npm run dev # :5173
Configuration lives in .env (template in .env.example). Bring the
infrastructure stack up first (see ../deploy/README.md)
and copy the WEB_CLIENT_ID / WEB_CLIENT_SECRET it writes to deploy/.env
into this .env once, then run the dev server.
npm run check # svelte-check — must be clean before closing a change
npm run lint # prettier --check . && eslint .
npm run format # prettier --write .
npm run build # production build into build/
npm run gen:api # regenerate src/lib/api/schema.d.ts from the running API
Production
Built and run as a container by the production stack — see
../deploy/README.md. There the same variables come from
deploy/.env.prod through compose instead of from .env.
Conventions and the design system are documented in CLAUDE.md and
in the musify-web skill.