Mixtape Component Refinement Spec

Built for offline playback, emotional clarity, and HTML-level storytelling

4 min

The following specification is the origin story of Skirbi. It isn’t implemented yet. And it probably violates some principles of current day Skirbi, but fuck it, it’s here.

Mixtape Component Refinement Spec

Canonical Elements

Element Purpose Notes
<chapter> Groups a themed collection Represents a tape side or segment
<playlist> Holds <track-item>s Main container
<track-item> Defines one audio/video imprint Can be hidden, aliased
<playback> Triggers playback (global/local) Replaces queue-playlist

Supported Aliases

For <track-item>

Alias Description
imprint Poetic emphasis on intent
bonus-track Hidden or post-arc material
skit Spoken interlude or vignette
intro Prelude or thematic opener
reprise Return or variation

All aliases map to TrackItem logic.

js
customElements.define('imprint', TrackItem);
customElements.define('bonus-track', TrackItem);
// etc.

For <playlist>

Alias Description
tracklist Structural clarity
setlist Concert or performance metaphor

All aliases map to playlist behavior. No logic changes.

Chapter Structure

html
<chapter name="sideA" tagline="Letters I Never Sent">
  <playlist>
    <track-item ... />
    <track-item ... />
  </playlist>
  <playback type="audio">▶ Play Side A</playback>
</chapter>

Attributes

Attribute Purpose
name Internal label (non-visible)
tagline Subtitle or short description
hidden Visually hides the entire chapter
playHidden="0" Prevents hidden chapters from being included in playback
audioBase / videoBase / artBase Base paths for resolving track assets

Playback Behavior

<playback type="audio">

Triggers either global or local queue based on DOM position.

Position Scope
Inside <chapter> Local to chapter
Outside chapters Global (all playlists)

Playback Inclusion Flags

Attribute Plays? Visible? Description
Default
hidden Hidden track (like a CD bonus)
hidden + playHidden="0" Fully skipped
playHidden="0" (alone) No effect unless hidden

Hidden tracks play unless explicitly told not to. Like real mixtapes.

Player Structure

html
<div id="playerSection">
  <button id="closePlayer">...</button>

  <audio id="audioPlayer" controls></audio>
  <video id="videoPlayer" controls></video>

  <div id="queueControls">
    <button id="prevTrack">⏮</button>
    <div id="trackMeta">
      <strong id="trackTitle">Title</strong>
      <span id="trackArtist">Artist</span>
    </div>
    <button id="nextTrack">⏭</button>
  </div>
</div>

Styling Tips

  • Use CSS only to reposition metadata (#trackMeta)
  • Change layout via grid/flex to match mood
  • Move controls left/right based on UX tone

Hidden Tracks & Discovery

  • Hidden tracks can be unlocked at runtime via removeAttribute('hidden')
  • Tracks with playHidden="0" remain excluded even when hidden
  • Typical use: easter eggs, emotional reveals, interludes

Future-Proof Design

Feature Current Status Future Option
Shuffle mode Manual mode="shuffle"
Playback limits Scoped target="chapterX"
Custom styling Author-driven Tag-specific theming via CSS

Naming Philosophy

  • playlist is familiar and keeps the HTML human
  • playback aligns with physical metaphor (play the tape)
  • track-item is literal; aliases like imprint give emotional weight
  • Chapters are structural and thematic containers — mix sides, arcs, or acts

<mixtape> — Root-Level Configuration Container

The <mixtape> tag acts as the top-level element for a mixtape instance, allowing shared configuration and asset path definitions, as well as overall metadata.

Purpose

  • Set global paths for media resolution
  • Provide shared config for all nested track-items
  • Contain multiple <chapter>s or playlists
  • Define mixtape-level name and tagline

Example

html
<mixtape
  name="The One That Wasn't"
  tagline="A mixtape for a moment that never began"
  audioBase="../audio/"
  videoBase="../video/"
  artBase="../art/"
>
  <chapter name="A" tagline="Intro / Side A">
    <playlist>
      <track-item song="Rocket Man" artist="Elton John" track="A01-Rocket_Man" />
    </playlist>
    <playback type="audio">▶ Play Side A</playback>
  </chapter>
</mixtape>

Attributes

Attribute Purpose
name Internal identifier for the mixtape
tagline Descriptive or poetic subtitle
audioBase Base folder for .mp3 or .m3u
videoBase Base folder for .mp4 or .m3u
artBase Base path for cover art/thumbnails

If omitted, base paths default to ./audio/, etc.

Scoping Behavior

  • Attributes on <mixtape> are inherited by nested elements unless overridden
  • Chapters or tracks can override media paths if needed

Semantic Track Aliases with Behavior

Unlike purely visual tags, some aliases carry built-in behavior to mirror real-world mixtape, CD, or vinyl structures. Authors can still override these via attributes.

Behavior Table

Alias Base Tag hidden playHidden Purpose
bonus-track track-item 1 Hidden track that still plays
intro track-item 0 Thematic opening, never skipped
interlude track-item 1 Mood-setter or ambient filler
skit track-item 1 Spoken word / vignette
reprise track-item 1 Musical callback
outro track-item 0 Closing gesture, always plays
live-track track-item 1 Recorded performance
instrumental track-item 1 No vocals version
remix track-item 1 Altered or alternate version
imprint track-item 1 Optional poetic alias (docs only)

All of these are just aliases for TrackItem, but some come with default attributes applied.

JavaScript Implementation (Concept)

js
function defineAlias(tag, defaults = {}) {
  class AliasTrackItem extends TrackItem {
    connectedCallback() {
      for (const [attr, val] of Object.entries(defaults)) {
        if (!this.hasAttribute(attr)) {
          this.setAttribute(attr, val);
        }
      }
      super.connectedCallback();
    }
  }
  customElements.define(tag, AliasTrackItem);
}

defineAlias('bonus-track', { hidden: '', playHidden: '1' });
defineAlias('intro', { playHidden: '0' });
defineAlias('interlude', { hidden: '', playHidden: '1' });
// Add remaining aliases as needed...

Authors may override any default by explicitly setting hidden, playHidden, etc.

Summary

You now have:

  • A clean, offline-compatible HTML format
  • Fully scoping playback and visibility
  • Themeable naming via aliasing
  • CSS-driven layout customization
  • Media-rich storytelling via Web Components