[go: up one dir, main page]

Music on Neocities: A cheap bastard's guide

Unfortunately, this seems to no longer be working as someone has attempted it themselves and seen the following:

Content-Security-Policy: The page’s settings blocked the loading of a resource (media-src) at data:audio/mp3;base64,AAAAHGZ0eXBNNEEgAA… because it violates the following directive: “media-src *”

I am leaving this up as a historic page for now in case anything new crops up. You should still pay the $5/mo for premium!

Unfortunately this also means if I can no longer pay, my music will be inaccessible. Alas.


Welcome! This used to live on Cohost but now it's gonna be here. It's a little bit out of date these days as I've since added file compression to my files - the latest code is still publicly available, though! Hope you enjoy!

If you, like me, are annoyed that you can't play sounds on Neocities without paying upfront while building a site, have no fear, Javascript is here! (ugh)

TL;DR

Base64 encode your data, load them in a bunch of files up in a directory, define a list of songs, append the songs into the document using Javascript.

I wholeheartedly recommend paying for it - not only does it get rid of their weird arbitrary file restrictions, but it also gives you the ability to set up a custom domain for your site (see: https://wyx.gay) so if you can afford those $5 then do it!

A live example

If you're curious you can see it in action over here: https://kobold-wyx.neocities.org/music

File structure
  music/
  ├─ Song Title 1.txt
  ├─ Song Title 2.txt
  music.js
  music.html
          

How-to

First, you need to set up your music directory so that you have files. Neocities doesn't let you upload raw music, so you have to trick it into thinking it's just textual data, which it technically is since the data we have to load is a base64 encoded string.

There's a lot of different ways to base64 encode data; the easiest way on a Mac or Unix-based machine is to just run cat file.mp3 | base64 > file.txt.

If you're on a Windows machine, I don't know the equivalent, but the easiest fallback I can think of is to use the base64 python library to load the data and output it as a string. If you need extra help with this or know a better utility for Windows feel free to plop it in the comments.

music.html

Two things are needed here. First, load the script in your <head> element, then add the following songList ul element wherever you want a list of songs to show up:

  <head>
  ...
    <script src="music.js"></script>
  </head>
  <body>
    <div id="content">
      <ul id="songList"></ul>
    </div>
  </body>
          

music.js

First, let's just look at the full file I wrote for this.

  var songs = {
    "Song Title 1": "This is the first song.",
    "Song Title 2": "This is the second song."
  };
  
  window.addEventListener("load", (event) => {
    var songList = document.getElementById('songList');
  
    for (let song in songs) {
      let descriptionText = songs[song];
      let url = "music/" + song + ".txt";
      
      let audio = document.createElement('audio');
      audio.id = song;
      audio.controls = 'controls';
      audio.type = 'audio/mp3';
      let entry = document.createElement('li');
      let div = document.createElement('div');
      div.classList.add("song");
      let title = document.createElement('p');
      title.classList.add("songTitle");
      title.innerHTML = song;
      entry.appendChild(title);
      
      if (descriptionText != null && descriptionText.length > 0) {
        let description = document.createElement('p');
        description.innerHTML = descriptionText;
        div.appendChild(description);
      }
      div.appendChild(audio);
      entry.appendChild(div);
      songList.appendChild(entry);
      
      fetch(url)
        .then((resp) => resp.text())
        .then((data) => {
          audio.src = 'data:audio/mp3;base64,' + data;
        });
    }
  });
          

Basically, audio data can be defined in-line, so we use some simple Javascript to glue this together. In this example, I'm using mp3s, but I believe you can play other file formats in a similar fashion. The most important piece of playing music is right here:

  fetch(url)
    .then((resp) => resp.text())
    .then((data) => {
      audio.src = 'data:audio/mp3;base64,' + data;
    });
          

Basically, we load the data at the relative path defined by the song's title, when the file is returned we process it as text data using resp.text(), then once the data is properly loaded we shove it into the <audio> tag's src attribute with some extra metadata that tells the player to play the base64 string as if it's an mp3 file.

What about css?

The most I needed was this:

  #songList {
    list-style-type: none; 
    padding-left: 0;
  }
  
  .song {
    width: 100%; 
  }
  
  .song audio {
    width: 100%; 
  }
  
  .songTitle {
    font-size: 28px;
    color: #87D618;
  }
          

But a lot of this is going to be up to you to style at the end of the day and that's more or less outside the scope of this guide :)

Have fun!