pay2play/README.md
Ole-Morten Duesund ffbe601cee Update README for 3-file structure and probe tool
Reflect the split into index.html/style.css/app.js, document the
probe-songs.py workflow and songs.json auto-loading, remove outdated
instructions about editing SONGS array in index.html.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:12:43 +01:00

4.6 KiB

Pay2Play! — The Worst Music Player

A satirical music player where every interaction is paywalled. Pause? That's $0.01. Resume? Separate charge. Turn off repeat? That costs more than turning it on.

Part of donothireus.com.

Quick start

No build step, no package manager. Just serve the public/ directory:

cd public/
python3 -m http.server 8080
# open http://localhost:8080

Or with any other static file server (Caddy, nginx, etc).

Project structure

public/
├── index.html          # HTML shell, CDN script tags, meta/OG tags
├── style.css           # Animations, hover/focus states, range styling
├── app.js              # All React components and logic (JSX via Babel)
└── audio/              # Drop MP3 files here for real music
    ├── songs.json      # Generated by tools/probe-songs.py (gitignored)
    └── .gitkeep
tools/
└── probe-songs.py      # Probe audio files → songs.json

Deploying to donothireus.com

Just serve the public/ directory. If you're using Caddy (which I know you are), something like:

donothireus.com {
    root * /srv/donothireus/public
    file_server
    encode gzip
}

Or to put it at a subpath like /payplay:

donothireus.com {
    handle /payplay/* {
        root * /srv/donothireus/payplay/public
        uri strip_prefix /payplay
        file_server
    }
}

Audio: procedural vs real music

By default the player uses Tone.js to generate procedural synth loops — no external audio files needed. This is funny on its own ("even the songs are cheaply made") but you can swap in real CC-licensed tracks.

Switching to self-hosted MP3s

  1. Download CC-BY licensed MP3s (see sources below)
  2. Put them in public/audio/
  3. Run the probe tool to generate songs.json:
./tools/probe-songs.py -d public/audio
# Writes public/audio/songs.json automatically

The app fetches audio/songs.json on startup. If it exists and contains tracks, they replace the procedural builtins. If not, the synth songs are used as a fallback.

The generated JSON looks like:

[
  {
    "title": "Sneaky Snitch",
    "artist": "Kevin MacLeod",
    "duration": 120,
    "url": "/audio/sneaky-snitch.mp3",
    "color": "#e74c3c"
  }
]

Title and artist are extracted from ID3 tags when available, falling back to the filename. Duration comes from ffprobe.

You can also probe specific files or write to a custom path:

./tools/probe-songs.py public/audio/track1.mp3 public/audio/track2.mp3
./tools/probe-songs.py -o public/audio/songs.json *.mp3

Where to get CC-BY music

All of these are free to use with attribution (CC-BY or CC0):

Kevin MacLeod / Incompetech (CC-BY 4.0)

Free Music Archive (various CC licenses — filter for CC-BY)

SampleSwap (CC-BY-NC-SA for most tracks)

Pixabay Music (Pixabay License — free, no attribution required)

Download and host workflow

# Example: grab a Kevin MacLeod track
cd public/audio/
wget -O sneaky-snitch.mp3 "https://incompetech.com/music/royalty-free/mp3-royaltyfree/Sneaky%20Snitch.mp3"

# Generate songs.json from all audio in the directory
cd ../..
./tools/probe-songs.py -d public/audio

Attribution

If using CC-BY music, add attribution. The fine print at the bottom of the player is a good place, or add a separate credits section. Kevin MacLeod's required format:

"Track Title" Kevin MacLeod (incompetech.com) Licensed under Creative Commons: By Attribution 4.0 https://creativecommons.org/licenses/by/4.0/

How it works

  • React 18 loaded from CDN, JSX compiled by Babel standalone
  • Tone.js for procedural synth audio (no build step needed)
  • HTML5 Audio API for self-hosted MP3 playback
  • Zero dependencies to install, zero build tools
  • All state is client-side, nothing persisted

The starting wallet is randomized between $0.50 and $10.00 each page load. The +$10 button lets people keep exploring all the paywalls (with a $0.50 processing fee, naturally).

License

Do whatever you want with this. It's a joke.