This rune is part of @refrakt-md/media. Install with npm install @refrakt-md/media and add "@refrakt-md/media" to the packages array in your refrakt.config.json.
Playlist
Curated track listings for albums, podcasts, audiobooks, and mixes. A heading becomes the playlist title, an image becomes the cover art, a paragraph becomes the description, and a list becomes the track listing. Bold text in each list item is the track name, parenthetical text is the duration, and italic text is the per-track artist.
Basic usage
An album with an artist and track listing.
{% playlist type="album" artist="Pink Floyd" layout="split" %}
# The Dark Side of the Moon
A landmark progressive rock album exploring themes of time, death, and madness.
- **Speak to Me** (1:13)
- **Breathe** (2:43)
- **On the Run** (3:36)
- **Time** (7:05)
- **The Great Gig in the Sky** (4:44)
---

{% /playlist %}<section data-field="content-section" data-rune="playlist" typeof="MusicPlaylist">
<meta content="album" data-field="type">
<meta content="split" data-field="layout">
<meta content="1 1" data-field="ratio">
<meta content="top" data-field="valign">
<meta content="Pink Floyd" data-field="artist" property="byArtist">
<div data-name="media">
<img src="https://assets.refrakt.md/playlist-dark-side-of-the-moon.png" alt="The Dark Side of the Moon" property="image">
</div>
<div data-name="content">
<header>
<h1 id="the-dark-side-of-the-moon" data-name="headline" property="name">The Dark Side of the Moon</h1>
<p data-name="blurb">A landmark progressive rock album exploring themes of time, death, and madness.</p>
</header>
<ol data-name="tracks">
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Speak to Me</span>
<span data-name="track-artist" property="byArtist">Pink Floyd</span>
<span data-name="track-duration">1:13</span>
<meta property="duration" content="PT73S">
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Breathe</span>
<span data-name="track-artist" property="byArtist">Pink Floyd</span>
<span data-name="track-duration">2:43</span>
<meta property="duration" content="PT163S">
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">On the Run</span>
<span data-name="track-artist" property="byArtist">Pink Floyd</span>
<span data-name="track-duration">3:36</span>
<meta property="duration" content="PT216S">
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Time</span>
<span data-name="track-artist" property="byArtist">Pink Floyd</span>
<span data-name="track-duration">7:05</span>
<meta property="duration" content="PT425S">
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">The Great Gig in the Sky</span>
<span data-name="track-artist" property="byArtist">Pink Floyd</span>
<span data-name="track-duration">4:44</span>
<meta property="duration" content="PT284S">
</li>
</ol>
</div>
</section>
The Dark Side of the Moon
A landmark progressive rock album exploring themes of time, death, and madness.
- Speak to MePink Floyd1:13
- BreathePink Floyd2:43
- On the RunPink Floyd3:36
- TimePink Floyd7:05
- The Great Gig in the SkyPink Floyd4:44
<section data-field="content-section" typeof="MusicPlaylist" class="rf-playlist rf-playlist--album rf-playlist--split" data-type="album" data-layout="split" data-ratio="1 1" data-valign="top" data-gap="default" data-artist="Pink Floyd" data-rune="playlist" data-density="full" data-media-position="top" style="--split-ratio: 1fr 1fr; --split-valign: start; --split-gap: var(--rf-spacing-md)">
<div data-name="meta" class="rf-playlist__meta" data-section="header">
<span data-name="type-badge" data-meta-type="category" data-meta-rank="primary" class="rf-playlist__type-badge">album</span>
</div>
<div data-name="media" class="rf-playlist__media" data-section="media" data-media="cover">
<img src="https://assets.refrakt.md/playlist-dark-side-of-the-moon.png" alt="The Dark Side of the Moon" property="image" />
</div>
<div data-name="content" class="rf-playlist__content">
<header data-name="preamble" class="rf-playlist__preamble" data-section="preamble">
<h1 id="the-dark-side-of-the-moon" data-name="headline" property="name" class="rf-playlist__headline" data-section="title">The Dark Side of the Moon</h1>
<p data-name="blurb" class="rf-playlist__blurb" data-section="description">A landmark progressive rock album exploring themes of time, death, and madness.</p>
</header>
<ol data-name="tracks" class="rf-playlist__tracks" data-sequence="numbered">
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Speak to Me</span>
<span data-name="track-artist" property="byArtist">Pink Floyd</span>
<span data-name="track-duration">1:13</span>
<meta property="duration" content="PT73S" />
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Breathe</span>
<span data-name="track-artist" property="byArtist">Pink Floyd</span>
<span data-name="track-duration">2:43</span>
<meta property="duration" content="PT163S" />
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">On the Run</span>
<span data-name="track-artist" property="byArtist">Pink Floyd</span>
<span data-name="track-duration">3:36</span>
<meta property="duration" content="PT216S" />
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Time</span>
<span data-name="track-artist" property="byArtist">Pink Floyd</span>
<span data-name="track-duration">7:05</span>
<meta property="duration" content="PT425S" />
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">The Great Gig in the Sky</span>
<span data-name="track-artist" property="byArtist">Pink Floyd</span>
<span data-name="track-duration">4:44</span>
<meta property="duration" content="PT284S" />
</li>
</ol>
</div>
</section>Podcast
Use type="podcast" for episodic content with dates.
{% playlist type="podcast" %}
# Design Systems Weekly
A podcast about building and scaling design systems.
- **Component Libraries at Scale** (45:30) — March 2025
- **Token Architecture** (38:15) — February 2025
- **Accessibility First** (42:00) — January 2025
{% /playlist %}<section data-field="content-section" data-rune="playlist" typeof="MusicPlaylist">
<meta content="podcast" data-field="type">
<meta content="stacked" data-field="layout">
<div data-name="content">
<header>
<h1 id="design-systems-weekly" data-name="headline" property="name">Design Systems Weekly</h1>
<p data-name="blurb">A podcast about building and scaling design systems.</p>
</header>
<ol data-name="tracks">
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Component Libraries at Scale</span>
<span data-name="track-duration">45:30</span>
<meta property="duration" content="PT2730S">
<span data-name="track-meta" property="datePublished">March 2025</span>
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Token Architecture</span>
<span data-name="track-duration">38:15</span>
<meta property="duration" content="PT2295S">
<span data-name="track-meta" property="datePublished">February 2025</span>
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Accessibility First</span>
<span data-name="track-duration">42:00</span>
<meta property="duration" content="PT2520S">
<span data-name="track-meta" property="datePublished">January 2025</span>
</li>
</ol>
</div>
</section>Design Systems Weekly
A podcast about building and scaling design systems.
- Component Libraries at Scale45:30March 2025
- Token Architecture38:15February 2025
- Accessibility First42:00January 2025
<section data-field="content-section" typeof="MusicPlaylist" class="rf-playlist rf-playlist--podcast rf-playlist--stacked" data-type="podcast" data-layout="stacked" data-ratio="1 1" data-valign="top" data-gap="default" data-rune="playlist" data-density="full" data-media-position="top" style="--split-ratio: 1fr 1fr; --split-valign: start; --split-gap: var(--rf-spacing-md)">
<div data-name="meta" class="rf-playlist__meta" data-section="header">
<span data-name="type-badge" data-meta-type="category" data-meta-rank="primary" class="rf-playlist__type-badge">podcast</span>
</div>
<div data-name="content" class="rf-playlist__content">
<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>
<p data-name="blurb" class="rf-playlist__blurb" data-section="description">A podcast about building and scaling design systems.</p>
</header>
<ol data-name="tracks" class="rf-playlist__tracks" data-sequence="numbered">
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Component Libraries at Scale</span>
<span data-name="track-duration">45:30</span>
<meta property="duration" content="PT2730S" />
<span data-name="track-meta" property="datePublished">March 2025</span>
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Token Architecture</span>
<span data-name="track-duration">38:15</span>
<meta property="duration" content="PT2295S" />
<span data-name="track-meta" property="datePublished">February 2025</span>
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Accessibility First</span>
<span data-name="track-duration">42:00</span>
<meta property="duration" content="PT2520S" />
<span data-name="track-meta" property="datePublished">January 2025</span>
</li>
</ol>
</div>
</section>Per-track artists
When tracks have different artists, use italic text for per-track attribution. Omit the artist attribute to avoid a default.
{% playlist type="mix" %}
# Summer Vibes 2025
- **Midnight City** (4:03) *M83*
- **Electric Feel** (3:49) *MGMT*
- **Do I Wanna Know?** (4:32) *Arctic Monkeys*
- **Intro** (4:18) *The xx*
{% /playlist %}<section data-field="content-section" data-rune="playlist" typeof="MusicPlaylist">
<meta content="mix" data-field="type">
<meta content="stacked" data-field="layout">
<div data-name="content">
<header>
<h1 id="summer-vibes-2025" data-name="headline" property="name">Summer Vibes 2025</h1>
</header>
<ol data-name="tracks">
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Midnight City</span>
<span data-name="track-artist" property="byArtist">M83</span>
<span data-name="track-duration">4:03</span>
<meta property="duration" content="PT243S">
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Electric Feel</span>
<span data-name="track-artist" property="byArtist">MGMT</span>
<span data-name="track-duration">3:49</span>
<meta property="duration" content="PT229S">
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Do I Wanna Know?</span>
<span data-name="track-artist" property="byArtist">Arctic Monkeys</span>
<span data-name="track-duration">4:32</span>
<meta property="duration" content="PT272S">
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Intro</span>
<span data-name="track-artist" property="byArtist">The xx</span>
<span data-name="track-duration">4:18</span>
<meta property="duration" content="PT258S">
</li>
</ol>
</div>
</section>Summer Vibes 2025
- Midnight CityM834:03
- Electric FeelMGMT3:49
- Do I Wanna Know?Arctic Monkeys4:32
- IntroThe xx4:18
<section data-field="content-section" typeof="MusicPlaylist" class="rf-playlist rf-playlist--mix rf-playlist--stacked" data-type="mix" data-layout="stacked" data-ratio="1 1" data-valign="top" data-gap="default" data-rune="playlist" data-density="full" data-media-position="top" style="--split-ratio: 1fr 1fr; --split-valign: start; --split-gap: var(--rf-spacing-md)">
<div data-name="meta" class="rf-playlist__meta" data-section="header">
<span data-name="type-badge" data-meta-type="category" data-meta-rank="primary" class="rf-playlist__type-badge">mix</span>
</div>
<div data-name="content" class="rf-playlist__content">
<header data-name="preamble" class="rf-playlist__preamble" data-section="preamble">
<h1 id="summer-vibes-2025" data-name="headline" property="name" class="rf-playlist__headline" data-section="title">Summer Vibes 2025</h1>
</header>
<ol data-name="tracks" class="rf-playlist__tracks" data-sequence="numbered">
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Midnight City</span>
<span data-name="track-artist" property="byArtist">M83</span>
<span data-name="track-duration">4:03</span>
<meta property="duration" content="PT243S" />
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Electric Feel</span>
<span data-name="track-artist" property="byArtist">MGMT</span>
<span data-name="track-duration">3:49</span>
<meta property="duration" content="PT229S" />
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Do I Wanna Know?</span>
<span data-name="track-artist" property="byArtist">Arctic Monkeys</span>
<span data-name="track-duration">4:32</span>
<meta property="duration" content="PT272S" />
</li>
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Intro</span>
<span data-name="track-artist" property="byArtist">The xx</span>
<span data-name="track-duration">4:18</span>
<meta property="duration" content="PT258S" />
</li>
</ol>
</div>
</section>With chapter markers
Tracks can include nested lists for chapter markers or lyrics. Use content="chapters" or content="lyrics" to force the display mode, or leave it as auto for automatic detection.
{% playlist type="podcast" content="chapters" %}
# Tech Talk: Web Components
- **Episode 42: Shadow DOM Deep Dive** (1:02:15)
1. **Introduction** (0:00) Overview of today's topic
2. **What is Shadow DOM?** (3:45) Core concepts explained
3. **Styling strategies** (18:30) CSS custom properties and parts
4. **Q&A** (45:00) Listener questions
{% /playlist %}<section data-field="content-section" data-rune="playlist" typeof="MusicPlaylist">
<meta content="podcast" data-field="type">
<meta content="stacked" data-field="layout">
<div data-name="content">
<header>
<h1 id="tech-talk:-web-components" data-name="headline" property="name">Tech Talk: Web Components</h1>
</header>
<ol data-name="tracks">
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Episode 42: Shadow DOM Deep Dive</span>
<span data-name="track-duration">1:02:15</span>
<meta property="duration" content="PT3735S">
<ol data-name="chapters">
<li data-time="0">
<span data-name="chapter-name">Introduction</span>
<span data-name="chapter-time">0:00</span>
</li>
<li data-time="225">
<span data-name="chapter-name">What is Shadow DOM?</span>
<span data-name="chapter-time">3:45</span>
</li>
<li data-time="1110">
<span data-name="chapter-name">Styling strategies</span>
<span data-name="chapter-time">18:30</span>
</li>
<li data-time="2700">
<span data-name="chapter-name">Q&A</span>
<span data-name="chapter-time">45:00</span>
</li>
</ol>
</li>
</ol>
</div>
</section>Tech Talk: Web Components
- Episode 42: Shadow DOM Deep Dive1:02:15
- Introduction0:00
- What is Shadow DOM?3:45
- Styling strategies18:30
- Q&A45:00
<section data-field="content-section" typeof="MusicPlaylist" class="rf-playlist rf-playlist--podcast rf-playlist--stacked" data-type="podcast" data-layout="stacked" data-ratio="1 1" data-valign="top" data-gap="default" data-rune="playlist" data-density="full" data-media-position="top" style="--split-ratio: 1fr 1fr; --split-valign: start; --split-gap: var(--rf-spacing-md)">
<div data-name="meta" class="rf-playlist__meta" data-section="header">
<span data-name="type-badge" data-meta-type="category" data-meta-rank="primary" class="rf-playlist__type-badge">podcast</span>
</div>
<div data-name="content" class="rf-playlist__content">
<header data-name="preamble" class="rf-playlist__preamble" data-section="preamble">
<h1 id="tech-talk:-web-components" data-name="headline" property="name" class="rf-playlist__headline" data-section="title">Tech Talk: Web Components</h1>
</header>
<ol data-name="tracks" class="rf-playlist__tracks" data-sequence="numbered">
<li typeof="MusicRecording" data-field="track" property="track">
<span data-name="track-name" property="name">Episode 42: Shadow DOM Deep Dive</span>
<span data-name="track-duration">1:02:15</span>
<meta property="duration" content="PT3735S" />
<ol data-name="chapters">
<li data-time="0">
<span data-name="chapter-name">Introduction</span>
<span data-name="chapter-time">0:00</span>
</li>
<li data-time="225">
<span data-name="chapter-name">What is Shadow DOM?</span>
<span data-name="chapter-time">3:45</span>
</li>
<li data-time="1110">
<span data-name="chapter-name">Styling strategies</span>
<span data-name="chapter-time">18:30</span>
</li>
<li data-time="2700">
<span data-name="chapter-name">Q&A</span>
<span data-name="chapter-time">45:00</span>
</li>
</ol>
</li>
</ol>
</div>
</section>Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
type | string | album | Playlist type: album, podcast, audiobook, series, or mix |
artist | string | — | Default artist applied to all tracks |
player | boolean | — | Show an embedded audio player |
content | string | auto | Cue point display: auto, lyrics, or chapters |
id | string | — | Identifier for connecting an audio player rune |
Section header
Playlist supports an optional eyebrow, headline, and blurb above the playlist content. Place a short paragraph or heading before the main content to use them. See Page sections for the full syntax.
Common attributes
All block runes share these attributes for layout and theming.
| Attribute | Type | Default | Description |
|---|---|---|---|
width | string | content | Page grid width: content, wide, or full |
spacing | string | — | Vertical spacing: flush, tight, default, loose, or breathe |
inset | string | — | Horizontal padding: flush, tight, default, loose, or breathe |
tint | string | — | Named colour tint from theme configuration |
tint-mode | string | auto | Colour scheme override: auto, dark, or light |
bg | string | — | Named background preset from theme configuration |