diff --git a/.gitignore b/.gitignore
index cd7396f52a329e17354895604ea35dea80b94bd0..a3e6499f579881a3c14f451bcfdf2d98acd55413 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ node_modules
 dist
 .cache
 out
+.webpack
diff --git a/css/style.css b/css/style.css
index 2126fa335730162c8831711575fdb1fc358f1c40..db1d20e78d3ffa0e2003a95f3db76f267c8565e7 100644
--- a/css/style.css
+++ b/css/style.css
@@ -30,10 +30,10 @@ body {
   color: #f1f1f1;
 
   min-height: 100vh;
-  min-width: 100vw;
+  min-width: 100%;
 
   margin: 0;
-  padding: 0;
+  padding: 0 0 100px 0;
 }
 
 * {
@@ -103,7 +103,10 @@ nav {
   bottom: 0;
   left: 0;
 
-  background: var(--gray-9-70);
+  background: url('../img/noise.png'), var(--gray-9-70);
+  -webkit-backdrop-filter: blur(40px);
+  backdrop-filter: blur(40px);
+  background-repeat: repeat;
   color: white;
 
   align-items: center;
@@ -266,6 +269,24 @@ input[type=text], input[type=url] {
   flex: 1;
 }
 
+.fw {
+  width: 100%;
+}
+
+.fh {
+  height: 100%;
+}
+
+.hw {
+  width: 50%;
+}
+
+img.fw {
+  width: 50%;
+  max-width: 25vw;
+  object-fit: contain;
+}
+
 img.rounded {
   border-radius: 1rem;
 }
@@ -281,12 +302,25 @@ img.appicon-settings {
 .subtitle {
   font-size: 0.9rem;
   opacity: 0.7;
+  z-index: -1;
 }
 
 .justify-center {
   justify-content: center;
 }
 
+.align-center {
+  align-items: center;
+}
+
+.align-space-between {
+  justify-content: space-between;
+}
+
+.text-align-center {
+  text-align: center;
+}
+
 .chip.song > img {
   height: 128px;
   object-fit: contain;
@@ -295,3 +329,30 @@ img.appicon-settings {
 #current-song-art {
   height: 200px;
 }
+
+#next-song-art {
+  height: 180px;
+}
+
+#fullscreen {
+  position: absolute;
+  top: 0;
+  left: 0;
+
+  z-index: 100;
+
+  background: var(--gray-9);
+
+  margin: 0;
+  padding: 1rem;
+  width: 100%;
+  height: 100%;
+
+}
+
+@media (prefers-color-scheme: light) {
+  input[type=text], input[type=url] {
+    background: var(--gray-1);
+    color: var(--gray-9);
+  }
+}
diff --git a/forge.config.js b/forge.config.js
index 483d2d42ada31678a11b0eee1e7108e62b8fe1a8..0049582a394f43f5f10e5f13cbcb0b87d668417c 100644
--- a/forge.config.js
+++ b/forge.config.js
@@ -31,5 +31,6 @@ module.exports = {
       }
     }
   ],
-  plugins: [],
+  plugins: [
+  ],
 };
diff --git a/index.html b/index.html
index 1c929231b28901b011d927845439158f0c0b92b0..c777cc6c19bbf9b8bbb44c5f879d221e6471c808 100644
--- a/index.html
+++ b/index.html
@@ -147,10 +147,17 @@
       <div class="stack v">
         <div class="chip song nowplaying stack h">
           <img src="img/radio-icon.png" alt="No album art" class="rounded" id="current-song-art">
-          <div class="stack v nogap justify-center">
+          <div class="stack v fw nogap justify-center">
             <span class="subtitle">Now playing:</span>
             <span id="current-song-title" class="title">Loading...</span>
             <span id="current-song-artist" class="artist">Loading...</span>
+            <div class="stack hw npgap v">
+              <progress id="progress"></progress>
+              <div class="stack fw nogap align-space-between h">
+                <span id="elapsed">0:00</span>
+                <span id="duration">0:00</span>
+              </div>
+            </div>
           </div>
         </div>
 
@@ -165,6 +172,10 @@
         </div>
       </div>
 
+      <h2 style="margin: 0.5rem 0">History</h2>
+      <div id="history" class="stack v">
+        No history :(
+      </div>
     </section>
 
 
@@ -187,6 +198,30 @@
 
     </section>
 
+    <section id="fullscreen" hidden="hidden" aria-hidden="true" >
+      <div class="stack spacer fh align-center">
+        <div class="stack v align-center spacer">
+          <img src="img/radio-icon.png" alt="No album art" class="rounded fw" id="full-current-song-art">
+          <div class="stack v fw nogap align-center text-align-center">
+            <span class="subtitle">Now playing:</span>
+            <span id="full-current-song-title" class="title">Loading...</span>
+            <span id="full-current-song-artist" class="artist">Loading...</span>
+            <div class="stack hw npgap v">
+              <div class="stack fw nogap align-space-between h">
+                <span id="full-elapsed">0:00</span>
+                <span id="full-duration">0:00</span>
+              </div>
+              <progress id="full-progress"></progress>
+            </div>
+          </div>
+        </div>
+
+        <div class="spacer"></div>
+
+      </div>
+
+    </section>
+
   </main>
 
 
diff --git a/js/app.js b/js/app.js
index bea1f6bd42600cba92bbd17697e946acb6ead886..4d56621f9a219093ac5979e5d10ce86e91c8cb01 100644
--- a/js/app.js
+++ b/js/app.js
@@ -5,9 +5,16 @@ const player = document.getElementById("player");
 const audioSource = player.children.item(0);
 console.debug(audioSource);
 
-const currentSongTitle = document.getElementById("current-song-title");
-const currentSongArtist = document.getElementById("current-song-artist");
-const currentSongArt = document.getElementById("current-song-art");
+let currentSongTitle = document.getElementById("current-song-title");
+let currentSongArtist = document.getElementById("current-song-artist");
+let currentSongArt = document.getElementById("current-song-art");
+let currentSongElapsed = document.getElementById("elapsed");
+let currentSongDuration = document.getElementById("duration");
+let currentSongProgress = document.getElementById("progress")
+
+const nextSongTitle = document.getElementById("next-song-title");
+const nextSongArtist = document.getElementById("next-song-artist");
+const nextSongArt = document.getElementById("next-song-art");
 
 // Important init stuff
 
@@ -18,6 +25,7 @@ let currentStation = null;
 
 runningInElectron = !!window.metadata;
 
+
 if (runningInElectron) {
   console.error("Running under electron.")
 }
@@ -105,7 +113,6 @@ function togglePlay() {
   if (player.paused) {
     audioSource.src += "&nocache=" + Math.random();
     player.load();
-    player.play();
     setPlayPauseButtonIcon("playing")
   } else {
     player.pause();
@@ -115,11 +122,23 @@ function togglePlay() {
 
 playPauseButton.addEventListener("click", togglePlay);
 
+player.addEventListener("loadeddata", _ =>{
+  console.debug("Loading started.")
+  player.play()
+});
+
 
+function convertSecondsToMinutes(secs) {
+  const minutes = Math.floor(secs / 60);
+  const seconds = secs - minutes * 60;
+  return `${minutes}:${seconds}`
+}
 
 // The following code handles giving browsers and operating systems media information
-async function updateMetadata(title="", artist="", album="radio waves", artUrl="https://radio.byemc.xyz/assets/icon-300.png", startTime=Date.now(), duration=0, playingStatus="Stopped", id = Math.floor(Math.random() * 1000)) {
+async function updateMetadata(title="", artist="", album="radio waves", artUrl="https://radio.byemc.xyz/assets/icon-300.png", startTime=Date.now(), duration=0, playingStatus="Stopped", elapsed=0, id = Math.floor(Math.random() * 1000)) {
   // Double-check the inputs to make sure they arent undefined
+  console.debug("Elapsed: ", elapsed)
+
   if (!album) album = "radio waves";
   if (!artUrl) artUrl = "https://radio.byemc.xyz/assets/icon-300.png";
   if (!startTime) startTime = Date.now();
@@ -142,11 +161,29 @@ async function updateMetadata(title="", artist="", album="radio waves", artUrl="
 
     playingStatus = playingStatus.toLowerCase() !== "playing" ? "paused" : "playing"; // or this
     navigator.mediaSession.playbackState = playingStatus;
-    navigator.mediaSession.setPositionState({
-      duration: duration,
-      position: Math.round((Date.now() - startTime) / 1000),
-      playbackRate: 1
-    })
+
+    currentSongDuration.innerText = `${convertSecondsToMinutes(duration)}`
+    currentSongProgress.max = (duration * 1000);
+    currentSongProgress.dataset.duration = duration;
+    currentSongProgress.dataset.startTime = startTime;
+    currentSongProgress.value = Date.now() - startTime
+
+    if (elapsed) {
+      navigator.mediaSession.setPositionState({
+        duration: duration,
+        position: elapsed,
+        playbackRate: 1
+      })
+      currentSongProgress.dataset.offset = Math.round(elapsed - ((Date.now() - startTime) / 1000))
+      currentSongElapsed.innerText = `${convertSecondsToMinutes(elapsed)}`;
+    } else {
+      navigator.mediaSession.setPositionState({
+        duration: duration,
+        position: Math.min(Math.round((Date.now() - startTime) / 1000), duration),
+        playbackRate: 1
+      })
+      currentSongElapsed.innerText = `${convertSecondsToMinutes(Math.min(Math.round((Date.now() - startTime) / 1000), duration))}`;
+    }
 
   }
 }
@@ -216,7 +253,6 @@ function tuneRadio(station={url:"assets/audio/noise.wav"}) {
   audioSource.src = station.url + "?nocache=" + Math.random();
   currentStation = station;
   player.load();
-  player.play();
 
   location.hash = "#station";
 }
@@ -299,6 +335,7 @@ const views = {
   "#add_station": document.getElementById("add_station"),
   "#add_station_from_azuracast": document.getElementById("add_station_from_azuracast"),
   "#station": document.getElementById("station"),
+  "#fullscreen": document.getElementById("fullscreen"),
   "#settings": document.getElementById("settings"),
 };
 
@@ -312,6 +349,13 @@ const viewFunctions = { // These run when a view is loaded.
       return;
     }
 
+    currentSongTitle = document.getElementById("current-song-title");
+    currentSongArtist = document.getElementById("current-song-artist");
+    currentSongArt = document.getElementById("current-song-art");
+    currentSongElapsed = document.getElementById("elapsed");
+    currentSongDuration = document.getElementById("duration");
+    currentSongProgress = document.getElementById("progress");
+
     if (currentStation.metadata_type === "azuracast") {
       let request = await fetch(currentStation.azuracast_server_url + `/api/station/${currentStation.azuracast_station_shortcode}`);
       let json = await request.json();
@@ -321,6 +365,16 @@ const viewFunctions = { // These run when a view is loaded.
     } else {
       stationThingy.innerHTML = "Yeah this is icecast, metadata coming soon."
     }
+  },
+  "#fullscreen": async function () {
+    currentSongTitle = document.getElementById("full-current-song-title");
+    currentSongArtist = document.getElementById("full-current-song-artist");
+    currentSongArt = document.getElementById("full-current-song-art");
+    currentSongElapsed = document.getElementById("full-elapsed");
+    currentSongDuration = document.getElementById("full-duration");
+    currentSongProgress = document.getElementById("full-progress");
+
+    await updateLoop();
   }
 }
 
@@ -374,7 +428,7 @@ function updateView() {
 // Set an interval to poll the station for metadata
 async function getCurrentSongInfoFromAzuracastStation(server, shortcode) {
 
-  let response = await (await fetch(server + "/api/nowplaying/" + shortcode)).json();
+  let response = await (await fetch(server + "/api/nowplaying/" + shortcode + "?nocache=" + Math.random())).json();
 
   let album;
   if (response.now_playing.song.album) {
@@ -383,10 +437,47 @@ async function getCurrentSongInfoFromAzuracastStation(server, shortcode) {
     album = response.station.name;
   }
 
-  document.getElementById("live_listeners").innerText = response.listeners.unique;
+  try {
+    nextSongTitle.innerText = response.playing_next.song.title;
+    nextSongArtist.innerText = response.playing_next.song.artist;
+    nextSongArt.src = response.playing_next.song.art;
+
+
+    document.getElementById("live_listeners").innerText = response.listeners.unique;
+    const history = document.getElementById("history");
+    history.innerText = "";
+    for (let song of response.song_history) {
+      const div = document.createElement("div");
+      div.classList = "chip compact song stack h";
+      const img = document.createElement("img");
+      img.classList = "rounded"
+      img.src = song.song.art;
+      const stack = document.createElement("div");
+      stack.classList = "stack v nogap justify-center";
+
+      //Strings
+      const title = document.createElement("span");
+      const artist = document.createElement("span");
+      const timeSince = document.createElement("span");
+
+      title.innerText = song.song.title;
+      artist.innerText = song.song.artist;
+      timeSince.innerText = ""
+
+      stack.append(title, artist, timeSince);
+
+      div.appendChild(img);
+      div.appendChild(stack);
+      history.appendChild(div)
+    }
+  } catch (e) {
+    console.error(e)
+  }
+
 
   return {title: response.now_playing.song.title, artist: response.now_playing.song.artist, album: album,
-    art: response.now_playing.song.art, startTime: response.now_playing.played_at * 1000, duration: response.now_playing.duration}
+    art: response.now_playing.song.art, startTime: response.now_playing.played_at * 1000, duration: response.now_playing.duration,
+    elapsed: response.now_playing.elapsed}
 }
 
 async function getCurrentSongInfoFromIceCastStation(streamUrl) {
@@ -406,20 +497,34 @@ async function updateLoop() {
   }
 
   const isPlaying = player.paused ? "paused" : "playing";
-  await updateMetadata(metadata.title, metadata.artist, metadata.album, metadata.art, metadata.startTime, metadata.duration, isPlaying);
+  await updateMetadata(metadata.title, metadata.artist, metadata.album, metadata.art, metadata.startTime, metadata.duration, isPlaying,  metadata.elapsed);
 
   currentSongTitle.innerText = metadata.title;
   currentSongArtist.innerText = metadata.artist;
   currentSongArt.src          = metadata.art;
 }
 
-setInterval(updateLoop, 3000)
+setInterval(updateLoop, 3000);
+
+async function updateProgressBars() {
+  try {
+    currentSongProgress.value = Date.now() - currentSongProgress.dataset.startTime;
+
+  } catch (e) {
+    currentSongProgress.value = 0
+  }
+  currentSongElapsed.innerText = convertSecondsToMinutes(Math.round(((Date.now() - currentSongProgress.dataset.startTime) / 1000)) + Number(currentSongProgress.dataset.offset))
+}
+
+setInterval(updateProgressBars, 500);
 
 // Give user feedback on buffering
 
 player.addEventListener('playing', function() {
   console.log('Playback started.');
-  noise.pause();
+  if (noise !== null) {
+    noise.pause();
+  }
   noise = null;
   setPlayPauseButtonIcon("playing");
   updateLoop();
@@ -435,7 +540,11 @@ player.addEventListener('pause', function() {
 player.addEventListener('waiting', function() {
   console.log("Buffering...");
   noise = new Audio("assets/audio/noise.wav");
-  noise.play();
+  try {
+    noise.play();
+  } catch (e) {
+    console.error(e);
+  }
   noise.volume = player.volume / 4;
   noise.loop = true;
   setPlayPauseButtonIcon("buffer");
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/webpack.config.prod.js b/webpack.config.prod.js
index adc763e33a47f6348dc5df0f9a3ad2bdc2549083..9cad3db7909ed09a192d409efd98641f5006e21c 100644
--- a/webpack.config.prod.js
+++ b/webpack.config.prod.js
@@ -14,11 +14,12 @@ module.exports = merge(common, {
         { from: 'img', to: 'img' },
         { from: 'css', to: 'css' },
         { from: 'js/vendor', to: 'js/vendor' },
+        { from: 'assets', to: 'assets' },
         { from: 'icon.svg', to: 'icon.svg' },
         { from: 'favicon.ico', to: 'favicon.ico' },
         { from: 'robots.txt', to: 'robots.txt' },
         { from: '404.html', to: '404.html' },
-        { from: 'site.webmanifest', to: 'site.webmanifest' },
+        { from: 'manifest.json', to: 'manifest.json' },
       ],
     }),
   ],