add default album art; allow overriding
Hunter
Sunday, May 3rd, 2026 at 10:46 PM
141 "resources/script.js",
142 "mix/tracks.json",
143 "resources/icon.png",
144 + "resources/album_art.jpg",
145 "resources/play.svg",
146 "resources/pause.svg",
147 "resources/prev.svg",
5 supported formats: `.mp3`, `.m4a`, `.ogg`, `.flac`, `.wav`
6
7 ## optional files
-- `album_art.jpg` - cover art for your mix
8 - `custom.css` - custom styles to override the default theme
9 - `custom.js` - custom scripts for additional functionality
10 +- `album_art.jpg` - cover art for your mix (overrides the default in `/resources`)
66 (pictured: integration with iOS lockscreen controls)
67
68 ## customization
-add `custom.css`, `custom.js` and/or `album_art.jpg` to `/mix` to customize your mixapp's appearance and behavior. these files are automatically loaded if present.
69 +add your own `custom.css`, `custom.js`, and/or `album_art.jpg` to `/mix` to customize your mixapp's appearance and behavior.
70
71 ## intellectual property notice
72 ensure you have the right to distribute any media files you include in public mixapps. personal archival backups are for your own use. sharing them with others, even as a gift, is not covered by fair use or backup exceptions.
Binary files differ.
75 let totalBytesLoaded = 0; // Track total filesize of all preloaded tracks
76 let cachedTracks = new Set(); // Track which tracks are cached for offline use
77 let CACHE_NAME = 'my-mixapp'; // Default fallback
78 +let hasCustomAlbumArt = false;
79 const staticFiles = [
80 './',
81 'index.html',
83 'resources/script.js',
84 'mix/tracks.json',
85 'resources/icon.png',
86 + 'resources/album_art.jpg',
87 'resources/play.svg',
88 'resources/pause.svg',
89 'resources/prev.svg',
138 return Promise.all([
139 ...optionalFiles.map(f =>
140 fetch(f, { method: 'HEAD' })
- .then(r => { if (r.ok) staticFiles.push(f); })
141 + .then(r => {
142 + if (r.ok) {
143 + staticFiles.push(f);
144 + if (f === 'mix/album_art.jpg') hasCustomAlbumArt = true;
145 + }
146 + })
147 .catch(() => {})
148 ),
149 fetch('mix/tracks.json')
209 if ('mediaSession' in navigator) {
210 // Convert relative path to absolute URL for media session
211 // Use document.baseURI to correctly resolve paths in subdirectories
- const albumArtUrl = new URL('mix/album_art.jpg', document.baseURI).href;
212 + const albumArtPath = hasCustomAlbumArt ? 'mix/album_art.jpg' : 'resources/album_art.jpg';
213 + const albumArtUrl = new URL(albumArtPath, document.baseURI).href;
214 navigator.mediaSession.metadata = new MediaMetadata({
215 title: track.title,
216 artist: track.artist,