No description
  • JavaScript 30.1%
  • Shell 28.7%
  • Python 24%
  • CSS 9.9%
  • HTML 5.9%
  • Other 1.4%
Find a file
Ivo Oskamp a3debdb263 Per-env Traefik routing; downloader on its own hostname behind TinyAuth
Rename stack/docker-compose.yml to stack/compose.yaml per the stack
convention. The web player's router is now ${ENV}-sleep-meditation on
${DOMAIN} (was hardcoded "sleep" / sleep.oskamp.info); the downloader
gets its own ${ENV}-sleep-meditation-downloader router on
${DOWNLOADER_DOMAIN} behind TinyAuth. Published ports removed; both
services only on the proxy network.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 09:37:02 +00:00
containers Add AirPlay button, update build script to 1.7.0 2026-06-06 11:20:15 +02:00
docs Per-env Traefik routing; downloader on its own hostname behind TinyAuth 2026-09-23 09:37:02 +00:00
stack Per-env Traefik routing; downloader on its own hostname behind TinyAuth 2026-09-23 09:37:02 +00:00
.gitignore Add AirPlay button, update build script to 1.7.0 2026-06-06 11:20:15 +02:00
build-and-push.sh Migrate git + registry from Gitea to Forgejo 2026-06-21 19:38:09 +02:00
README.md Per-env Traefik routing; downloader on its own hostname behind TinyAuth 2026-09-23 09:37:02 +00:00

Sleep Meditation

Sleep Meditation is a self-hosted web player for MP3 files, optimized for mobile use.

Goal

A simple website that can play MP3 audio while an iPhone screen is locked, as long as playback is started manually (iOS limitation).

Features

  • Playlist through mp3/playlist.json
  • Automatic track discovery from /mp3/ when playlist.json is missing
  • Standard HTML5 audio player
  • Media Session API support (play/pause/next/previous on lock screen)
  • Playlist ends at the last track (no automatic loop)
  • Back to start button resets to track 1 without autoplay
  • Server-side audio download via URL (avoids browser timeout on long files)
  • Downloaded tracks stored in /mp3/downloads/, played individually (no auto-advance)
  • Track titles editable via Settings page (titles stored separately from filenames)
  • Rename and delete downloaded tracks via Settings
  • Two-page UI: player + settings (hash routing)
  • PWA manifest + service worker
  • Containerized with Nginx + Python API (supervisord)

Repository layout

  • containers/sleep-meditation/: web player Docker image, Nginx config, Python API, web app
  • containers/sleep-meditation-downloader/: downloader image (server-side track downloads)
  • stack/compose.yaml: Portainer/Compose stack (shared stack convention)
  • stack/stack.env: environment variables (documents what Portainer supplies)
  • docs/TECHNICAL.md: technical details and iPhone behavior

Deploy (Portainer)

The stack follows the shared stack convention: ENV (dev/prod) and IMAGE_TAG (dev/latest) select the environment, DOMAIN/DOWNLOADER_DOMAIN are the hostnames Traefik routes to the web player (public) and the downloader (behind TinyAuth, via TINYAUTH_MIDDLEWARE), and the mp3 folder is bind-mounted from /docker/appdata/${ENV}-sleep-meditation/mp3.

  1. Deploy stack/compose.yaml with the variables from stack/stack.env.
  2. Ensure /docker/appdata/<env>-sleep-meditation/mp3 exists on the host and holds the MP3 files (the container reads it at /usr/share/nginx/html/mp3).
  3. Optionally add playlist.json in that folder for custom ordering/metadata.
  4. Open https://${DOMAIN} and press Play manually once.

Playlist format

mp3/playlist.json

[
  {
    "title": "Deep Sleep Wave",
    "artist": "Sleep Meditation",
    "src": "/mp3/deep-sleep-wave.mp3"
  }
]

Download a track

Open Settings in the app, enter a direct audio URL and a title, then press Download. The file is downloaded server-side and saved to mp3/downloads/. It appears in the Downloads section on the main page.