# Sleep Meditation — Technical Documentation ## Scope This project provides a static web app in a container that plays MP3 audio on desktop and mobile, including iPhone lock-screen controls. ## Architecture - Service: `sleep-meditation` - Runtime: `nginx:alpine` - App: static frontend (`index.html`, `styles.css`, `app.js`) - MP3 source: mounted host volume at `/usr/share/nginx/html/mp3` ## iPhone background playback Important on iOS: - Autoplay without user interaction is blocked. - The user must start playback manually at least once. - After playback starts, audio usually continues when the screen is locked. - Media Session API enables lock-screen controls for play/pause/track skip. ## Player controls - `Previous`: go to previous track (clamped at first track) - `Play/Pause`: toggle playback - `Next`: go to next track (clamped at last track) - `Back to start`: select first track, reset position to `0:00`, no autoplay When a track ends: - If there is a next track, it starts automatically. - If the last track ends, playback stops (no loop). ## File overview ``` containers/sleep-meditation/ Dockerfile nginx.conf site/ index.html styles.css app.js manifest.webmanifest service-worker.js mp3/playlist.json stack/ stack.yml sleep-meditation.env ``` ## Track loading behavior The app loads tracks in this order: 1. `/mp3/playlist.json` 2. Auto-discovery from `/mp3/` directory listing (Nginx `autoindex on`) 3. Built-in fallback track (`/mp3/example.mp3`) ## Playlist contract File: `/mp3/playlist.json` ```json [ { "title": "Track name", "artist": "Artist", "src": "/mp3/track.mp3" } ] ``` Rules: - `title` optional (derived from filename if omitted) - `artist` optional - `src` required; absolute path within web root (`/mp3/...`) or relative filename ## Container healthcheck - Endpoint: `GET /` - Expected: HTTP 200 - Configured in Dockerfile with `wget`