Index: src/assets/js/mod/post-edit.js
===================================================================
--- src/assets/js/mod/post-edit.js	(revision 25dd08f3833da4deb81ef7a027a7e4382dbc5181)
+++ src/assets/js/mod/post-edit.js	(revision 8e1af9c0d284f99d5dbe69c16f2f5242239f9e4e)
@@ -8,5 +8,5 @@
 // Dezelfde regel die de server gebruikt -- zie shared/post-music-type.js voor
 // waarom hij daar staat en niet twee keer.
-import { afleidenUitInsluitingen } from '../shared/post-music-type.js';
+import { afleidenUitInsluitingen, SOORTEN } from '../shared/post-music-type.js';
 
 // De oude inline scripts draaiden bij ELKE render; een module draait zijn
@@ -1020,5 +1020,5 @@
     // alleen als ijkpunt onthouden. Anders zou een oude post van type veranderen
     // door hem te bekijken.
-    const VOLGBAAR = new Set(['post', 'album', 'playlist', 'audio']);
+    const VOLGBAAR = new Set(['post', 'album', 'playlist', 'mixtape', 'audio']);
     const kindVan = new Map();
     let vorigeAfleiding = null;
@@ -1028,5 +1028,9 @@
       .then((j) => {
         if (j && j.ok && Array.isArray(j.playlists)) {
-          for (const p of j.playlists) kindVan.set(p.id, p.kind === 'playlist' ? 'playlist' : 'album');
+          // De soort ZOALS HIJ IS. Dit was `=== 'playlist' ? 'playlist' : 'album'`,
+          // en dan ziet de editor een mixtape als album terwijl de server hem
+          // als mixtape opslaat: het type verspringt onder je handen bij het
+          // bewaren. SOORTEN is dezelfde lijst die de server gebruikt.
+          for (const p of j.playlists) kindVan.set(p.id, SOORTEN.includes(p.kind) ? p.kind : 'album');
         }
       })
Index: src/config/post-types.js
===================================================================
--- src/config/post-types.js	(revision 25dd08f3833da4deb81ef7a027a7e4382dbc5181)
+++ src/config/post-types.js	(revision 8e1af9c0d284f99d5dbe69c16f2f5242239f9e4e)
@@ -13,8 +13,13 @@
  * zo'n post mag zijn type niet stilzwijgend weggooien -- tot de backfill hem
  * heeft omgezet. Daarna kan audio hier weg.
+ *
+ * MIXTAPE erbij (Robins idee, 21-8): een bandje, samengesteld uit de nummers
+ * van een playlist, dat alleen vooruit en achteruit speelt. Het draagt muziek,
+ * dus het deelt het muziekpaneel en de afleiding met album en playlist -- het
+ * verschil zit in de playlist die je insluit, niet in wat je hier uploadt.
  */
 
 /** Types die een gebruiker in de editor kan kiezen. */
-export const KEUZE_TYPES = ['post', 'foto', 'video', 'album', 'playlist'];
+export const KEUZE_TYPES = ['post', 'foto', 'video', 'album', 'playlist', 'mixtape'];
 
 /** Alles wat in de kolom posts.type mag staan, inclusief wat er historisch is. */
@@ -22,3 +27,3 @@
 
 /** De types die muziek dragen -- ze delen hetzelfde paneel en dezelfde afleiding. */
-export const MUZIEK_TYPES = new Set(['album', 'playlist', 'audio']);
+export const MUZIEK_TYPES = new Set(['album', 'playlist', 'audio', 'mixtape']);
Index: src/services/AudioEmbedService.js
===================================================================
--- src/services/AudioEmbedService.js	(revision 25dd08f3833da4deb81ef7a027a7e4382dbc5181)
+++ src/services/AudioEmbedService.js	(revision 8e1af9c0d284f99d5dbe69c16f2f5242239f9e4e)
@@ -10,4 +10,8 @@
  * </figure>
  */
+
+// Dezelfde lijst soorten als de server en de editor gebruiken. Zie
+// assets/js/shared/post-music-type.js: die module is puur, dus hij mag hier.
+import { SOORTEN } from '../assets/js/shared/post-music-type.js';
 
 // "Open in" icons (brand-colored via CSS .pat-link--).
@@ -538,6 +542,12 @@
 
       const albumDomId = 'album-' + id;
-      const kind = (pl.kind === 'playlist') ? 'playlist' : 'album';
-      const kindLabel = kind === 'playlist' ? '📃 Playlist' : '💿 Album';
+      // De soort zoals hij is opgeslagen. Stond hier als ternair met twee
+      // uitkomsten, en dan draagt een mixtape het jasje en het woord van een
+      // album -- dezelfde vorm die op vier andere plekken al misging.
+      // DE SPELER IS ER NOG NIET. Een mixtape rendert voorlopig als de gewone
+      // lijst; wat hier af is, is dat hij zichzelf goed noemt.
+      const kind = SOORTEN.includes(pl.kind) ? pl.kind : 'album';
+      const KIND_LABEL = { album: '💿 Album', playlist: '📃 Playlist', mixtape: '📼 Mixtape' };
+      const kindLabel = KIND_LABEL[kind] || KIND_LABEL.album;
       const titleH  = this.escape(pl.title || 'Naamloos');
       const artistH = this.escape(pl.artist || '');
@@ -638,5 +648,5 @@
             data-pcms-track-url="${firstUrl}"
             data-pcms-album-id="${albumDomId}"
-            aria-label="Speel ${kind === 'playlist' ? 'playlist' : 'album'}">
+            aria-label="Speel ${kind}">
       ${coverH
         ? `<span class="post-album-cover" style="background-image:url('${coverH}')"></span>`
Index: src/services/i18n.js
===================================================================
--- src/services/i18n.js	(revision 25dd08f3833da4deb81ef7a027a7e4382dbc5181)
+++ src/services/i18n.js	(revision 8e1af9c0d284f99d5dbe69c16f2f5242239f9e4e)
@@ -770,5 +770,5 @@
     'pedit.type_audio': 'Audio',
     'pedit.type_album': 'Album',
-    'pedit.type_playlist': 'Playlist',
+    'pedit.type_playlist': 'Playlist', 'pedit.type_mixtape': 'Mixtape',
     'pedit.s_type': 'Wat voor post?',
     'pedit.audio_up_drop': 'Sleep audio hierheen of klik om te kiezen',
@@ -1779,5 +1779,5 @@
     'pedit.type_audio': 'Audio',
     'pedit.type_album': 'Album',
-    'pedit.type_playlist': 'Playlist',
+    'pedit.type_playlist': 'Playlist', 'pedit.type_mixtape': 'Mixtape',
     'pedit.s_type': 'What kind of post?',
     'pedit.audio_up_drop': 'Drop audio here or click to choose',
@@ -2788,5 +2788,5 @@
     'pedit.type_audio': 'Audio',
     'pedit.type_album': 'Album',
-    'pedit.type_playlist': 'Playlist',
+    'pedit.type_playlist': 'Playlist', 'pedit.type_mixtape': 'Mixtape',
     'pedit.s_type': 'Was für ein Beitrag?',
     'pedit.audio_up_drop': 'Audio hierher ziehen oder klicken',
Index: src/views/pages/post-edit.ejs
===================================================================
--- src/views/pages/post-edit.ejs	(revision 25dd08f3833da4deb81ef7a027a7e4382dbc5181)
+++ src/views/pages/post-edit.ejs	(revision 8e1af9c0d284f99d5dbe69c16f2f5242239f9e4e)
@@ -24,10 +24,10 @@
         Foto → cover/insert hint. %>
     <% var ptype = post.type || 'post'; %>
-    <% var TYPE_ICONS = { post: '📝', foto: '📷', video: '🎬', album: '💿', playlist: '📃', audio: '🎵' }; %>
+    <% var TYPE_ICONS = { post: '📝', foto: '📷', video: '🎬', album: '💿', playlist: '📃', mixtape: '📼', audio: '🎵' }; %>
     <%# Audio is geen keuze meer (shaer-cyg): alles wat muziek is landt op Album
         of Playlist. De knop blijft alleen staan zolang deze post nog audio IS,
         zodat een oude post niet stilzwijgend van type verandert bij het openen. %>
     <% var TYPES = (typeof keuzeTypes !== 'undefined' && keuzeTypes.length)
-                     ? keuzeTypes.slice() : ['post','foto','video','album','playlist']; %>
+                     ? keuzeTypes.slice() : ['post','foto','video','album','playlist','mixtape']; %>
     <% if (ptype === 'audio' && TYPES.indexOf('audio') < 0) TYPES.push('audio'); %>
     <section class="pe-card pe-type-card">
@@ -45,7 +45,8 @@
 
       <%# Muziek: inline upload (transcodes + drops [[track]] into the post).
-          Album en Playlist delen dit paneel -- het verschil zit in de playlist,
-          niet in wat je hier uploadt. Audio staat er alleen nog voor oude posts. %>
-      <div class="pe-type-panel" data-panel="album playlist audio" hidden>
+          Album, Playlist en Mixtape delen dit paneel -- het verschil zit in de
+          playlist die je insluit, niet in wat je hier uploadt. Audio staat er
+          alleen nog voor oude posts. %>
+      <div class="pe-type-panel" data-panel="album playlist mixtape audio" hidden>
         <div class="pe-audio-up" id="pe-audio-drop" tabindex="0" role="button" aria-label="<%= t('pedit.audio_up_drop') %>">
           <input type="file" id="pe-audio-file" accept="audio/*,.mp3,.m4a,.ogg,.opus,.flac,.wav" multiple hidden>
Index: src/views/shell.ejs
===================================================================
--- src/views/shell.ejs	(revision 25dd08f3833da4deb81ef7a027a7e4382dbc5181)
+++ src/views/shell.ejs	(revision 8e1af9c0d284f99d5dbe69c16f2f5242239f9e4e)
@@ -505,5 +505,5 @@
   // Eén nummer voor de hele map. Te vaak bumpen kost één download; te weinig
   // bumpen kost een bugfix die nooit aankomt.
-  var MOD_V = 50;
+  var MOD_V = 51;
 
   // name -> 1 (aan het laden) of de module-namespace (geladen). Een module
