Developers

Built to be extended

Riff is built the way a feature plugin is: one track shape everywhere, read through WordPress's own APIs, with a public surface that is written down and kept. Everything below is stable within a major version.

PHP

Every filter and action has a page of its own, generated from the docblock above the line it fires on, and CI fails a change that adds one without it; Riff's functions are held to the same. The PHP reference lists them with the Riff\Source interface, the track schema and the Listen block. Change a track before the player reads it, add a section to About, register a view or a control, or turn the turntable or the whole player off on a page; all hooks are searchable in one list.

JavaScript

window.riff is the player's API. Actions and filters through wp.hooks, and riff:* events on the player's root, announce every change of state: what is playing, what is queued, what a press did. The JavaScript reference has every member of window.riff, generated from the player's own docblocks, and each action and filter has a page in the hooks reference.

REST and GraphQL

The REST API gives each audio and video item in wp/v2/media a riff_track. riff/v1/library lists the posts with tracks and riff/v1/library/{id} opens one with its tracks and rendered blocks. riff/v1/tracks, riff/v1/albums and riff/v1/artists browse and search the Media Library, and a visitor sees only what WordPress's own media route would show them. Every route describes itself on OPTIONS. With WPGraphQL active, MediaItem.riffTrack and Post.riffTracks. All of it shares one schema with the player, Riff\Tracks::schema(), versioned and held to after the riff_track filter; WPGraphQL's RiffTrack is built from it. The REST API reference has every route, argument and field.

Your own tracks

Tracks come from registered sources. The core source reads the audio, video and playlist blocks in posts. A plugin adds its own post type or catalogue by implementing Riff\Source and calling Riff\Sources::register() on init, or through the riff_sources filter, and the library, the REST routes and the player read it like any other. The PHP reference has the interface, method by method.

Views and controls

Now Playing shows one view at a time, the album, the turntable or the lyrics, each taking the whole screen above the bar and opened from its button at the bar's right, or on a phone from its chip in Now Playing. Up next, About and Together are side panels, one open at a time, beside the page on a wide screen and over it on a phone.

A plugin adds its own views, and controls to the bar, as Riff adds its own: registered on the server with riff_register_view() and riff_register_control() on the riff_register action, so the page has every button and every view before any script runs. In the browser, window.riff.view() and window.riff.control() give each what it does, by its id, and add one the server didn't register, for what only the browser knows; window.riff.openView() and closeView() open and close one. How the player works has the whole of it.

Riff Lyrics is the reference extension: a separate plugin that adds a Lyrics view using only Riff's documented API, and CI fails if it reaches past it.

Standalone mode and WP-CLI

Any page with the Riff block also answers at its address plus app/, outside the theme and with a web app manifest. wp riff import <folder> adds a folder of music to the Media Library, one album post per folder, and --dry-run shows what it would do.

Design and theming

Riff has three layers, and each one is changed in a different place.

  • The Listen block follows your site. It takes the background, text, link colour and fonts from the theme's global styles. Styles > Blocks > Riff in the Site Editor comes before those, and the colour, typography, spacing, border and shadow settings on one block come before both. Every view inside the block, its rows, cards and search, is drawn from those colours, so a dark block has dark rows.
  • The standalone player is one design. At a Listen page's app/ address, Riff looks the same on every site, in its own dark style, the way a streaming app does. The Site Editor doesn't change it.
  • The docked player is the same everywhere too. The bar and Now Playing keep Riff's layout on every page. A theme sets their accent under settings.custom.riff.accent in theme.json.

Other plugins' styles still load in standalone mode, where only the theme's are left out, so a stylesheet can set the player's public custom properties there too; the CSS reference lists each with its default.

Handbooks

Beside the reference, the repository's own docs, published from the Markdown on every deploy. How the player works follows the front end from the blocks a page plays to the views, the panels and the turntable. Extensions covers the plugins that ship inside Riff: how one is bundled, how Riff loads it, and how to write one.

Under the hood

Each browser API and CSS feature the player calls has a page of its own: how Riff uses it, why, what happens without it, and the exact lines in the source at the commit that was published.

The code

No build step: the shipped files are the source. The repository has the contributing guide, the test suites, and a Playground blueprint for a scratch site with the demo on it.