I love listening to podcasts. You can learn a language, keep up to date on news, or absorb tonnes of information about interesting topics. But I don't do that. I listen to dozens of hours of improvisational comedy a week instead. Hands-free entertainment while driving, cooking, doing chores or something to entertain yourself with that isn't reading or staring at a screen after hours of coding during bootcamp project week.
Podcasts are also one of the last bastions of the "open internet". They are built on RSS (Really Simple Syndication) for distribution. RSS has fallen out of favor in recent years as people moved towards social media and personalized timelines rather than RSS feed readers.
Apple Podcast was the first big player in podcasting (the "pod" comes from iPod) and it's still the standard that podcasters use for the their RSS feeds (big boo to Apple for suing developers that used "pod" in the name of other podcast listening apps though).
So, armed with a little bit of JavaScript knowledge, some React and a basic understanding of RSS I set out to make a simple web app that would allow users to search for a podcast, see episodes of that podcast and then listen to them.
The iTunes Search API allows you to search through everything in the vast iTunes catalogue, including podcasts. Almost all public podcasts are distributed to iTunes so it's a comprehensive list.
useEffect(() => {
fetch(`https://itunes.apple.com/search?term=${searchTerm}&entity=podcast&attributeType=titleTerm.`)
.then((r) => r.json())
.then((r) => {
console.log(r.results);
setResults(r.results);
});
}, [searchTerm]);It's also very easy to work with. No API key to worry about! The biggest "gotcha" moment was the period in the endpoint URL. The fetch request won't work without it.
The iTunes Search API will return the podcast RSS feed. Great! I can just look through that and get all of the episodes (podcast episodes are .mp3 files on a hosting service). No so fast! Although RSS feeds generally follow the same format they are not exactly the same. They are also not an array but an XML (Extensible Markup Language) file. Okay! Back to the iTunes search API to do another fetch request to get episodes of a podcast in JSON.
function handlePodcastClick(e) {
const podcastURL = `https://itunes.apple.com/lookup?id=${e.target.alt}&country=US&media=podcast&entity=podcastEpisode&limit=12`;
fetch(podcastURL)
.then((r) => r.json())
.then((r) => {
setPodcastEpisodes(r.results);
console.log(r);
});
}This will return an array of objects with the latest 12 episodes of the podcast you searched for. Inside those objects are the address of the podcast artwork, the .mp3 file and other helpful information for us like the title and description. And it's uniform for all podcasts so it's easy to iterate over and display in the DOM via React.

Every modern browser supports audio/video playback with a built in player. These are pretty bare bones, with just a play/pause button and maybe a scrubber and some volume controls. I wanted something a little more modern, with a mute button, playback speed controller, and skip forward/backward buttons. I used React Player as the basis for my listening experience.
<ReactPlayer
ref={player}
height={0}
url={audioURL}
controls={false}
playing={playing}
muted={muted}
volume={volume}
onDuration={handleDuration}
onProgress={onProgress}
playbackRate={playbackRate}
/>React Player gives you the basic building blocks of a media player and allows you to customize the elements visually and functionally. Everything is held in state and is mutable by the developer. Adding a mute button is pretty easy:
function handleMute() {
setMuted(!muted);
}
<span onClick={handleMute}>{muted ? "🔇" : "🔈R"}lt;/span>Same with playing and pausing.
function handlePlayPause() {
setPlaying(!playing);
}
<span onClick={handlePlayPause}>{playing ? "⏸" : "▶️"}</span>Speed and volume work the same way too.
function handleLouder() {
setMuted(false)
if (volume < .9)
setVolume(volume+=0.1)
}
function handleQuieter() {
if (volume <= 0.1) {
setMuted(true)
} else {
setVolume(volume-=0.1)
}
}
<button onClick={handleQuieter}>-</button>
<span>Volume: {Math.round(volume * 10)}</span>
<button onClick={handleLouder}>+</button>React Player will let you go up to 16x speed before it stops working. Good luck to anyone trying to understand a podcast host at that speed!
This side project was a "test run" for my final project (Podkeeper). I wanted to see if there was a useable (and free) API and get some experience in dealing with A/V in React. React Player was incredibly useful, with great docs and demos, that made this project much easier and inspired some new features. The callback functions (onPlay, onStart, onEnded, etc…) made it easy to build fun features like notifications.