Files
wp-fedistream/CLAUDE.md
2026-01-29 15:43:34 +01:00

22 KiB

Wordpress Plugin to stream music over Activity Pub

Author: Marco Graetsch Author URL: https://src.bundespruefstelle.ch/magdev Author Email: magdev3.0@gmail.com Repository URL: https://src.bundespruefstelle.ch/magdev/wp-fedistream Issues URL: https://src.bundespruefstelle.ch/magdev/wp-fedistream/issues

Project Overview

This plugin provides a way for Musicians or Music-Labels to cut the ties with Spotify, Youtube Music et al and build their own Streaming-Platform (optionally including selling their work using WooCommerce) base on the ActivityPub protocol. This plugin implements the management of Musicians (Single or Bands), Albums (or Releases), Tracks and Playlists.

The plugin utilizes the ActivityPub protocol to publish Releases or Tracks, share Playlists and let users create Playlist from different Wordpress instances, which use this plugin. It also employs Fediverse reactions to build comprehensive profile for Musicians and Bands (or the Label at all), including classicla Blogposts from Musicians. The Plugin should serve as a full Fediverse profile for Musicians. Everyone in the Fediverse is able to subscribe to the Label's or Musician's account.

If WooCommerce is installed, the Musician (or the Label) is allowed to sell the Music either as Album or single track utilizing special WooCommerce product types.

The goal is to create an alternative to the big tech streaming plaforms and give the musicians their freedom back and concentrate to make music. The first goal is to publish, the second goal is to monetize the platform without ripping of the users or musicians.

Key Fact: 100% AI-Generated

This project is proudly "vibe-coded" using Claude.AI - the entire codebase was created through AI assistance.

Temporary Roadmap

Note for AI Assistants: Clean this section after the specific features are done or new releases are made. Effective changes are tracked in CHANGELOG.md. Do not add completed versions here - document them in the Session History section at the end of this file.

(No pending features - all roadmap items completed)

Technical Stack

  • Language: PHP 8.3.x
  • Framework: Latest WordPress Plugin API
  • E-commerce (optional): WooCommerce 10.0+
  • Template Engine: Twig 3.0 (via Composer)
  • Communication Protocol: ActivityPub
  • Wordpress Base Theme twentytwentyfive
  • Frontend: Vanilla JavaScript
  • Styling: Custom CSS
  • Dependency Management: Composer
  • Internationalization: WordPress i18n (.pot/.po/.mo files)
  • Canonical Plugin Name: wp-fedistream

Security Best Practices

  • All user inputs are sanitized (integers for quantities/prices)
  • Nonce verification on form submissions
  • Output escaping in templates (esc_attr, esc_html, esc_js)
  • Direct file access prevention via ABSPATH check
  • XSS-safe DOM construction in JavaScript (no innerHTML with user data)
  • SQL injection prevention using $wpdb->prepare() throughout

Translation Ready

All user-facing strings use:

__('Text to translate', 'wp-fedistream')
_e('Text to translate', 'wp-fedistream')

Text domain: wp-fedistream

Translation Template

  • Base .pot file created: languages/wp-fedistream.pot
  • Ready for translation to any locale
  • All translatable strings properly marked with text domain

Available Translations

  • en_US - English (United States) [base language - .pot template]
  • de_CH - German (Switzerland, formal)

To compile translations to .mo files for production:

for po in languages/*.po; do msgfmt -o "${po%.po}.mo" "$po"; done

Create releases

  • The vendor/ directory MUST be included in releases (Dependencies required for runtime)
  • Don't create any release files until version 0.1.x and up!
  • CRITICAL: Build vendor/ for the MINIMUM supported PHP version, not the development version
    • Use composer config platform.php 8.3.0 before building release packages
    • Run composer update --no-dev --optimize-autoloader to rebuild dependencies
  • CRITICAL: WordPress requires plugins in a subdirectory structure
    • Run zip from the plugins/ parent directory, NOT from within the plugin directory
    • Package must extract to wp-fedistream/ subdirectory with main file at wp-fedistream/wp-fedistream.php
    • Correct command: cd /wp-content/plugins/ && zip -r wp-fedistream/releases/wp-fedistream-x.x.x.zip wp-fedistream ...
    • Wrong: Running zip from inside the plugin directory creates files at root level
  • CRITICAL: Exclude symlinks explicitly - zip follows symlinks by default
    • Always use -x "wp-fedistream/wp-core" -x "wp-fedistream/wp-core/*" -x "wp-fedistream/wp-plugins" -x "wp-fedistream/wp-plugins/*" to exclude development symlinks
    • Otherwise the entire linked directory contents will be included in the package
  • Exclusion patterns must match the relative path structure used in zip command
  • Always verify the package structure with unzip -l before distribution
    • Check all files are prefixed with wp-fedistream/
    • Verify main file is at wp-fedistream/wp-fedistream.php
    • Check for duplicate entries (indicates multiple builds in same archive)
  • Test installation on the minimum supported PHP version before final deployment
  • Releases are stored in releases/ including checksums
  • Track release changes in a single CHANGELOG.md file
  • Bump the version number to either bugfix release versions or on new features minor release versions
  • CRITICAL: WordPress reads version from TWO places - BOTH must be updated:
    1. Plugin header comment Version: x.x.x (line ~6 in wc-licensed-product.php) - WordPress uses THIS for admin display
    2. PHP constant WP_FEDISTREAM_VERSION (line ~28) - Used internally by the plugin
    • If only the constant is updated, WordPress will show the old version in Plugins list

Important Git Notes:

  • Default branch while development is dev
  • Create releases from branch main after merging branch dev
  • Tags should use format vX.X.X (e.g., v1.1.22), start with v0.1.0
  • Use annotated tags (-a) not lightweight tags
  • Commit messages should follow the established format with Claude Code attribution
  • .claude/settings.local.json changes are typically local-only (stash before rebasing)

What Gets Released

  • All plugin source files
  • Compiled vendor dependencies
  • Translation files (.mo compiled from .po)
  • Assets (CSS, JS)
  • Documentation (README, CHANGELOG, etc.)

What's Excluded

  • Git metadata (.git/)
  • Development files (.vscode/, .claude/, .gitea/, CLAUDE.md, wp-core, wp-plugins)
  • Logs and cache files
  • Previous releases
  • composer.lock (but vendor/ is included)

CI/CD Pipeline (Gitea Actions)

Automated release packages are created via Gitea Actions when a tag matching v* is pushed:

Workflow: .gitea/workflows/release.yml

Trigger: Push tag vX.X.X to repository

Steps:

  1. Checkout code
  2. Setup PHP 8.3 with required extensions
  3. Install production Composer dependencies
  4. Compile translations (.po to .mo)
  5. Verify plugin version matches tag version
  6. Build release zip with proper WordPress structure
  7. Generate SHA256 checksums
  8. Verify package structure
  9. Extract changelog for release notes
  10. Create Gitea release with attachments

Required Secret: GITEA_TOKEN - Personal access token with release permissions

Pre-release Detection: Tags containing - (e.g., v1.0.0-beta) are marked as pre-release

To create a release:

# Ensure version is updated in wp-fedistream.php (both header and constant)
git checkout main
git merge dev
git tag -a v0.4.0 -m "Release v0.4.0"
git push origin main --tags

The pipeline will automatically build and publish the release package.


For AI Assistants:

When starting a new session on this project:

  1. Read this CLAUDE.md file first
  2. Semantic versioning follows the MAJOR.MINOR.BUGFIX pattern
  3. Check git log for recent changes
  4. Verify you're on the dev branch before making changes
  5. Run composer install if vendor/ is missing
  6. Test changes before committing
  7. Follow commit message format with Claude Code attribution
  8. Update this session history section with learnings
  9. Never commit backup files (*.po~, *.bak, etc.) - check git status before committing
  10. Follow markdown linting rules (see below)

Always refer to this document when starting work on this project.

Markdown Linting Rules

When editing CLAUDE.md or other markdown files, follow these rules to avoid linting errors:

  1. MD031 - Blank lines around fenced code blocks: Always add a blank line before and after fenced code blocks, even when they follow list items. Example of correct format:

    • Item label:

      (blank line here) ```php code example ``` (blank line here)

  2. MD056 - Table column count: Table separators must have matching column counts and proper spacing. Use consistent dash lengths that match column header widths.

  3. MD009 - No trailing spaces: Remove trailing whitespace from lines

  4. MD012 - No multiple consecutive blank lines: Use only single blank lines between sections

  5. MD040 - Fenced code blocks should have a language specified: Always add a language identifier to code blocks (e.g., txt, bash, php). For shortcode examples, use txt.

  6. MD032 - Lists should be surrounded by blank lines: Add a blank line before AND after list blocks, including after bold labels like **Attributes:**.

  7. MD034 - Bare URLs: Wrap URLs in angle brackets (e.g., <https://example.com>) or use markdown link syntax [text](url).

  8. Author section formatting: Use a heading (### Name) instead of bold (**Name**) for the author name to maintain consistent document structure.

Project Architecture

Directory Structure

wp-fedistream/
├── .gitea/
│   └── workflows/
│       └── release.yml        # CI/CD release pipeline
├── assets/
│   ├── css/
│   │   ├── admin.css          # Admin interface styles
│   │   └── frontend.css       # Frontend styles
│   ├── js/
│   │   ├── admin.js           # Admin interface scripts
│   │   ├── frontend.js        # Frontend scripts
│   │   ├── player.js          # Audio player
│   │   ├── library.js         # User library page
│   │   └── notifications.js   # Notification system
│   └── images/
├── includes/
│   ├── ActivityPub/
│   │   ├── Integration.php    # ActivityPub plugin integration
│   │   ├── ArtistActor.php    # Artist as ActivityPub actor
│   │   ├── Inbox.php          # Process incoming activities
│   │   ├── Outbox.php         # Publish outgoing activities
│   │   ├── RestApi.php        # REST endpoints for ActivityPub
│   │   └── Transformers/      # Object transformers
│   │       ├── TrackTransformer.php
│   │       ├── AlbumTransformer.php
│   │       └── PlaylistTransformer.php
│   ├── Admin/
│   │   └── ListColumns.php    # Custom list table columns
│   ├── Frontend/
│   │   ├── Ajax.php           # AJAX handlers
│   │   ├── Shortcodes.php     # All shortcodes
│   │   ├── TemplateLoader.php # Template loading
│   │   └── Widgets.php        # Widget registration
│   ├── PostTypes/
│   │   ├── Artist.php         # fedistream_artist
│   │   ├── Album.php          # fedistream_album
│   │   ├── Track.php          # fedistream_track
│   │   └── Playlist.php       # fedistream_playlist
│   ├── Roles/
│   │   └── Capabilities.php   # User roles and caps
│   ├── Taxonomies/
│   │   ├── Genre.php          # fedistream_genre
│   │   ├── Mood.php           # fedistream_mood
│   │   └── License.php        # fedistream_license
│   ├── User/
│   │   ├── Library.php        # Favorites, follows, history
│   │   ├── LibraryPage.php    # Library shortcode
│   │   └── Notifications.php  # Notification system
│   ├── WooCommerce/
│   │   ├── Integration.php    # WooCommerce setup
│   │   ├── AlbumProduct.php   # Album product type
│   │   ├── TrackProduct.php   # Track product type
│   │   ├── DigitalDelivery.php # Download handling
│   │   └── StreamingAccess.php # Access control
│   ├── Installer.php          # Database setup, activation
│   └── Plugin.php             # Main singleton class
├── languages/
│   ├── wp-fedistream.pot      # Translation template
│   └── wp-fedistream-de_CH.po # German (Switzerland)
├── templates/                 # Twig templates
│   ├── admin/
│   ├── archive/
│   ├── single/
│   └── player/
├── vendor/                    # Composer dependencies
├── composer.json
├── uninstall.php
└── wp-fedistream.php          # Plugin entry point

Database Tables

Table Purpose
{prefix}_fedistream_plays Track play statistics
{prefix}_fedistream_playlist_tracks Playlist-track relationships
{prefix}_fedistream_followers ActivityPub followers
{prefix}_fedistream_purchases WooCommerce purchase tracking
{prefix}_fedistream_favorites User favorites
{prefix}_fedistream_user_follows Local artist follows
{prefix}_fedistream_listening_history Track play history
{prefix}_fedistream_notifications User notifications
{prefix}_fedistream_reactions Fediverse reactions

Custom Post Types

Post Type Slug Description
fedistream_artist /artists/ Musicians, bands, collectives
fedistream_album /albums/ Albums, EPs, singles, compilations
fedistream_track /tracks/ Individual audio tracks
fedistream_playlist /playlists/ Curated track collections

Custom Taxonomies

Taxonomy Type Applied To
fedistream_genre Hierarchical Artists, Albums, Tracks
fedistream_mood Non-hierarchical Tracks, Playlists
fedistream_license Hierarchical Albums, Tracks

User Roles

Role Slug Capabilities
Artist fedistream_artist Manage own content, upload files
Label fedistream_label Manage all content, taxonomies, stats

Shortcodes

Shortcode Description
[fedistream_player track_id="123"] Single track player
[fedistream_playlist id="456"] Playlist display
[fedistream_album id="789"] Album display
[fedistream_artist id="101"] Artist profile
[fedistream_recent_releases count="5"] Recent releases
[fedistream_popular_tracks count="10"] Popular tracks
[fedistream_library] User library page

Key Classes

  • Plugin (singleton) - Main controller, initializes all components
  • Installer - Database setup, activation/deactivation hooks
  • Artist, Album, Track, Playlist - Post type registration and meta boxes
  • Genre, Mood, License - Taxonomy registration with defaults
  • Capabilities - User role and capability management
  • ActivityPubIntegration - Integration with WordPress ActivityPub plugin
  • ArtistActor - Artist profiles as ActivityPub Person/Group actors
  • Inbox - Process Follow, Like, Announce, Create activities
  • Outbox - Publish Create, Update activities to followers
  • WooCommerceIntegration - Custom product types for albums/tracks
  • DigitalDelivery - Secure download handling with ZIP support
  • StreamingAccess - Purchase-based streaming control
  • Library - User favorites, follows, listening history
  • Notifications - In-app and email notification system

REST API Endpoints

Endpoint Method Purpose
/wp-json/fedistream/v1/artists/{id}/actor GET ActivityPub actor profile
/wp-json/fedistream/v1/artists/{id}/inbox POST ActivityPub inbox
/wp-json/fedistream/v1/artists/{id}/outbox GET ActivityPub outbox
/wp-json/fedistream/v1/artists/{id}/followers GET Followers collection
/wp-json/fedistream/v1/artists/{id}/following GET Following collection

AJAX Actions

Action Purpose
fedistream_record_play Record track play
fedistream_toggle_favorite Add/remove favorite
fedistream_toggle_follow Follow/unfollow artist
fedistream_get_library Get user library
fedistream_get_followed_artists Get followed artists
fedistream_get_history Get listening history
fedistream_clear_history Clear listening history
fedistream_get_notifications Get user notifications
fedistream_mark_notification_read Mark notification read
fedistream_mark_all_notifications_read Mark all read
fedistream_delete_notification Delete notification

Session History

2026-01-28 - Initial Release v0.1.0

Summary: Consolidated all development phases (0.0.1 through 0.7.0) into initial release v0.1.0.

Completed:

  • Implemented Phase 6 (WooCommerce Integration):
    • Custom product types for albums and tracks
    • Pricing models (Fixed, PWYW, NYP)
    • Digital delivery with secure downloads
    • Streaming access control based on purchases
  • Implemented Phase 7 (User Interactions):
    • User library with favorites, follows, history
    • Notification system (in-app and email)
    • Library shortcode and frontend page
  • Consolidated documentation:
    • Moved implementation details from PLAN.md to CLAUDE.md
    • Deleted PLAN.md (no longer needed)
    • Merged all changelog entries into single v0.1.0 release
    • Updated README.md with current features
  • Git operations:
    • Created initial commit on dev branch
    • Merged to main branch
    • Tagged as v0.1.0
    • Push pending (requires credentials)

Files Created:

  • includes/WooCommerce/Integration.php
  • includes/WooCommerce/AlbumProduct.php
  • includes/WooCommerce/TrackProduct.php
  • includes/WooCommerce/DigitalDelivery.php
  • includes/WooCommerce/StreamingAccess.php
  • includes/User/Library.php
  • includes/User/LibraryPage.php
  • includes/User/Notifications.php
  • assets/js/library.js
  • assets/js/notifications.js

Files Deleted:

  • PLAN.md

Notes:

  • Successfully pushed dev, main branches and v0.1.0 tag to origin
  • Remote URL updated from HTTPS to SSH for authentication
  • First release is now live at the repository

2026-01-28 - Bugfix v0.1.1 and Feature v0.2.0

Summary: Fixed WooCommerce integration timing bug, added plugin action links and user guide.

v0.1.1 - Bugfix:

  • Fixed WooCommerce product types not appearing in product selector
  • Root cause: Integration constructor hooked check_woocommerce to plugins_loaded priority 5, but class was instantiated at priority 10 (too late)
  • Solution: Call check_woocommerce() directly in constructor

v0.2.0 - Features:

  • Added Dashboard and Settings links to WordPress Plugins page
  • Created comprehensive USERGUIDE.md covering all features

Files Modified:

  • includes/WooCommerce/Integration.php - Fixed hook timing
  • includes/Plugin.php - Added add_plugin_action_links() method

Files Created:

  • USERGUIDE.md - Comprehensive user documentation

Notes:

  • All releases pushed to origin (v0.1.1 and v0.2.0 tags)
  • Markdown linting fixes applied to USERGUIDE.md

2026-01-29 - License Management v0.3.0

Summary: Implemented license management integration and reorganized settings page into tabs.

Features:

  • License management using magdev/wc-licensed-product-client package
  • Tabbed settings page: License, Default Settings, Integrations
  • License validation and activation via AJAX
  • License status banner with expiration display
  • Frontend license checks (unlicensed sites show message instead of content)
  • Admin/backend works regardless of license status

License Behavior:

  • Backend (admin): Full access always
  • Frontend (player, shortcodes, ActivityPub): Requires valid license

Files Created:

  • includes/License/Manager.php - License management wrapper class

Files Modified:

  • composer.json - Added VCS repository and magdev/wc-licensed-product-client dependency
  • includes/Plugin.php - Tabbed settings page, license manager initialization, conditional frontend loading
  • includes/Installer.php - Added default license options
  • includes/Frontend/Shortcodes.php - Added unlicensed mode support
  • includes/Frontend/Ajax.php - Added license checks to public AJAX endpoints
  • assets/js/admin.js - License validation AJAX handlers
  • assets/css/admin.css - Tab and license status styling
  • wp-fedistream.php - Version bump to 0.3.0
  • CHANGELOG.md - Added v0.3.0 entry

Notes:

  • Package name is magdev/wc-licensed-product-client (not wc-license-product-client)
  • Uses Symfony HTTP Client via the license client package
  • License validation cached for 24 hours using WordPress transients

2026-01-29 - CI/CD Pipeline v0.4.0

Summary: Added Gitea Actions workflow for automated release package creation.

Features:

  • Automated release builds triggered by v* tags
  • PHP 8.3 environment with required extensions
  • Production Composer dependency installation
  • Automatic translation compilation (.po to .mo)
  • Version verification (plugin version must match tag)
  • Proper WordPress plugin zip structure
  • SHA256 checksum generation
  • Package structure verification
  • Changelog extraction for release notes
  • Automatic Gitea release creation with attachments
  • Pre-release detection for tags containing -

Files Created:

  • .gitea/workflows/release.yml - CI/CD release pipeline

Files Modified:

  • CLAUDE.md - Added CI/CD documentation and updated directory structure
  • CHANGELOG.md - Added v0.4.0 entry
  • wp-fedistream.php - Version bump to 0.4.0

Notes:

  • Requires GITEA_TOKEN secret configured in repository settings
  • Uses shivammathur/setup-php@v2 for PHP setup
  • Uses actions/gitea-release-action@v1 for release creation
  • Compatible with GitHub Actions syntax
  • User simplified checksums to SHA256 only (removed MD5)