Handles media-heavy Hotwire features: image/video/audio uploads, previews, playback controls, progress tracking, galleries, carousels, and third-party integrations (WaveSurfer, Swiper, Picture-in-Picture, Blurhash). Use when the core problem is media rendering, playback state, audio/video player, file preview, carousel, gallery, waveform display, or media library integration. Cross-references: turbo-streams for server-pushed updates, hotwire-forms for upload forms, stimulus-controllers for non-media controller patterns.
How this skill is triggered — by the user, by Claude, or both
Slash command
/hotwire-frontend-skills:media-contentThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Implement media-centric Hotwire features with Stimulus and Turbo Frames. This skill covers upload previews, playback controls, progress persistence, and third-party media library integrations.
Implement media-centric Hotwire features with Stimulus and Turbo Frames. This skill covers upload previews, playback controls, progress persistence, and third-party media library integrations.
| Mode | Examples | Key Concern |
|---|---|---|
| Upload/Preview | Image preview before submit, file validation | Blob URL lifecycle |
| Playback controls | Video player, audio waveform, Picture-in-Picture | Browser API integration |
| Progress persistence | Video progress tracker, bookmark position | State serialization |
| Library integration | WaveSurfer, Swiper, Blurhash | Third-party lifecycle |
| Time-synced content | Scrolling lyrics, chaptered video | Frame update timing |
Bridge third-party APIs through value callbacks and targets. The controller owns the state; the library renders it. Declare static values for media state (currentTime, playing, volume) and use valueChanged callbacks to sync with the player API.
Prefer native APIs before reaching for libraries:
URL.createObjectURL() for file previewsIntersectionObserver for lazy media loadingMediaSession API for playback metadataMedia controllers allocate heavy resources. Every connect() must have a matching disconnect():
Save playback progress, marker positions, or user preferences deliberately. Reconcile stored state on reconnection — do not blindly restore stale state.
Revoke blob URLs after image/file preview rendering.
// GOOD
const url = URL.createObjectURL(file)
img.src = url
img.onload = () => URL.revokeObjectURL(url)
// BAD — memory leak
img.src = URL.createObjectURL(file)
Feature-detect browser APIs (PiP/Web Share/MediaSession). Hide UI for unsupported APIs.
// GOOD: Feature-detect before exposing UI
connect() {
this.pipButtonTarget.hidden = !document.pictureInPictureEnabled
}
// BAD: Assume API exists
connect() {
this.playerTarget.requestPictureInPicture()
}
Do not mix transport concerns with rendering. Media rendering belongs here; stream orchestration belongs in turbo-streams.
Keep frame updates incremental for time-based UI (lyrics, carousels, progress widgets). Do not replace the entire container on each tick.
Clean up third-party library instances in disconnect(). WaveSurfer, Swiper, and similar libraries hold references that must be explicitly destroyed.
// GOOD: Destroy on disconnect
disconnect() {
this.wavesurfer?.destroy()
this.wavesurfer = null
}
// BAD: No cleanup — memory leak and stale event listeners
disconnect() {
// nothing
}
| Topic | File |
|---|---|
| Upload previews (blob URLs) | references/image-upload-previews.md |
| Progressive loading (Blurhash) | references/progressive-image-loading-blurhash.md |
| Picture-in-Picture | references/picture-in-picture.md |
| Video progress persistence | references/video-progress-tracker.md |
| WaveSurfer markers | references/wavesurfer-markers.md |
| Time-synced lyrics | references/scrolling-lyrics.md |
| Carousel (Swiper) | references/swiper-integration.md |
Full catalog: references/INDEX.md.
Out-of-scope requests: route back to frontend-craft for triage.
npx claudepluginhub ether-moon/hotwire-frontend-skills --plugin hotwire-frontend-skillsProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.