Ik heb de technische stack voor ⌘+P: The App Podcast gebouwd zoals een app-ontwikkelaar een app bouwt, niet zoals een podcaster Spotify for Podcasters aan elkaar plakt. Dit gebeurt er als je RSS als product behandelt.
De eerste afleveringen van ⌘+P heb ik opgenomen bij Podspace in Parijs: een echte cabine, echte microfoons en een echte geluidstechnicus die niet doet alsof hij begrijpt wat je bedoelt met AES-bus en monitoruitgang. Monteren doe ik op mijn Mac in Final Cut Pro. Laten we eerlijk zijn: een Apple-ontwikkelaar die zijn podcast in Premiere monteert, is als een Italiaanse chef die room in de carbonara doet. Je proeft het, en mensen oordelen (terecht).
Wat ik had onderschat: opnemen en monteren is ongeveer 20% van het werk. De rest is distributie. En de distributie van podcasts is in 2026 een veel verraderlijker terrein dan het lijkt.
Dit artikel is de technische autopsie van de stack die ik voor ⌘+P heb gebouwd: drie verschillende RSS-feeds, een headless CMS, een eigen CDN, een adaptieve video-encoder en een uitgesproken obsessie voor Apple Podcasts. Als je een serieuze podcast wilt starten zonder Acast of Spotify for Podcasters, is dit waarschijnlijk het meest uitvoerige Franstalige stuk over het onderwerp dat je dit jaar zult vinden.
De keuze: RSS als product behandelen
De vraag die me zes maanden omwegen heeft bespaard: wil ik dat mijn podcast op het platform van iemand anders leeft, of bij mij?
Spotify for Podcasters (voorheen Anchor) biedt een ogenschijnlijk onverslaanbare deal: je uploadt je .wav, zij maken een RSS-feed, hosten de audio en verspreiden die naar Apple Podcasts. Gratis. De valkuil is natuurlijk dat de RSS-feed van hen is. Als je later van hostingprovider wilt wisselen, neem je je archief mee, maar verlies je je statistieken, canonieke links en soms je geloofwaardigheid bij directories die je via de oorspronkelijke Anchor-feed hebben geïndexeerd. Acast werkt volgens hetzelfde principe, met een professionelere UX en een maandelijkse rekening.
Ik koos voor het tegenovergestelde. De RSS-feed is een endpoint dat ik beheer, op mijn domein, gegenereerd door mijn code vanuit mijn enige bron van waarheid. Apple, Spotify, Pocket Casts, Castro, Overcast: iedereen abonneert zich op mijn feed. Als Spotify morgen lastig gaat doen, verander ik twee regels XML, niet mijn hostingprovider.
Die keuze heeft gevolgen: als ik RSS beheer, moet ik ook alles eromheen beheren. De CMS, opslag voor audio en video, encoding, CDN, hoofdstukken, Podcasting 2.0-metadata en varianten per platform. Meer werk, maar ook oneindig leerzamer; de stack die eruit voortkomt is verrassend licht.
De bron van waarheid: Hygraph
De inhoud staat in Hygraph, een headless CMS op GraphQL. Mijn model PodcastEpisode bevat alles wat je verwacht: seizoen, afleveringsnummer, gasten, hoofdstukken, audio- en video-URL’s, rich-text-show notes, datums en de vlaggen isPrivate en showOnHomepage. Gasten zijn aparte entiteiten, PodcastGuest, met een eigen rich-text-biografie en linkedinUrl. Eenzelfde gast kan terugkomen en een biografie in twee records dupliceren is zo’n zonde waar je zes maanden later spijt van krijgt. De video staat in een herbruikbare entiteit Video waarnaar PodcastEpisode verwijst. Daar kom ik zo op terug, want dat is een centraal onderdeel geworden.
De website draait op Next.js 16 App Router met Turbopack en Tailwind v4, uitgerold op Clever Cloud met automatische redeploy na een Git-push. De GraphQL-laag gebruikt Apollo Client. i18n loopt via next-intl met zeven locales (en, fr, de, it, nl, ar-AE, ar-SA) en localePrefix: 'as-needed'. Een belangrijk detail: de podcast is Franstalig. Dus ook als een bezoeker /de/podcast opent, dwingt de RSS-feed op Hygraph locales: ['fr', 'en'] af. De RSS is niet meertalig, maar van nature tweetalig. Apple Podcasts verwacht dat, ongeacht waar je klikt.
Opslag: Clever Cloud Cellar achter Cloudflare
Mediabestanden (audio, video, covers) staan op Clever Cloud Cellar, hun S3-compatibele opslag, achter een Cloudflare-CDN op cdn2.clementsauvage.me. Die keuze is niet vanzelfsprekend, dus hier is mijn uitleg.
Mux is verleidelijk als je alles wilt uitbesteden: encoding, streaming, distributie. Maar bij een videopodcast van soms 250 MB per aflevering lopen de Mux-kosten snel uit de hand als RSS-downloads zich opstapelen. Cellar heeft voorspelbare kosten per gigabyte, native byte-range (getest: Range: bytes=0-1023 geeft HTTP 206 terug) en de app draait al op Clever Cloud, dus de latency tussen services is verwaarloosbaar. Byte-range is onmisbaar: podcastclients downloaden een bestand nooit in één keer, ze streamen geleidelijk en verwachten dat ze verder kunnen gaan waar ze waren gebleven.
Mux gebruik ik nog wel, maar alleen voor webstreaming: adaptieve HLS via playbackId, in de browser afgespeeld met mux-player-react op de afleveringspagina. De video op de site krijgt een professionele encoding ladder van Mux; de H.264-MP4-master op Cellar dient uitsluitend voor RSS-distributie. Twee toepassingen, twee bestanden, twee strategieën. Dat kost meer opslag, maar ieder bestand doet zijn werk zonder concessies.
De importadmin: eerst de context, dan de inhoud
Ik heb een privé-endpoint, een tool die een ruwe .mp3 uit Final Cut en een JPEG-cover aanneemt en in Hygraph een conceptaflevering aanmaakt die klaarstaat voor goedkeuring.
De UX-les die me een herbouw kostte: de context moet vóór de inhoud komen. In de eerste versie stonden de bestanden bovenaan en de velden Seizoen / Aflevering / Type / Taal onderaan. Logisch voor een formulier, rampzalig voor de pipeline, want die vier velden bepalen het uploadpad in Cellar (cmd-p-podcast/s{n}/episode-{m}/audio.wav). Als je de bestanden dropt voordat je het seizoen kiest, weigert de server de upload of gaat hij gokken, en belandt aflevering 12 in de map van aflevering 11. Ik heb de volgorde omgedraaid: eerst een 2×2-raster met de context, daarna het dropgebied. Het formulier staat uploads pas toe als alle vier velden zijn ingevuld. Die fout maak ik niet meer.
De upload zelf is een presigned S3-multipart-upload vanuit de browser: de server maakt ondertekende URL’s per chunk van 64 MB, de browser doet de PUT rechtstreeks naar Cellar en de server ontvangt de ETags om de multipart-upload aan het eind samen te voegen. Een eigen endpoint configureert de CORS van de bucket met ExposeHeaders: ETag. Zonder die instelling kan de browser de ETags niet uitlezen en mislukt de voltooiing stilletjes. Een detail dat je niet in algemene S3-documentatie vindt.
Voor teasers gebruik ik een eigen naamconventie: een alfanumeriek achtervoegsel van zeven tekens uit een alfabet van 55 tekens (zonder 0, 1, I, O, i, l en o om visuele verwarring te voorkomen). De sleutel wordt opnieuw gegenereerd zodra je de TEASER-modus inschakelt en wordt gedeeld door de drie bestanden van dezelfde teaser (audio/video/cover). Zo kunnen meerdere teasers voor hetzelfde seizoen en dezelfde aflevering naast elkaar bestaan zonder elkaar te overschrijven, en kun je de URL telefonisch spellen. Drie regels code besparen je een ongemakkelijk gesprek met een gast omdat je diens teaser per ongeluk met een andere hebt overschreven.
Na de upload verloopt de volledige pipeline zo: Mux neemt de video in en maakt een asset, playback-ID en thumbnail op een gekozen tijdstip. AssemblyAI transcribeert de audio en genereert automatisch hoofdstukken. In de admin verschijnt een bewerkvriendelijke preview met korte beschrijving, show notes en hoofdstukken (titel / begin / einde). Alles is aanpasbaar voordat het naar Hygraph wordt geschreven. Na goedkeuring maken we een PodcastEpisode-concept met een stabiele UUID als episodeGuid, de verwijzing naar het Mux-asset, het AssemblyAI-transcript en hoofdstukken die apart blijven van de show-notes-blob. De website-UI en het <podcast:chapters>-JSON bieden die los van elkaar aan; samenvoegen zou een architectuurfout zijn waar je bij elke update voor betaalt.
De RSS: drie feeds, drie strategieën
Nu wordt het interessant. Apple Podcasts krijgt voorrang. Dat is de hoofdfeed, de enige die nieuwe afleveringen meteen publiceert en de enige met alle Podcasting 2.0-functies. Spotify en de rest volgen later.
Concreet zijn er drie endpoints:
/podcast/rss— hoofdfeed, nieuwe afleveringen meteen, volledige Podcasting 2.0/podcast/rss/late— dezelfde inhoud met drie dagen vertraging/podcast/rss/spotify— alleen audio, drie dagen vertraging en strikte Spotify-compatibiliteit
Die vertraging van drie dagen is een bewuste redactionele keuze. Apple Podcasts krijgt de aflevering dinsdagochtend. Spotify en de secundaire directories krijgen hem vrijdag. In die 72 uur heeft het Apple Podcasts-publiek exclusieve voorsprong. Zo beloon ik het platform dat het podcast-ecosysteem twintig jaar heeft gedragen en stuur ik luisteraars naar de client die het best begrijpt wat een podcast is: een RSS-bestand, geen algoritmische playlist.
In de code is het filter !episode.isPrivate && isVisibleInDelayedFeed(...). De betekenis van isPrivate heeft me een halfuur verwarring gekost: een privéaflevering wordt verborgen in RSS, maar blijft zichtbaar op de site. Precies het tegenovergestelde van wat mijn brein er in eerste instantie van maakt. Daarom heb ik het als commentaar in de code gezet en schrijf ik het hier ook op, zodat ik me niet nog eens vergis. Zo kan ik een teaser of aflevering voor supporters op de site tonen zonder Apple of Spotify te vervuilen.
Wat er in de Apple-feed staat
De hoofdfeed omarmt Podcasting 2.0 volledig. De namespace xmlns:podcast staat op <channel> en we geven het volgende uit:
<podcast:guid>— een stabiele UUID voor de show, onafhankelijk van de feed-URL<podcast:updateFrequency rrule="FREQ=WEEKLY;INTERVAL=2;BYDAY=TU" dtstart="2026-05-05T05:00:00Z">Un mardi sur deux</podcast:updateFrequency>— het officiële, machineleesbare publicatieritme<podcast:person>voor de host (Clément Sauvage, role="host", href, Cellar-avatar) en dynamisch één voor elke gast (role="guest", Hygraph-afbeelding, naam en bedrijf in tekst)<podcast:chapters>met een verwijzing naar externe JSON met MIME-typeapplication/json+chapters<podcast:alternateEnclosure>om audio en video in hetzelfde<item>aan te bieden
In de Apple iTunes-namespace staat alles: itunes:author, itunes:type op episodic, itunes:image (de verplichte cover van 3000×3000, daarover zo meer), itunes:category op Technology, itunes:explicit en itunes:owner met itunes:name en vooral itunes:email. Bij de items komen itunes:episodeType (full of trailer), itunes:title, itunes:episode, itunes:season, itunes:duration in seconden en de afbeelding van de aflevering, met fallback naar de kanaalcover.
De primaire <enclosure> verwijst naar de H.264-MP4-video wanneer een aflevering die heeft; de audio gaat dan in podcast:alternateEnclosure. Zonder video wordt de audio de primaire <enclosure>. Het MIME-type wordt afgeleid van de URL met mimeTypeFromUrl, die de extensie in het pad herkent en querystrings negeert. Apple vereist een geldige extensie, en ondertekende Cellar-URL’s kunnen queryparameters bevatten die de validator anders laten struikelen.
De cover-valkuil: 3000×3000 of niets
Ik heb de cover in Figma ontworpen. Dat is inmiddels mijn standaardtool voor bijna alle statische visuele assets: nette vectoren, eenvoudige exports in meerdere resoluties en varianten (showcover, afleveringscover en hoofdstukthumbnails) die via componenten synchroon blijven. En daarmee komen we bij de valkuil.
Apple Podcasts eist een vierkante JPEG-cover van minimaal 3000×3000. Eerste export uit Figma, eerste upload, Apple wijst hem af: 3000×3004. Vier pixels te hoog. Een Figma-frame met een binnenmarge die niet helemaal even is, zie je niet met het blote oog, maar het is genoeg om de validator te laten crashen. Mijn feed werd afgewezen. Ik heb de uitsnede in Figma exact op 3000×3000 gezet, opnieuw geëxporteerd en geüpload naar cdn2.clementsauvage.me/cmd-p-podcast/cmdp-cover.jpg, met curl gecontroleerd dat accept-ranges: bytes werd teruggegeven, en alles opnieuw ingediend. Goedgekeurd.
Als je maar één ding uit dit artikel onthoudt: controleer de afmetingen pixel voor pixel voordat je iets indient. Apple geeft geen duidelijke foutmelding, alleen een afwijzing en jij mag gaan zoeken. Stel je Figma-frame bovendien expliciet in op 3000×3000, niet op “ongeveer vierkant”.
Hoofdstukken als externe JSON
In plaats van hoofdstukken in de XML te zetten, raadt de Podcasting 2.0-standaard externe JSON aan. Mijn endpoint /podcast/{slug}/chapters.json geeft PodcastIndex-specificatie 1.2.0 terug:
{
"version": "1.2.0",
"title": "...",
"podcastName": "⌘+P: The App Podcast",
"author": "Clément Sauvage",
"chapters": [
{
"startTime": 0,
"endTime": 90,
"title": "Intro",
"img": "...",
"url": "..."
}
]
}
Fallback voor hoofdstukafbeeldingen, in volgorde: chapter.imageUrl uit Hygraph, anders een Mux-thumbnail op t=startTime, anders de cover van de aflevering. De Content-Type staat expliciet op application/json+chapters; charset=utf-8, want de standaard application/json van Next wordt niet door elke client herkend. Cache: s-maxage=900, stale-while-revalidate=3600, zodat Castro niet bij elke tik opnieuw Hygraph hoeft te bevragen.
De dubbele <description> en <content:encoded>
De meeste hostingproviders houden het bij een minimale <description>. Ik stuur beide uit: een gewone-tekst-<description> voor universele compatibiliteit (ook voor oude clients die HTML niet parsen) en een <content:encoded> met een nette HTML-versie van dezelfde inhoud. Beide bevatten de show notes, een Timeline met tijdstempels als MM:SS of na een uur H:MM:SS, een korte bio van de host en per gast een bio met de kop Avec {nom} — {role} chez {company}.
Een detail dat me tijd kostte: rich text uit Hygraph kwam via .text terug met letterlijke \n-tekens (de backslash en de letter n, niet een echte regeleinde), omdat het JSON-gecodeerd was opgeslagen. Een functie unescapeNewlines zet dat om vóór het renderen. Zonder die functie toonde mijn feed in elke podcastclient zichtbare \n-tekst. Lekker geloofwaardig.
De Spotify-feed: alles wat Apple fijn vindt, eruit
Spotify is veeleisend en eigenzinnig. Hun officiële specificatie verbiedt of negeert sommige dingen waar Apple dol op is. Mijn /podcast/rss/spotify-feed is daarom een strikte variant:
- Geen
podcast:*-namespace — Spotify weet er geen raad mee en ziet hem liever helemaal niet - Geen
podcast:alternateEnclosure— om dezelfde reden - Geen
atom:link— Spotify heeft liever van niet itunes:ownermetitunes:email— door hun support vereist om de feed te verifiëren- Geen overbodige
itunes:titlebij de items - Alleen audio — Spotify ondersteunt geen video via RSS, dus
<enclosure>bevat altijd MP3 of WAV - Hoofdstukken in Podlove Simple Chapters-formaat, niet Podcasting 2.0:
<psc:chapters version="1.1">
<psc:chapter start="0:00" title="..." href="..." image="..." />
</psc:chapters>
De namespace xmlns:psc="http://podlove.org/simple-chapters" wordt alleen toegevoegd wanneer de aflevering hoofdstukken heeft, want sommige validators mopperen over een namespace die nergens wordt gebruikt.
Dit alles wordt geregeld door de parameter mediaMode: 'default' | 'audio' die aan getPodcastRss(...) wordt meegegeven. De builder is één geheel; de feeds zijn verschillende projecties. Geen dubbele code en geen afwijkingen tussen de versies.
Video-encoding voor RSS: H.264 en niets anders
Ik wilde HEVC gebruiken omdat het efficiënter is, mijn Mac Studio het hardwarematig codeert en de bestanden 40% kleiner zijn. Fout. HEVC werkt niet via RSS. Pocket Casts, Overcast en Castro decoderen HEVC niet in een podcastcontext. Apple Podcasts accepteert het via een directe upload in Podcasts Connect, maar niet via RSS. Het resultaat: een bestand dat de helft van je luisteraars niet kan afspelen, zonder duidelijke foutmelding.
De regel voor RSS is: MP4 H.264, AAC-stereo, klaar. Dit is het ffmpeg-recept dat ik gebruik:
ffmpeg -i source.mov \
-c:v libx264 -profile:v high -preset slow -crf 23 \
-vf "scale=1280:720" -pix_fmt yuv420p -movflags +faststart \
-c:a aac -b:a 256k -ar 48000 \
out.mp4
Een paar minder voor de hand liggende keuzes:
- 720p, geen 1080p of 4K. Voor pratende hoofden in een gesprek met weinig beweging is 1280×720 de beste balans. 4K is verspilling; 1080p voegt gewicht toe zonder zichtbaar voordeel.
- CRF 23 + preset slow in plaats van een vaste bitrate. Het encoderen duurt langer, maar de rate control is beter en statische scènes worden automatisch kleiner.
- AAC stereo op 256 kbps — dat is Apples aanbeveling; bij spraak hoor je het verschil met 128 kbps.
-movflags +faststartverplaatst de moov-atom naar het begin van het bestand. Zonder deze optie moet de podcastclient het hele bestand downloaden voordat hij kan afspelen. Met de optie werkt progressief streamen vanaf de eerste kilobytes.-pix_fmt yuv420p— zonder deze vlag kan ffmpeg yuv444p produceren, wat sommige players weigeren. Zes tekens besparen uren debugwerk.
Een concreet resultaat: een teaser ging van 120 MB (FCP-export in H.264 op 9,8 Mbps) naar 26,4 MB, zonder zichtbaar verschil. Een aflevering van 22 minuten komt rond 250 MB uit, redelijk voor een RSS-download via mobiel netwerk.
Gebruik je Permute om encodings in batches te verwerken? Zet “Allow copying of HEVC tracks” dan altijd uit. Anders kopieert de tool de stream en eindig je met een MP4 die HEVC bevat, precies wat je wilde voorkomen.
Bestandsgrootte in RSS en waarom Video.sourceSizeBytes
Een klein detail dat veel uitmaakt voor podcastclients: het length-attribuut van <enclosure> moet de exacte bestandsgrootte in bytes bevatten. Apple Podcasts heeft die nodig om de downloadvoortgang te berekenen. Als de waarde ontbreekt of niet klopt, tonen sommige clients een kapotte voortgangsbalk of weigeren ze de download.
Op PodcastEpisode had ik al audioSizeBytes, berekend tijdens de upload. Toen video de primaire <enclosure> werd, moest er een tegenhanger op de entiteit Video komen: het optionele veld Video.sourceSizeBytes. PodcastEpisode had al een relatie video naar Video, dus ik voegde Video.sourceUrl ook daar toe in plaats van de URL te dupliceren op PodcastEpisode. Als een aflevering video heeft, gebruikt de RSS-generator video.sourceUrl en video.sourceSizeBytes; anders valt hij terug op de audio-URL en audioSizeBytes.
Na elke Hygraph-migratie genereer ik de GraphQL-types opnieuw (src/gql/graphql.ts en src/gql/gql.ts), en de RSS-code handelt beide gevallen goed af. Vijf extra regels in de builder, maar precies het soort regels dat het verschil maakt tussen “werkt op mijn computer” en “werkt in Castro via 4G”.
AI-ondersteunde productie: video-intro, trailer, RSS
Op drie plekken liet ik generatieve modellen het werk doen, in het besef dat dit de stack ook haalbaar maakt voor één persoon.
De video-intro van de show — het korte voorstuk aan het begin van elke aflevering — begon met een eenvoudige iPhone-foto die ik met het videomodel Happy Horse 1.0 heb geanimeerd. Het resultaat duurt maar een paar seconden, maar geeft de show een eigen visuele signatuur. Met After Effects had ik in een weekend nooit zo’n goede motion design gemaakt. De extra kosten zijn verwaarloosbaar, het resultaat past bij de identiteit en niemand vraagt “wie heeft je intro gemaakt?” Dat is precies de bedoeling.
De audiotrailer die op sociale media draait en via <itunes:episodeType>trailer</itunes:episodeType> in de feed staat, is gemaakt met Suno. Niet voor de gebruikelijke achtergrondmuziek (die componeer of licentieer ik liever netjes), maar voor een korte muzikale teaser die past bij het podcasttrailers-format: energiek, herkenbaar en met duidelijke rechten. De hoofdtune van de show is ambachtelijker gemaakt; voor een trailer die maar enkele weken actueel is, is Suno precies het juiste gereedschap.
En vooral: Codex. Het RSS-gedeelte van deze stack — met name het samenspel van de drie feeds, mediaMode, de hoofdstukvarianten van Podcasting 2.0 en Podlove Simple Chapters, de dynamische namespace per aflevering en het herstellen van regeleindes — heb ik samen met Codex via pair programming geschreven. Niet gegenereerd en geplakt, maar samen geschreven: ik definieer het contract (wat elke feed moet opleveren, wat Podbase valideert en wat Spotify weigert), Codex stelt de XML-mechaniek voor en ik loop de randgevallen na die alleen iemand kent wiens feed al eens is afgewezen. Ik lees alle code zelf en sta ervoor in, maar alleen had ik hem niet zo snel geschreven. Het tegendeel beweren zou oneerlijk zijn. En ik verlies mijn geduld met ontwikkelaars die in 2026 nog beweren dat het ze vertraagt.
Ook daarom past deze stack in drie weekenden en kost hij € 12 per maand. Niet omdat we slimmer zijn geworden, maar omdat hulpmiddelen solowerk mogelijk maken waar vijf jaar geleden een team voor nodig was.
Validatie en debuggen: wat me heeft gered
Drie tools die ik zonder aarzeling aanraad:
Podbase valideert je feed tegen de specs van Apple, Spotify en Podcasting 2.0. In het begin wees hij op de ontbrekende podcast:-namespace (die ik vergeten was), een fout-positieve melding dat byte-range “niet ondersteund” was (de validator testte met een lege feed terwijl alle afleveringen isPrivate waren) en ook “0% van de enclosures heeft een geldige extensie”, om dezelfde reden. Conclusie: valideer met minstens één openbare aflevering, anders jaag je achter bugs aan die niet bestaan.
curl + ffprobe + MediaInfo om enclosures te controleren: HTTP 200, content-type, accept-ranges, videocodecs (H.264 of HEVC) en exacte afmetingen (1280×720 en niet zomaar iets). Een curl -I naar je enclosure-URL vertelt binnen drie seconden of Cellar goed reageert. Een ffprobe -v error -show_entries stream=codec_name,width,height laat in twee seconden zien of je bestand klopt.
Clever Cloud-logs + lokaal bun build om runtimecrashes na te bootsen. Twee voorbeelden die me elk een avond kostten:
- Een Apollo-fout
DYNAMIC_SERVER_USAGEdeed een niet-gecachete fetch tijdens het renderen van een SSG-route. Oplossing:Promise.allSettledgebruiken voor de Hygraph-query in de OG-imageroute, zodat een Hygraph-5xx de kaartgeneratie niet laat crashen. - Een Satori-crash
Cannot read properties of undefined (reading '256')tijdens het renderen van de dynamische OG-afbeelding met het variabele lettertype Rethink Sans. Satori ondersteunt variabele fonts niet. Onthouden: geen variabele fonts innext/og. Ik verving de ⌘ die als tekst werd gerenderd door een inline-SVG en de crash verdween.
Structurele keuzes, achteraf bekeken
Als ik de filosofie in vijf punten moest samenvatten:
Overal SSG behalve de player. De pagina /podcast en elke /podcast/[slug] worden statisch gegenereerd met generateStaticParams. De Mux-videoplayer en de <audio>-tag zijn de enige clientcomponenten die op aanvraag streamen. Maximale SEO, pagina’s die door de CDN kunnen worden gecachet en een time-to-first-byte onder de 100 ms.
Hygraph als enige bron. Geen aparte database, geen schemamigraties om bij te houden en geen eigen adminpaneel om te onderhouden. De importadmin schrijft concepten, ik keur elke aflevering handmatig goed en Hygraph publiceert. Eén canonieke status.
Cellar als primaire opslag, Mux als optionele luxe. De H.264-MP4-mastervideo staat op Cellar en levert de RSS. Mux maakt een eigen adaptieve HLS-encoding van dezelfde video voor het web. Als Mux morgen verdwijnt, verliest de site adaptief streamen, maar de podcast blijft zonder onderbreking draaien.
Podcasting 2.0 als volwaardig onderdeel, niet als optie. De podcast:-namespace, person-tags, hoofdstuk-JSON, updateFrequency en alternateEnclosure. De investering is klein als je de XML toch zelf maakt. De winst in Castro, Pocket Casts en Fountain is groot.
Apple Podcasts bewust en concreet voorrang geven. Drie dagen eerder dan Spotify. Alle Podcasting 2.0-tags. Een pixelperfecte cover van 3000×3000. Het platform dat het formaat heeft uitgevonden, verdient een echte technische inspanning, geen aardige tweet (Cupertino, dat kost je een kaartje voor de Dubdub. Kusjes).
Waar dit naartoe gaat
⌘+P is geen marketingexperiment om consultancy te verkopen, ook al ben ik consultant. Het is een ambachtelijk project van iemand die wilde weten of hij met de tools van 2026 in plaats van 2018 een moderne, nette podcastpipeline kon bouwen zonder van iemand afhankelijk te zijn. Na twee maanden tunnelvisie is het antwoord ja, maar alleen als je twee dingen accepteert. RSS is op zichzelf een product, niet een bestand dat je aan het einde genereert. En AI-ondersteunde productie is geen beschamende snelkoppeling, maar een wezenlijk onderdeel van wat solo werken haalbaar maakt: Figma voor beeld, Happy Horse om een iPhone-foto in een video-intro te veranderen, Suno voor de trailer en Codex voor de helft van de RSS-code. Zonder die tools zou ik deze podcast niet maken. Met die tools maak ik hem goed.
De volgende versie krijgt waarschijnlijk transcripties via <podcast:transcript> (ik heb de SRT’s van AssemblyAI al, het zijn drie regels XML), een Engelse versie van de feed voor een Engelstalig publiek en een analyticsdashboard dat Range-verzoeken aan Cellar analyseert om luistercurves per aflevering te reconstrueren. Geen Spotify Wrapped, geen Chartable, alleen mijn eigen logs.
Als je nu een podcast opzet en twijfelt tussen Acast en zelf bouwen: de stack die ik net beschreef kostte ongeveer drie codeweekenden en kost circa € 12 per maand aan infrastructuur (Clever Cloud + Cellar + de gratis tier van Hygraph + de gratis tier van Mux tot een bepaalde hoeveelheid). Dat is meer dan nul. Het is ook het verschil tussen je feed huren en hem bezitten.
De eerste aflevering van ⌘+P verschijnt dinsdag 5 mei 2026. Als je geïnteresseerd bent in tech, productontwikkeling, softwarevakmanschap of gewoon mensen die goed werk leveren, abonneer je dan eerst op Apple Podcasts — niet omdat dat beter is, maar omdat je de aflevering daar drie dagen eerder krijgt.
En als je een uitzonderlijk project hebt, neem contact met me op. Innoveren is waar ik energie van krijg.
