diff --git a/server/djrandom/frontend/static/js/djr/backend.js b/server/djrandom/frontend/static/js/djr/backend.js
new file mode 100644
index 0000000000000000000000000000000000000000..3586149c16e080350de47656105231541480c5ef
--- /dev/null
+++ b/server/djrandom/frontend/static/js/djr/backend.js
@@ -0,0 +1,92 @@
+// backend.js
+
+
+// Backend API stub.
+
+djr.Backend = function() {
+  // Nothing yet.
+};
+
+// Search.
+djr.Backend.prototype.search = function(query, callback, ctx) {
+  $.ajax({url: '/json/search',
+          data: {'q': query},
+          dataType: 'json',
+          type: 'GET',
+          context: ctx || this,
+          success: function(data, status, jqxhr) {
+            callback(data.results);
+          }
+         });
+};
+
+// More like these.
+djr.Backend.prototype.moreLikeThese = function(uuids, callback, ctx) {
+  $.ajax({url: '/json/morelikethese',
+          data: {'h': uuids.join(',')},
+          dataType: 'json',
+          type: 'POST',
+          context: ctx || this,
+          success: function(data, status, jqxhr) {
+            callback(data.results);
+          }
+         });
+};
+
+// Get information about a specific song.
+
+// Read a playlist, calls callback(Playlist).
+djr.Backend.prototype.getPlaylist = function(uuid, callback, ctx) {
+  $.ajax({url: '/json/playlist/get/' + uuid,
+          dataType: 'json',
+          type: 'GET',
+          context: ctx || this,
+          success: function(data, status, jqxhr) {
+            callback(new djr.PlaylistChunk(data.songs, uuid));
+          }
+         });
+};
+
+// Save a playlist (song array).
+djr.Backend.prototype.savePlaylist = function(uuid, songs) {
+  $.ajax({url: '/json/playlist/save',
+          data: {uuid: uuid,
+                 h: songs.join(',')},
+          type: 'POST'
+         });
+};
+
+// Stream a playlist.
+djr.Backend.prototype.streamPlaylist = function(uuid, streaming, callback, ctx) {
+  $.ajax({url: '/json/playlist/stream',
+          data: {uuid: uuid,
+                 stream: streaming ? 'y' : 'n'},
+          dataType: 'json',
+          type: 'POST',
+          context: ctx || this,
+          success: function(data, status, jqxhr) {
+            callback(data);
+          }
+         });
+};
+
+// Return the HTML fragment for an array of songs.
+djr.Backend.prototype.getHtmlForSongs = function(songs, callback, ctx) {
+  $.ajax({url: '/fragment/songs',
+          data: {'h': songs.join(',')},
+          dataType: 'html',
+          type: 'POST',
+          context: ctx || this,
+          success: callback,
+         });
+};
+
+// Ping a song that is currently playing.
+djr.Backend.prototype.nowPlaying = function(song, old_songs) {
+  $.ajax({url: '/json/playing',
+          data: {'cur': song,
+                 'prev': old_songs.join(',')},
+          type: 'POST',
+          });
+};
+
diff --git a/server/djrandom/frontend/static/js/djr/djr.js b/server/djrandom/frontend/static/js/djr/djr.js
new file mode 100644
index 0000000000000000000000000000000000000000..b7e70d636698f99f1efbb3b9d59ca2c567caf898
--- /dev/null
+++ b/server/djrandom/frontend/static/js/djr/djr.js
@@ -0,0 +1,17 @@
+// djr.js
+
+// Globals and namespace definition.
+
+
+// Namespace.
+djr = {};
+
+
+// Utility functions.
+var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
+djr.generateRandomId = function() {
+  var uuid = [], chars = CHARS, i;
+  var len = 40, radix = chars.length;
+  for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random()*radix];
+  return uuid.join('');
+};
diff --git a/server/djrandom/frontend/static/djrandom.js b/server/djrandom/frontend/static/js/djr/history.js
similarity index 100%
rename from server/djrandom/frontend/static/djrandom.js
rename to server/djrandom/frontend/static/js/djr/history.js
diff --git a/server/djrandom/frontend/static/player.js b/server/djrandom/frontend/static/js/djr/player.js
similarity index 82%
rename from server/djrandom/frontend/static/player.js
rename to server/djrandom/frontend/static/js/djr/player.js
index 7dc5cac8be97acb2468ab008b3e5771fe4f8ba38..91286e60396b32e23f2c0f1adc791d9744dc43d1 100644
--- a/server/djrandom/frontend/static/player.js
+++ b/server/djrandom/frontend/static/js/djr/player.js
@@ -1,110 +1,6 @@
 // player.js
 
 
-// Namespace.
-djr = {};
-
-// Utility functions.
-var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
-djr.generateRandomId = function() {
-  var uuid = [], chars = CHARS, i;
-  var len = 40, radix = chars.length;
-  for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random()*radix];
-  return uuid.join('');
-};
-
-
-// Backend API stub.
-
-djr.Backend = function() {
-  // Nothing yet.
-};
-
-// Search.
-djr.Backend.prototype.search = function(query, callback, ctx) {
-  $.ajax({url: '/json/search',
-          data: {'q': query},
-          dataType: 'json',
-          type: 'GET',
-          context: ctx || this,
-          success: function(data, status, jqxhr) {
-            callback(data.results);
-          }
-         });
-};
-
-// More like these.
-djr.Backend.prototype.moreLikeThese = function(uuids, callback, ctx) {
-  $.ajax({url: '/json/morelikethese',
-          data: {'h': uuids.join(',')},
-          dataType: 'json',
-          type: 'POST',
-          context: ctx || this,
-          success: function(data, status, jqxhr) {
-            callback(data.results);
-          }
-         });
-};
-
-// Get information about a specific song.
-
-// Read a playlist, calls callback(Playlist).
-djr.Backend.prototype.getPlaylist = function(uuid, callback, ctx) {
-  $.ajax({url: '/json/playlist/get/' + uuid,
-          dataType: 'json',
-          type: 'GET',
-          context: ctx || this,
-          success: function(data, status, jqxhr) {
-            callback(new djr.PlaylistChunk(data.songs, uuid));
-          }
-         });
-};
-
-// Save a playlist (song array).
-djr.Backend.prototype.savePlaylist = function(uuid, songs) {
-  $.ajax({url: '/json/playlist/save',
-          data: {uuid: uuid,
-                 h: songs.join(',')},
-          type: 'POST'
-         });
-};
-
-// Stream a playlist.
-djr.Backend.prototype.streamPlaylist = function(uuid, streaming, callback, ctx) {
-  $.ajax({url: '/json/playlist/stream',
-          data: {uuid: uuid,
-                 stream: streaming ? 'y' : 'n'},
-          dataType: 'json',
-          type: 'POST',
-          context: ctx || this,
-          success: function(data, status, jqxhr) {
-            callback(data);
-          }
-         });
-};
-
-// Return the HTML fragment for an array of songs.
-djr.Backend.prototype.getHtmlForSongs = function(songs, callback, ctx) {
-  $.ajax({url: '/fragment/songs',
-          data: {'h': songs.join(',')},
-          dataType: 'html',
-          type: 'POST',
-          context: ctx || this,
-          success: callback,
-         });
-};
-
-// Ping a song that is currently playing.
-djr.Backend.prototype.nowPlaying = function(song, old_songs) {
-  $.ajax({url: '/json/playing',
-          data: {'cur': song,
-                 'prev': old_songs.join(',')},
-          type: 'POST',
-          });
-};
-
-
-
 // A Playlist chunk (basically, an array of songs).
 
 djr.PlaylistChunk = function(songs, title) {