Media›Track
note

This rune is part of @refrakt-md/media. Install with npm install @refrakt-md/media and add "@refrakt-md/media" to the plugins array in your refrakt.config.json.

Track

A standalone track or recording with metadata. A heading becomes the track name. Use attributes for artist, duration, and other metadata. Tracks can be used independently or inside a playlist rune.

Basic usage

A single track with artist and duration.

{% track artist="Radiohead" duration="4:01" type="song" %}
# Everything in Its Right Place
{% /track %}
<li data-rune="track" typeof="MusicRecording" data-rune-fields="{&quot;artist&quot;:&quot;Radiohead&quot;,&quot;duration&quot;:&quot;PT241S&quot;,&quot;type&quot;:&quot;song&quot;}">
  <span data-name="track-name" data-field="name" property="name">Everything in Its Right Place</span>
  <span data-name="track-artist">Radiohead</span>
  <span data-name="track-duration">4:01</span>
  <meta property="duration" content="PT241S">
  <meta property="byArtist" content="Radiohead">
</li>
  • Everything in Its Right PlaceRadiohead4:01
  • <li typeof="MusicRecording" class="rf-track" data-elevation="flat" data-rune="track" data-density="full">
      <span data-name="track-name" data-field="name" property="name" class="rf-track__track-name">Everything in Its Right Place</span>
      <span data-name="track-artist" class="rf-track__track-artist">Radiohead</span>
      <span data-name="track-duration" class="rf-track__track-duration">4:01</span>
      <meta property="duration" content="PT241S" />
      <meta property="byArtist" content="Radiohead" />
    </li>

    Podcast episode

    Use type="episode" for podcast episodes with a date.

    {% track type="episode" artist="Tech Weekly" duration="42:30" date="March 2025" %}
    # The Future of Web Standards
    {% /track %}
    <li data-rune="track" typeof="PodcastEpisode" data-rune-fields="{&quot;artist&quot;:&quot;Tech Weekly&quot;,&quot;duration&quot;:&quot;PT2550S&quot;,&quot;datePublished&quot;:&quot;March 2025&quot;,&quot;type&quot;:&quot;episode&quot;}">
      <span data-name="track-name" data-field="name" property="name">The Future of Web Standards</span>
      <span data-name="track-artist">Tech Weekly</span>
      <span data-name="track-duration">42:30</span>
      <span data-name="track-meta">March 2025</span>
      <meta property="duration" content="PT2550S">
      <meta property="datePublished" content="March 2025">
    </li>
  • The Future of Web StandardsTech Weekly42:30March 2025
  • <li typeof="PodcastEpisode" class="rf-track" data-elevation="flat" data-rune="track" data-density="full">
      <span data-name="track-name" data-field="name" property="name" class="rf-track__track-name">The Future of Web Standards</span>
      <span data-name="track-artist" class="rf-track__track-artist">Tech Weekly</span>
      <span data-name="track-duration" class="rf-track__track-duration">42:30</span>
      <span data-name="track-meta" class="rf-track__track-meta">March 2025</span>
      <meta property="duration" content="PT2550S" />
      <meta property="datePublished" content="March 2025" />
    </li>

    With body content

    Tracks can include additional body content like descriptions or show notes.

    {% track artist="Miles Davis" duration="9:22" type="song" %}
    # So What
    
    The opening track from *Kind of Blue*, featuring the iconic two-chord modal structure that changed jazz forever.
    {% /track %}
    <li data-rune="track" typeof="MusicRecording" data-rune-fields="{&quot;artist&quot;:&quot;Miles Davis&quot;,&quot;duration&quot;:&quot;PT562S&quot;,&quot;type&quot;:&quot;song&quot;}">
      <span data-name="track-name" data-field="name" property="name">So What</span>
      <span data-name="track-artist">Miles Davis</span>
      <span data-name="track-duration">9:22</span>
      <div data-name="track-description">
        <p>
          The opening track from
          <em marker="*">Kind of Blue</em>
          , featuring the iconic two-chord modal structure that changed jazz forever.
        </p>
      </div>
      <meta property="duration" content="PT562S">
      <meta property="byArtist" content="Miles Davis">
    </li>
  • So WhatMiles Davis9:22

    The opening track from Kind of Blue, featuring the iconic two-chord modal structure that changed jazz forever.

  • <li typeof="MusicRecording" class="rf-track" data-elevation="flat" data-rune="track" data-density="full">
      <span data-name="track-name" data-field="name" property="name" class="rf-track__track-name">So What</span>
      <span data-name="track-artist" class="rf-track__track-artist">Miles Davis</span>
      <span data-name="track-duration" class="rf-track__track-duration">9:22</span>
      <div data-name="track-description" class="rf-track__track-description">
        <p>
          The opening track from 
          <em marker="*">Kind of Blue</em>
          , featuring the iconic two-chord modal structure that changed jazz forever.
        </p>
      </div>
      <meta property="duration" content="PT562S" />
      <meta property="byArtist" content="Miles Davis" />
    </li>

    Inside a playlist

    A {% track %} written inside a {% playlist %} becomes one of that playlist's tracks — in the listing, in the HTML, and in the structured data. Use it when the list format is too limited: body content, per-track links, or cue points with prose.

    It costs nothing to switch. A nested track that states no type takes the playlist's kind, and inherits the playlist's artist the way a list item does, so the same track written either way produces the same structured data. The longer form may carry more; it never carries less.

    {% playlist type="podcast" artist="Tech Weekly" %}
    # Design Systems Weekly
    
    - **Token Architecture** (38:15) — February 2025
    
    {% track duration="45:30" date="March 2025" url="https://example.com/ep-12" %}
    # Component Libraries at Scale
    
    Why component libraries stall at the second team, and what to do about it.
    {% /track %}
    {% /playlist %}
    <section data-field="content-section" data-rune="playlist" typeof="PodcastSeries" data-rune-fields="{&quot;type&quot;:&quot;podcast&quot;,&quot;media-position&quot;:&quot;top&quot;,&quot;artist&quot;:&quot;Tech Weekly&quot;}" data-schema-lists="[&quot;hasPart&quot;]">
      <h1 id="design-systems-weekly" data-name="headline" property="name">Design Systems Weekly</h1>
      <ol data-name="tracks">
        <li data-field="track" typeof="PodcastEpisode" property="hasPart">
          <span data-name="track-name" property="name">Token Architecture</span>
          <span data-name="track-artist">Tech Weekly</span>
          <span data-name="track-duration">38:15</span>
          <meta data-name="duration" content="PT2295S" property="duration">
          <span data-name="track-meta" property="datePublished">February 2025</span>
        </li>
        <li data-field="track" data-rune="track" typeof="PodcastEpisode" data-rune-fields="{&quot;duration&quot;:&quot;PT2730S&quot;,&quot;url&quot;:&quot;https://example.com/ep-12&quot;,&quot;datePublished&quot;:&quot;March 2025&quot;,&quot;type&quot;:&quot;episode&quot;}" property="hasPart">
          <span data-name="track-name" data-field="name" property="name">Component Libraries at Scale</span>
          <span data-name="track-duration">45:30</span>
          <span data-name="track-meta" property="datePublished">March 2025</span>
          <div data-name="track-description">
            <p>Why component libraries stall at the second team, and what to do about it.</p>
          </div>
          <meta content="Tech Weekly" data-name="track-artist">
          <meta property="duration" content="PT2730S">
          <meta property="url" content="https://example.com/ep-12">
        </li>
      </ol>
    </section>
    podcast

    Design Systems Weekly

    1. Token ArchitectureTech Weekly38:15February 2025
    2. Component Libraries at Scale45:30March 2025

      Why component libraries stall at the second team, and what to do about it.

    <section data-field="content-section" typeof="PodcastSeries" class="rf-playlist rf-playlist--podcast" data-schema-lists="[&quot;hasPart&quot;]" data-type="podcast" data-media-position="top" data-artist="Tech Weekly" data-elevation="flat" data-rune="playlist" data-density="full">
      <div data-name="content" class="rf-playlist__content">
        <div data-name="eyebrow" data-zone="eyebrow" data-zone-layout="bar" class="rf-playlist__eyebrow">
          <span class="rf-badge" data-meta-type="category">podcast</span>
        </div>
        <header data-name="preamble" class="rf-playlist__preamble" data-section="preamble">
          <h1 id="design-systems-weekly" data-name="headline" property="name" class="rf-playlist__headline" data-section="title">Design Systems Weekly</h1>
        </header>
        <ol data-name="tracks" class="rf-playlist__tracks" data-sequence="numbered">
          <li data-field="track" typeof="PodcastEpisode" property="hasPart">
            <span data-name="track-name" property="name">Token Architecture</span>
            <span data-name="track-artist">Tech Weekly</span>
            <span data-name="track-duration">38:15</span>
            <meta data-name="duration" content="PT2295S" property="duration" />
            <span data-name="track-meta" property="datePublished">February 2025</span>
          </li>
          <li data-field="track" typeof="PodcastEpisode" class="rf-track" property="hasPart" data-elevation="flat" data-rune="track" data-density="full">
            <span data-name="track-name" data-field="name" property="name" class="rf-track__track-name">Component Libraries at Scale</span>
            <span data-name="track-duration" class="rf-track__track-duration">45:30</span>
            <span data-name="track-meta" property="datePublished" class="rf-track__track-meta">March 2025</span>
            <div data-name="track-description" class="rf-track__track-description">
              <p>Why component libraries stall at the second team, and what to do about it.</p>
            </div>
            <meta content="Tech Weekly" data-name="track-artist" class="rf-track__track-artist" />
            <meta property="duration" content="PT2730S" />
            <meta property="url" content="https://example.com/ep-12" />
          </li>
        </ol>
      </div>
    </section>

    Both forms can be mixed, and document order is preserved. Two things worth knowing:

    • Tracks must be consecutive. The track listing is collected as one run, so prose written between two tracks ends it — anything after that becomes the playlist's body rather than another track.
    • An explicit type always wins. A {% track type="song" %} inside a podcast stays a song. The attribute means what it says; the playlist only supplies a kind when the track states none.

    Attributes

    AttributeTypeRequiredDescription
    srcstring—URL of the audio or video file for this track.
    artiststring—Performer or creator name for this track.
    durationstring—Track length in m:ss, h:mm:ss, or ISO 8601 duration format.
    numbernumber—Position number of the track in its parent listing.
    datestring—Publication or release date for the track.
    urlstring—External link to the track on a streaming platform or website.
    type"song" | "episode" | "chapter" | "talk" | "video"—Media category: song, episode, chapter, talk, or video.

    Universal attributes

    bg

    The background layer (SPEC-088): image, video, gradient, flat overlay wash and legibility scrim, in a single injected layer behind the rune's content.

    AttributeTypeRequiredDescription
    bgstring—Background preset applied to this block
    bg-fromstring—Gradient start colour — a semantic token name (→ var(--rf-color-*))
    bg-gradient"to-t" | "to-b" | "to-l" | "to-r" | "to-tr" | "to-br" | "to-bl" | "to-tl"—Gradient direction (bounded named set)
    bg-gradient-type"linear" | "radial" | "conic"—Gradient type
    bg-tostring—Gradient end colour — a semantic token name
    bg-viastring—Optional middle gradient stop — a semantic token name
    scrim"top" | "bottom" | "left" | "right" | "none"—Scrim direction (heaviest edge); presence turns the scrim on, "none" opts out of the default cover scrim
    scrim-blur"none" | "sm" | "md" | "lg"—Frost scrim blur amount
    scrim-strength"sm" | "md" | "lg"—Gradient scrim strength
    scrim-tone"dark" | "light"—Whether the scrim darkens (for light text) or lightens (for dark text)
    scrim-type"gradient" | "frost"—Scrim treatment: gradient (default) or frost (backdrop blur)
    elevation

    The chrome/depth ladder (SPEC-107). The skin maps each rung to a chrome bundle by attribute, so there is no BEM class.

    AttributeTypeRequiredDescription
    elevation"sunken" | "flush" | "flat" | "raised" | "floating" | "overlay" | "none" | "sm" | "md" | "lg"—Surface depth on the SPEC-107 ladder (sunken→overlay); none/sm/md/lg are deprecated aliases
    inset

    Internal padding override.

    AttributeTypeRequiredDescription
    inset"flush" | "tight" | "default" | "loose" | "breathe"—Inner padding of this block
    motion

    Scroll-reveal entrance (SPEC-105). The author declares the character, the theme owns the choreography, a behaviour owns the timing.

    AttributeTypeRequiredDescription
    reveal"none" | "fade" | "slide" | "scale" | "blur"—Scroll-reveal entrance character (none|fade|slide|scale|blur); the theme owns the choreography
    staggerboolean—Cascade this block's items in as it reveals (no-op on single-child runes)
    spacing

    Block-level rhythm override.

    AttributeTypeRequiredDescription
    spacing"flush" | "tight" | "default" | "loose" | "breathe"—Vertical spacing above and below this block
    substrate

    Generated pattern fills (SPEC-087). Markers only — the engine sets the attributes and cell/opacity custom properties, CSS draws the pattern.

    AttributeTypeRequiredDescription
    substrate"dots" | "grid" | "lines" | "cross" | "checker" | "none"—Generated surface pattern
    substrate-fill"inherit" | "inset"—Surface fill the pattern sits on (full colour stays with tint)
    substrate-opacity"sm" | "md" | "lg"—Pattern ink strength
    substrate-size"sm" | "md" | "lg"—Pattern cell size
    substrate-target"self" | "media"—Which surface the pattern fills (overrides the rune/theme default)
    tint

    Per-rune colour override (SPEC-053): a named tint from the theme registry, with inline per-token overrides layered on top.

    AttributeTypeRequiredDescription
    tintstring—Color tint preset applied to this block
    tint-mode"auto" | "dark" | "light"—Whether the tint adapts to auto, dark, or light mode
    width

    The track a block rune occupies.

    AttributeTypeRequiredDescription
    width"compact" | "narrow" | "content" | "wide" | "full"—Maximum width constraint for this block
    Not availableWhy
    dropcap, readingthis rune declares no prose body
    framethis rune declares neither a `frameTarget` nor a media section
    prominencethis rune has no page-section header