Template API Manual
This document explains how player templates connect to the Studio Player core engine. It is intentionally practical and not overly technical: you should be able to understand how a template is built from PHP + CSS + JS, which DOM “hooks” are expected, and which parts are already handled by the core (streaming, timing, text engine, and waveform plumbing).
1. What is a template?
A Studio Player template defines the player’s structure and presentation. The core engine (streaming, variant switching, synchronization, buffering, and global keyboard handling) stays the same across templates. Templates connect to the engine via a small set of predefined DOM hooks (CSS classes and data attributes), plus a small JS API that the core attaches to the player root element.
The current plugin ships with two templates: default and cover-flow.
2. Where templates live (plugin vs. uploads)
| Location | Purpose | Example path |
|---|---|---|
| Plugin templates | Built-in templates shipped with the plugin. | wp-content/plugins/the-studio-player/templates/player/<slug>/ |
| Uploads templates | Update-safe overrides and custom templates. | wp-content/uploads/the-studio-player/templates/player/<slug>/ |
If a template exists in both locations, the uploads version is used. This allows you to copy a built-in template into uploads, customize it, and keep it unchanged across plugin updates.
Default template selection uses a folder name marker: a template directory name can optionally end with (default). If multiple templates
are marked as default, the first one in lexical order wins (uploads candidates are preferred over plugin candidates).
Template folders must contain a player.php file. Folders starting with an underscore are ignored (reserved for internal use).
3. Template file structure (PHP/CSS/JS)
A player template folder contains a required player.php file. Typically it also includes style.css and script.js:
templates/player/<slug>/
player.php
style.css
script.js
player.php outputs the HTML markup and reads the playlist context (playlist id, selected template slug, design schema). It also declares template defaults via a header block (colors, “show playlist”, “show audio info”, etc.).
style.css styles the template. The core design system provides CSS variables on the root element, so templates can share a common palette and still look different.
script.js binds the template UI to the core engine. This is where the “predefined” calls live (bind playlist, bind variants, bind transport buttons, render the text engine, and optional waveform/canvas visuals).
When you embed players via the shortcode, the plugin automatically enqueues the core scripts and the selected template’s
style.css/script.js (from uploads or plugin). The selected template comes from the playlist (Player-Builder) and can also be set via shortcode,
e.g. [[thespl_player playlist_id="123" template="cover-flow"]].
4. DOM contract (required hooks)
The core initializes players by scanning for .thespl-player[data-playlist-id]. Your template must provide a root wrapper with at least:
<div
class="thespl-player"
id="thespl-player-123-XXXX"
data-playlist-id="123"
data-template-slug="my-template"
>
...
</div>
data-template-slug
data-template-slug is used by template scripts to find “their” player instances (the built-in templates bind to
.thespl-player[data-template-slug="…"]).
You may see data-thespl-core-ui in older templates or builds. It is deprecated and will be removed, so it is not part of the public template API and should not be relied on.
Both built-in templates also use these standard elements (recommended):
| Hook | What it connects | Where it appears |
|---|---|---|
.thespl-player__audio (audio element) |
Audio output owned by the core engine. | default, cover-flow |
.thespl-player__status |
Text engine line 1 (status: Buffering / Ready / Paused / errors). | default, cover-flow |
.thespl-player__infotext |
Text engine line 2 (infotext: track/variant/message rotation). | default, cover-flow |
.thespl-player__variants |
Variant buttons (A/B or Pro: A/B/C/D), driven by UI facade. | default, cover-flow |
.thespl-player__playlist |
Track list / coverflow list, driven by UI facade. | default, cover-flow |
.thespl-player__btn--play, --pause, --stop |
Transport controls (predefined actions). | default (+ cover-flow uses a toggle button as well) |
.thespl-player__canvas inside __canvas-wrap |
Optional canvas UI (progress ring, waveform visualization, etc.). | default, cover-flow |
data-thespl-audio-info="…" (optional) |
Audio info box (plugin version/build + runtime metrics). | default, cover-flow |
5. JS contract (predefined API calls)
The core attaches a small API object to the root element as root._thesplPlayerApi. Templates can call it, and the shared UI facade uses it
to connect buttons and lists.
// Provided by the core on each player root:
root._thesplPlayerApi = {
play: async () => { ... },
pause: () => { ... },
stop: () => { ... },
toggle: () => { ... },
playTrack: async (index) => { ... },
selectVariant: (index) => { ... }
};
The template should not re-implement playback logic. Instead, it renders buttons and containers and then calls the shared UI facade to bind them to the core API.
Minimal binding pattern used by both built-in templates:
(function () {
function initTemplate(root) {
if (!window.THESPL_Player_Store || !window.THESPL_Player_UI) return;
window.THESPL_Player_Store.init(root);
var api = root._thesplPlayerApi;
window.THESPL_Player_UI.setInfotextMode(root, 'scroll');
window.THESPL_Player_UI.bindInfotext(root);
window.THESPL_Player_UI.bindPlaylist(root, api);
window.THESPL_Player_UI.bindVariants(root, api);
window.THESPL_Player_UI.bindTransport(root, api);
window.THESPL_Player_UI.renderStatus(root);
}
})();
6. Design schema & CSS variables
Templates read colors and visibility defaults from the template header and the playlist’s design schema. On render, the template maps the schema into CSS variables on the root element. This gives you a consistent “design language” without hardcoding everything.
Typical variables include: --thespl-bg, --thespl-text, --thespl-accent, --thespl-accent-2,
--thespl-waveform, and button/chip colors. Your template CSS can rely on these.
/* Example usage inside a template CSS */
.thespl-player {
background: var(--thespl-bg);
color: var(--thespl-text);
}
.thespl-player__btn--play {
background: var(--thespl-button-bg);
color: var(--thespl-button-text);
}
7. Waveforms & visualization
Waveforms are an optional UI layer on top of the core. The core handles streaming and timing; the template can decide how to visualize progress and (optionally) waveform data. Both shipped templates include a canvas element for visualization, but the design is fully template-specific.
You do not need to invent your own streaming, buffering, or variant switching. Templates should treat these as “framework” features. For waveform display, you can build your UI around the existing player store/UI facade patterns and show a friendly notice when waveform data is missing.
8. Steps to build your own template
- Copy an existing template folder (recommended starting point: default).
- Rename the folder to your slug (letters/numbers/dashes). Keep it inside uploads for update safety.
- Adjust
player.phpmarkup (layout/structure). Keep the required hooks. - Adjust
style.css(use CSS variables from the design schema). - Adjust
script.jsto bind UI components viaTHESPL_Player_UIand the core API. - Select the template in Player-Builder and embed the player with a shortcode, e.g.
[[thespl_player playlist_id="123"]].
The template slug is derived from the template folder name. After renaming the folder, update your copied script.js to bind to the new slug
(the shipped templates use selectors like .thespl-player[data-template-slug="default"]). Then select the new template slug in Player-Builder
(or pass it via shortcode using template="your-slug").
For update-safe templates, use: wp-content/uploads/the-studio-player/templates/player/<your-template>/
If the built-in design options don't fully match your vision, we can create a fully custom template tailored to your brand for a flat fee. Contact us at support@studioplayer.de.