This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This repository contains the "Everything is Free" music album by Software-Entwicklungskit. The project is organized as a collection of audio tracks named after alkali metals (Group 1 elements of the periodic table), each with associated artwork and individual audio stems.
ev3/
├── .github/
│ └── copilot-instructions.md (GitHub Copilot/AI agent guidance)
├── src/
│ ├── 1.Hydrogen/
│ │ ├── README.md
│ │ └── artwork/ (Track-specific artwork with dimensions in filenames)
│ ├── 2.Lithium/
│ ├── 3.Sodium/
│ ├── 4.Potassium/
│ ├── 5.Rubidium/
│ ├── 6.Caesium/
│ ├── 7.Francium/
│ ├── workers/
│ │ ├── everything-is-free-worker.js (Main Cloudflare Worker)
│ │ ├── app.js (Client-side WaveSurfer.js player logic)
│ │ ├── style.css (Stylesheet)
│ │ └── stem-descriptions.json (Stem descriptions data)
│ ├── artwork/ (Album-level artwork - main cover and beadwork)
│ └── images/ (Example screenshots and preview images)
├── .npmignore (Excludes large audio/media files from npm package)
├── package.json (NPM package configuration)
├── index.js (NPM package entry point - exports album data)
├── MANIFESTO.md (Album manifesto - philosophy and principles)
└── README.md (Main album documentation)
Each track directory contains:
README.md- Comprehensive documentation of available audio stems (individual track components in WAV format)artwork/subdirectory with PNG files (with dimensions in filenames):[Element]-Symbol-1000x1000.png- Element symbol artwork (1000x1000)[Element]-Text.png- Text-based artwork[Element].png- Main gradient artwork
- M4A audio files (compressed versions for web playback, if present locally)
The main src/artwork/ directory contains album-level artwork:
Cover-Square-750x750.png- Main album artwork (750x750)Small-Square-550x550.png- Beadwork artwork (550x550)
Note: Audio stems (WAV and M4A files, ~1-3.4 GB per track for WAV) are hosted in Cloudflare R2 buckets and accessible via a web interface powered by Cloudflare Workers. M4A files provide compressed versions of each stem for efficient web streaming.
- Track directories use numbered prefixes (1-7) followed by element names
- Audio stem files follow pattern:
[#].[Element]_Stem_[DESCRIPTION].wavor.m4a - Master files:
[#].[Element]_Master.wavor.m4a - Track numbers are zero-padded in filenames (e.g.,
7.Francium_Master.wav) - M4A files use identical naming as WAV files, only the extension differs
Audio Stems: Both WAV and M4A formats are available in R2 buckets:
WAV files (for download):
- Format: WAV (Waveform Audio File Format)
- Bit Depth: 24-bit (Uncompressed)
- Sample rate: 44.1 kHz
- File Size: ~85-95 MB per stem
- Total per track: 13-39 stems (~1.1-3.4 GB per track)
M4A files (for web playback):
- Format: M4A (MPEG-4 Audio)
- Used by the web interface audio player and Track README "Play" links
- Significantly smaller file size than WAV for faster streaming
- Same filename pattern as WAV but with
.m4aextension - Present in both R2 buckets and optionally in local track directories
Track Metadata:
- Hydrogen: 132 BPM, D Major, 5:19, 12 stems (13 total files including master)
- Lithium: 124 BPM, G minor, 5:33, 38 stems (39 total files including master)
- Sodium: 140 BPM, G minor, 5:09, 28 stems (29 total files including master)
- Potassium: 90 BPM, C Major, 5:16, 19 stems (20 total files including master)
- Rubidium: 132 BPM, G Major, 4:41, 9 stems (10 total files including master)
- Caesium: 130 BPM, C Major, 3:50, 16 stems (17 total files including master)
- Francium: 128 BPM, B flat, 4:59, 26 stems (27 total files including master)
Important: Stem counts exclude the master track. The master track is counted separately in total file counts.
R2 Buckets: Audio stems are hosted in Cloudflare R2 (S3-compatible object storage):
- Separate bucket per track (HYDROGEN, LITHIUM, SODIUM, POTASSIUM, RUBIDIUM, CAESIUM, FRANCIUM)
- Each bucket contains both WAV and M4A versions of all stems
- WAV files are too large for Git (~1-3.4 GB per track)
- M4A files are used for web player streaming
- Files accessible via custom domain URLs (e.g.,
https://hydrogen.ichbinsoftware.com/)
Cloudflare Workers:
The web interface is powered by a refactored multi-file worker architecture in src/workers/:
everything-is-free-worker.js- Main worker with routing, HTML generation, and R2 integrationapp.js- Client-side JavaScript for WaveSurfer.js audio playerstyle.css- GitHub-style CSS for all pagesstem-descriptions.json- Stem metadata (157 entries mapping filenames to descriptions)
Worker Capabilities:
- Serves index page listing all tracks
- Generates track-specific pages with audio stem listings
- Streams static assets (CSS, JS, JSON) from R2 ASSETS bucket
- Streams audio files and assets directly from track-specific R2 buckets
- Environment variables map track names to R2 bucket bindings
Key Features:
- Interactive waveform visualization for each stem (loads M4A files for faster streaming)
- Direct download links for individual stems and ZIP archives (WAV format)
- Responsive design for mobile and desktop
- Metadata display (BPM, key, length, stems count)
- Dual-format support: M4A for playback, WAV for downloads
- Stems column displays count of audio stems (excluding master track)
M4A files are integrated throughout the project for efficient web streaming:
Track READMEs:
- Track Information table "Play" link → M4A master file (e.g.,
1.Hydrogen_Master.m4a) - Download links → WAV files via web interface and ZIP archives
Cloudflare Worker (everything-is-free-worker.js + app.js):
- WaveSurfer.js audio player → Loads M4A files automatically
- Implementation:
app.jsline 49 replaces.wavwith.m4aextension in audio URL - Download links → Serve WAV files (uncompressed, production-quality)
- Bucket listings → Show only WAV files, but M4A equivalents exist for all stems
R2 Buckets:
- Each bucket contains complete dual-format library
- For every
*.wavfile, there's a corresponding*.m4afile - M4A files reduce bandwidth and improve streaming performance
- WAV files remain canonical format for professional use
This project is released under Creative Commons Zero v1.0 Universal (CC0 1.0) — public domain dedication with no restrictions.
The album manifesto is a core declaration of the project's philosophy: "Everything is Free". This is not just a title—it's a fundamental principle that defines how this work exists in the world.
Core Philosophy:
- This work is released without any restrictions whatsoever
- No attribution required, no permission needed, no licenses to navigate
- Released under CC0 1.0 Universal—complete public domain dedication
- Music should circulate freely like public infrastructure, not locked behind platforms or licenses
Key Principles from the Manifesto:
"This work is not a product. It is not content. It is not owned."
"You may: copy it, remix it, destroy it, commercialise it, repackage it, ignore it."
"Music should circulate like electricity."
"If something meaningful comes from this, it will not be because it was protected. It will be because it was free."
File Locations:
MANIFESTO.md- Standalone markdown file containing the full manifesto textindex.js- Embedded as themanifestoproperty (multi-line string using template literals)
Context for AI Assistants: When working with this codebase, understand that the "everything is free" philosophy extends to the code itself. The refusal of scarcity, control, and platform-locked distribution is central to all technical decisions. Features should support open access, easy downloading, and frictionless sharing—never paywalls, DRM, or artificial restrictions.
The .github/copilot-instructions.md file provides comprehensive guidance for GitHub Copilot and AI coding assistants working with this repository. It includes:
- Quick reference for common workflows
- Code examples and templates
- Integration points and where to make changes
- Technical details about worker routes and data structures
- Checklists for adding new tracks
Important: When making significant changes to project structure or workflows, update this file to keep AI assistants informed.
This project is published as an npm package: @ichbinsoftware/everything-is-free
Package Purpose:
- Provides programmatic access to album metadata and track information
- Enables developers to integrate track data into applications, websites, and tools
- Exports album manifesto, track metadata (BPM, key, URLs), and license information
Key Files:
package.json- NPM package configuration with scripts and metadataindex.js- Main export file containing album data structure.npmignore- Excludes large files (audio stems, artwork) from npm package.github/copilot-instructions.md- Instructions for GitHub Copilot and AI coding assistants
Exported Data Structure:
{
artist: "Software-Entwicklungskit",
album: "Everything is Free",
released: "Release date string",
albumPage: "https://software-entwicklungskit.bandcamp.com/album/everything-is-free",
homePage: "https://ev3.ichbinsoftware.com",
license: "CC0 1.0 Universal (CC0 1.0) Public Domain Dedication",
manifesto: "...", // Full manifesto text (multi-line string)
tracks: [
{
title: "Hydrogen",
number: 1,
symbol: "H",
color: "#25daf0",
bpm: 132,
key: "D Major",
repoSource: "https://github.com/ichbinsoftware/everythingisfree/tree/main/src/1.Hydrogen",
webUrl: "https://ev3.ichbinsoftware.com/hydrogen",
streamUrl: "https://hydrogen.ichbinsoftware.com/1.Hydrogen_Master.m4a",
wavUrl: "https://hydrogen.ichbinsoftware.com/1.Hydrogen_Master.wav",
stemsUrl: "https://hydrogen.ichbinsoftware.com/1.Hydrogen_STEMS.zip",
gradientImageUrl: "https://hydrogen.ichbinsoftware.com/Hydrogen.png",
symbolImageUrl: "https://hydrogen.ichbinsoftware.com/Hydrogen-Symbol.png",
textImageUrl: "https://hydrogen.ichbinsoftware.com/Hydrogen-Text.png",
lyrics: "...", // Optional - Song lyrics (String)
stems: [
{
name: "1.Hydrogen_Stem_BEEPS",
description: "Beeps/electronic sounds",
streamUrl: "https://hydrogen.ichbinsoftware.com/1.Hydrogen_Stem_BEEPS.m4a",
wavUrl: "https://hydrogen.ichbinsoftware.com/1.Hydrogen_Stem_BEEPS.wav"
},
// ... all stems for this track
]
},
// ... all 7 tracks
]
}Package Exports (Top-Level Properties):
artist(String) - Artist namealbum(String) - Album titlereleased(String) - Release datealbumPage(String) - Bandcamp URLhomePage(String) - Web interface URLlicense(String) - License informationmanifesto(String) - Full manifesto texttracks(Array) - Array of track objects
Track Object Properties:
title(String) - Track namenumber(Number) - Track number 1-7symbol(String) - Element symbol e.g. "H", "Li"color(String) - Hex color code for track brandingbpm(Number) - Beats per minutekey(String) - Musical key e.g. "D Major", "G Minor"repoSource(String) - GitHub URL to track directorywebUrl(String) - Web interface URL for trackstreamUrl(String) - M4A master file URL for streamingwavUrl(String) - WAV master file URL for downloadstemsUrl(String) - ZIP archive URL with all stemsgradientImageUrl(String) - Main gradient artwork PNG URLsymbolImageUrl(String) - Element symbol artwork PNG URLtextImageUrl(String) - Text-based artwork PNG URLlyrics(String, optional) - Song lyricsstems(Array) - Array of stem objects
Stem Object Properties:
name(String) - Stem filename without extensiondescription(String) - Human-readable descriptionstreamUrl(String) - M4A file URL for streamingwavUrl(String) - WAV file URL for download
NPM Scripts:
npm run manifesto- Print the album manifestonpm run info- Display album metadata (artist, album, homepage, license)
Usage Examples:
Basic Usage:
const ev3 = require('@ichbinsoftware/everything-is-free');
// Access album metadata
console.log(`${ev3.album} by ${ev3.artist}`);
console.log(`Released: ${ev3.released}`);
console.log(`License: ${ev3.license}`);
console.log(`Homepage: ${ev3.homePage}`);
// Print manifesto
console.log(ev3.manifesto);
// Access track information
const hydrogen = ev3.tracks[0];
console.log(`${hydrogen.title} - ${hydrogen.bpm} BPM in ${hydrogen.key}`);
console.log(`Symbol: ${hydrogen.symbol} | Color: ${hydrogen.color}`);
console.log(`Stems: ${hydrogen.stems.length}`);Working with Stems:
const lithium = ev3.tracks[1]; // Lithium (2nd track)
console.log(`\n${lithium.title} has ${lithium.stems.length} stems:\n`);
// List all stems with descriptions
lithium.stems.forEach((stem, index) => {
console.log(`${index + 1}. ${stem.name}`);
console.log(` Description: ${stem.description}`);
console.log(` Stream (M4A): ${stem.streamUrl}`);
console.log(` Download (WAV): ${stem.wavUrl}\n`);
});
// Find specific stems by keyword
const drumStems = lithium.stems.filter(s =>
s.description.toLowerCase().includes('drum')
);
console.log(`Found ${drumStems.length} drum stems`);NPM Package Exclusions (.npmignore): The npm package intentionally excludes large files and development documentation to keep the package lightweight (metadata only):
.github/- GitHub-specific files (Copilot instructions, workflows)CLAUDE.md- Claude Code AI assistant documentation (development use only)src/- Track directories with large audio filesartwork/- Large PNG artwork filesvideos/- Video files*.wav,*.m4a,*.mp3- All audio formats*.zip- ZIP archives*.png- PNG images.git,.DS_Store- System files
This ensures the published package contains only index.js, package.json, README.md, and MANIFESTO.md - providing programmatic access to metadata without bloating the package with large media files or development documentation.
When adding new tracks:
- Create directory: Follow the numbered pattern (e.g.,
8.Oganesson/) - Add artwork: Include all three PNG variants in
artwork/subdirectory - Create README: Document all audio stems with descriptions
- Upload stems: Upload both WAV and M4A files to new R2 bucket
- WAV files for downloads
- M4A files for web player streaming (same filename, different extension)
- Update worker: Add track metadata to
TRACKSconstant ineverything-is-free-worker.js - Add stem descriptions: Update
stem-descriptions.jsonwith new stem entries - Update NPM package: Add new track to
tracksarray inindex.jswith all properties:Important:{ title: "TrackName", number: 8, symbol: "Og", color: "#hexcode", bpm: 000, key: "X Major/Minor", repoSource: "https://github.com/ichbinsoftware/everythingisfree/tree/main/src/#.TrackName", webUrl: "https://ev3.ichbinsoftware.com/trackname", streamUrl: "https://trackname.ichbinsoftware.com/#.TrackName_Master.m4a", wavUrl: "https://trackname.ichbinsoftware.com/#.TrackName_Master.wav", stemsUrl: "https://trackname.ichbinsoftware.com/#.TrackName_STEMS.zip", gradientImageUrl: "https://trackname.ichbinsoftware.com/TrackName.png", symbolImageUrl: "https://trackname.ichbinsoftware.com/TrackName-Symbol.png", textImageUrl: "https://trackname.ichbinsoftware.com/TrackName-Text.png", lyrics: "...", // Optional - Add if track has lyrics stems: [ { name: "#.TrackName_Stem_DESCRIPTION", description: "Human-readable description", streamUrl: "https://trackname.ichbinsoftware.com/#.TrackName_Stem_DESCRIPTION.m4a", wavUrl: "https://trackname.ichbinsoftware.com/#.TrackName_Stem_DESCRIPTION.wav" }, // ... repeat for each stem ] }
- Use double quotes for all string property values (not single quotes)
- Include all stems in the
stemsarray with their descriptions - Match stem descriptions from
stem-descriptions.json - Add
lyricsproperty if the track has lyrics (optional)
- Bump version: Update
versioninpackage.jsonfollowing semantic versioning - Publish: Run
npm publishto publish the updated package
The main README.md follows this structure:
- Badges (npm version, license, status)
- Album cover image
- Introduction with Bandcamp link
- Key quotes from manifesto
- Tracks table with columns:
- Track (Track name)
- Symbol (Element symbol with embedded 50x50 PNG image)
- BPM
- Key
- Stems (count excluding master track)
- Assets (Interactive link to web player, Source link to GitHub)
- Artwork section with credits:
- Digital artwork by Maubere
- Bead work by Beadhammer
- Album cover and beadwork images displayed
- Contributing section with GitHub workflow instructions
- Usage section divided into:
- 🎛️ For Producers and Musicians (download, sync, DAW import)
- 📦 For Developers (npm package usage, code examples)
- Manifesto (full text inline)
- License information
- Credits with Instagram links
Each track's README follows a consistent format:
- Badges showing license, BPM, key, and format
- Track information table with audio link (M4A format for streaming playback)
- Columns: Track, BPM, Key, Stems, Audio
- Stems column shows count of audio stems (excluding master track)
- Audio contents section with download links:
- "All uncompressed stems + Master" - links to web player interface
- "All uncompressed stems + Master (ZIP)" - direct ZIP download
- Detailed stem listing table with file sizes and descriptions (WAV files)
- Technical specifications
- Stem categories (organized by type: vocals, drums, bass, synths, FX)
- Usage instructions (sync, tempo, DAW import) - uses 🎯 emoji
- Lyrics (if applicable)
- Artwork images
- License information
- Credits
- ASCII art footer
Important README Details:
- Main README tracks table includes Symbol column with 50x50 embedded images
- Track Information table includes Stems column (count excludes master track)
- Track Information "Play" link uses M4A file for faster streaming
- Download links emphasize "uncompressed" to clarify WAV format
- Stem listings document WAV files (production-quality format)
- M4A files mirror WAV filenames with
.m4aextension - Credits include Instagram links for contributors (@ichbinsoftware, @beadhammer)
The worker has been refactored into a clean, modular architecture:
Constants:
TRACKS- Array of track metadata objects (id, name, number, bpm, key, stems, length, color)stemsproperty contains count of audio stems excluding master track
TRACK_MAP- Quick lookup object derived from TRACKS arrayVALID_BUCKETS- Set of valid bucket identifiersCACHE_MAX_AGE- Cache duration for static assets (1 year)SHORT_CACHE- Cache duration for dynamic pages (5 minutes)cachedAssets- Global in-memory cache for parsed JSON assets
Routing Logic:
- Route 0: Assets (
/assets/style.css,/assets/app.js)- Fetches from
env.ASSETSR2 bucket - Serves with long cache headers (1 year)
- Fetches from
- Route 1: Home Page (
/)- Renders index page with all tracks
- Route 2: File Download (
/{bucket}/{filename})- Streams individual files from track-specific R2 buckets
- Validates bucket name and handles errors
- Route 3: Track Page (
/{bucket})- Lists bucket contents (WAV files only)
- Renders track-specific page with audio player
- Loads stem descriptions from
stem-descriptions.jsonasset
View Layer Functions:
renderLayout({ title, meta, content })- Shared HTML layout wrapperrenderIndexPage()- Generates home page with track tablerenderTrackPage(bucketName, files, stemDescriptions)- Generates track page with WaveSurfer.js player
Helper Functions:
formatBytes(sizeInBytes)- Converts bytes to human-readable format (decimal units)fetchAssetSafely(env, filename)- Safely fetches assets from R2 ASSETS bucket
Purpose: WaveSurfer.js audio player initialization and control
Key Features:
- Initializes WaveSurfer.js instances on-demand (not page load)
- Replaces
.wavwith.m4ain audio URLs for streaming (line 49) - Handles play/pause, time display, and waveform visualization
- Auto-pauses other players when one starts playing
- Uses track-specific colors for waveforms
Event Flow:
- User clicks "Load Player" button
- Creates WaveSurfer instance with track color
- Loads M4A file for visualization
- Displays play/pause controls and time indicator
Design System:
- GitHub-inspired design with clean typography
- Responsive tables and images
- Mobile-first approach with media queries
- Consistent color palette (#24292f for text, #0969da for links, #d0d7de for borders)
Key Components:
.site-header- Dark header with album title.track-summary- Track metadata table with album art.file- Individual stem card with waveform placeholder.waveform- Hidden by default, shown after loading.footer- Centered links to streaming platforms
Structure: JSON object with 157 entries mapping filenames to descriptions
Format:
{
"1.Hydrogen_Master.wav": "Full mix master track",
"1.Hydrogen_Stem_BEEPS.wav": "Beeps/electronic sounds",
...
}Usage:
- Loaded from R2 ASSETS bucket on first track page request
- Cached globally in worker memory for subsequent requests
- Displayed as italicized descriptions next to stem filenames
- All stems sync to Bar 1 for easy DAW alignment
- File sizes use decimal units (1 MB = 1,000,000 bytes) per R2 standard
- WaveSurfer.js loads on-demand to avoid performance issues
- Audio player uses M4A files (
.wavextension replaced with.m4ainapp.js) - Download links use WAV files (original high-quality format)
- Stems column displays in both index page (after Key) and track pages (after Length)
- Stems count excludes master track - shows only individual audio stems
- Bucket names are lowercase in code but display capitalized
- Each track has a dedicated R2 bucket bound via environment variables
- Static assets (CSS, JS, JSON) served from separate
env.ASSETSbucket
When modifying the worker files:
Do:
- Keep routing logic clean and well-commented
- Maintain consistent error handling with try-catch blocks
- Use the shared
renderLayout()function for all pages - Cache parsed JSON assets in
cachedAssetsglobal variable - Add new routes following the existing pattern (assets → home → file → bucket)
- Validate all user inputs (bucket names, filenames)
Don't:
- Inline CSS or JavaScript (use
/assets/routes instead) - Modify cache durations without consideration
- Remove error handling or fallback logic
- Change the fundamental page structure (header, main content, footer)
Do:
- Keep WaveSurfer.js initialization logic modular
- Use track colors from
TRACK_DATAconfiguration - Handle edge cases (WaveSurfer not loaded, network errors)
- Auto-pause other players when starting a new one
Don't:
- Add additional dependencies beyond WaveSurfer.js from unpkg
- Remove the M4A conversion logic (line 49)
- Break the on-demand loading pattern
Do:
- Maintain GitHub-style design system
- Use responsive design with mobile-first approach
- Keep consistent color palette (#24292f, #0969da, #d0d7de)
- Test on both desktop and mobile viewports
Don't:
- Remove responsive media queries
- Change core layout structure
- Add heavy CSS frameworks
Do:
- Keep descriptions concise and descriptive
- Follow the existing naming pattern:
"X.TrackName_Stem_NAME.wav": "Description" - Include all master tracks with "Full mix master track" description
- Alphabetize or organize by track number
Don't:
- Remove existing entries
- Use inconsistent description formats
- Include special characters that break JSON syntax
General Conventions:
- Footer links should be centered and wrap on mobile
- Tables should have responsive padding and font sizes
- Images should scale properly without distortion
- Use
width: 100%; height: auto;for responsive images - Include ARIA labels for accessibility