Here's a little javascript web app I'm working on: Weird Waves, a fake online radio station for horror audiobooks and radio plays!

I dunno how far off the final app is. The rest of this post's just an explanation of how it works.

The idea

What's a fake online radio station? I mean a simple web app that plays audio shows every hour on the hour—so simple it can run on static hosting (no need for server-side scripts or a database). You go to the site, you click a button labelled "tune in", and it starts playing the current show in the schedule. It starts from the point in the show when you arrive, not the beginning of the show, and it plays the same show no matter what timezone you're in. For instance:

What about those horror audiobooks and radio plays? Here's the kinda stuff I mean:

How it works

The schedules

The app works off a weekly schedule that's split into two blocks:

  1. Weekday, a block of 4 shows that runs on repeat every day from Monday to Friday. This block shifts by 1 show every midnight (e.g. if you listen at 10 p.m. on Monday you'll hear one show, and if you listen at 10 p.m. on Tuesday you'll hear the next show, and so on).

  2. Weekend, a block of 6 shows that runs on repeat every Saturday and Sunday. This runs the same on both days.

The blocks can actually be any number of shows long, but it's neater if they divide evenly into 24 (for 24 hours). Those numbers are 1, 2, 3, 4, 6, 8, 12, or 24 shows per block.

Each schedule is a .json file stored separate from the script that contains some info about the schedule, plus the lists of shows for each block:

	"info": {
		"title": "Regular Test Schedule",
		"description": "This is a test schedule loaded from a separate file. It plays a mix of episodes from the 1940s weird fiction/sci-fi/horror radio anthology, <cite>Quiet, Please</cite>.",
		"intermission": "test-intermission.mp3"
	"weekday": [
			"file": "QP-001.mp3",
			"id": "qp-001"
			"file": "QP-002.mp3",
			"id": "qp-002"
			"file": "QP-004.mp3",
			"id": "qp-004"
	"weekend": [
			"file": "QP-006.mp3",
			"id": "qp-006"

The script fetches schedules from the server using their filenames. Each schedule file has a name in this format: schedule-YYYY-MM-DD.json, where YYYY-MM-DD is the date of that week's Monday (in the station's timezone). If the script fails to fetch the schedule then it goes with a default schedule written into the script file itself.

Here's what is used for:

Each schedule gets a name that goes in a heading near the top of the app page. If a schedule's got a theme (e.g. underground horror, cosmic horror, dream horror) then that theme can go in the title somehow.
Each schedule gets a single paragraph of description. In future I might change this to allow multiple paragraphs.
Each week has its own intermission track. The schedule provides the filename and the script plays that file between shows.

schedule.weekday and schedule.weekend list the shows in each block. For each show, they have the filename and an ID that points to its metadata, which is written on the app page. For instance, the ID qp-001 points to this metadata:

<li id="qp-001">
	<h5 class="archive-show-title">Nothing Behind the Door</h5>
	<dl class="archive-show-info">
		<dd><a href="">Quiet, Please #1</a></dd>
		<dd>Bank robbers try to hide the money in a mountain shed that contains nothing. Literally nothing.</dd>

Which looks (kinda) like this on the page:

  • Nothing Behind the Door
    Quiet, Please #1
    Bank robbers try to hide the money in a mountain shed that contains nothing. Literally nothing.

Since the metadata's gonna be on the page anyway, I don't need to put show metadata in the schedule file, just a pointer to the metadata on the page. That keeps schedule files small and simple.

The player

Once the player's got the schedule (weekly or default), it can start playing audio. It starts playing when you tune in. Like I explained up above, it follows a set schedule with shows starting every hour on the hour, so if you arrive at X minutes past the hour then the app starts playing the track X minutes in.

There's a little issue right now where if you and arrive in the intermission then the player might play the final seconds of the last show before starting the intermission, but that's not a big deal.

Finally, there's a few controls: a mute/unmute button and a volume slider.

The rest of the app

The rest of the app's gonna have different sections in tabs on the same page (putting everything on one page means the audio won't get broken by navigating between pages):

What next?

The player's pretty much done, I think. It's ~11 KB of javascript, including explanatory comments, and I think all the moving parts are working. There's one thing I need to test with the forecast tables (at the end of each day in your timezone, the now-empty table should be removed from the page).

Here's the to-do list:

It's an alpha/proof of concept right now! And I'm working on it when I have the time, so I dunno exactly when it'll be ready.

Return to top