make a website for Hot Z100 in Bay City, Texas, is described as Bay City's "#1 PARTY / HIT MUSIC STATION." Additional details include:Format: Top 40 & Pop Music.Operating since: 2020.Catchphrase: "THE PARTY STATION FOR THE 979".Features: It features radio shows and various content. User reviews mention a DJ Fire Cat and appreciate the electronic music mixes.Email Contact: thegaragefmfire@gmail.comstudio number:979-429-3724
I'll create a modern, energetic website for Hot Z100, Bay City's "#1 PARTY / HIT MUSIC STATION" with all the essential features a radio station needs.
The website is built with Next.js and uses Tailwind CSS for styling, making it fast, modern, and easy to maintain.
use this html player code for hot z100:<div class="radio-player-container"> <audio id="audio-{{unique_id}}" crossorigin="anonymous" preload="none"></audio> <div class="radio-player"> <div class="player-content"> <div class="cover-container"> <img class="cover-image" src="http://hotz100baycity.unaux.com/wp-content/uploads/2025/06/cropped-cropped-image-10-1.png" alt="Album cover" /> </div> <div class="metadata"> <div class="title">Loading title...</div> <div class="artist">Loading artist...</div> <div class="album"></div> <div class="year"></div> </div> </div> <div class="player-controls"> <button class="play-pause-btn" aria-label="Play radio stream"> <span class="btn-icon"></span> <span class="btn-text">Play</span> </button> <input type="range" class="volume-slider" min="0" max="1" step="0.01" value="0.5" aria-label="Volume control"/> </div> <div class="status-message"></div> </div> </div> <style> /* Your existing styles unchanged */ .radio-player-container { color: #e0e0e0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 2em 0; } .radio-player { background: #1e1e1e; padding: 1.5em 2em; box-shadow: 0 0 12px #00bcd4; width: 100%; margin: 0 auto; box-sizing: border-box; } .player-content { display: flex; align-items: center; justify-content: center; gap: 1em; } .cover-container { flex-shrink: 0; } .cover-image { width: 160px; height: 160px; border-radius: 20px; background: #333; object-fit: cover; } .metadata { flex: 1; margin-top: 0; line-height: 1.4; font-size: 1.2em; text-align: left; user-select: text; } .metadata .title { font-weight: 700; font-size: 1.3em; color: #00bcd4; } .metadata .artist { font-style: italic; color: #80deea; margin-top: 0.2em; } .metadata .album { font-size: 0.9em; color: #aaaaaa; margin-top: 0.5em; } .metadata .year { font-size: 0.8em; color: #888888; margin-top: 0.2em; } .player-controls { margin-top: 1em; display: flex; justify-content: space-between; align-items: center; gap: 1em; } .play-pause-btn { background: #00bcd4; border: none; padding: 0.6em 1.2em; color: #121212; font-weight: 700; border-radius: 8px; cursor: pointer; transition: background-color 0.3s ease; user-select: none; display: flex; align-items: center; gap: 0.5em; } .play-pause-btn:hover:not(:disabled) { background: #00acc1; } .play-pause-btn:disabled { background: #3a9fbf; cursor: default; } .volume-slider { -webkit-appearance: none; width: 160px; height: 6px; background: #444; border-radius: 5px; outline: none; cursor: pointer; } .volume-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 18px; height: 18px; border-radius: 50%; background: #00bcd4; cursor: pointer; transition: background-color 0.3s ease; margin-top: -6px; } .volume-slider:hover::-webkit-slider-thumb { background: #00acc1; } .volume-slider::-moz-range-thumb { width: 18px; height: 18px; border-radius: 50%; background: #00bcd4; cursor: pointer; transition: background-color 0.3s ease; } .volume-slider:hover::-moz-range-thumb { background: #00acc1; } .status-message { margin-top: 0.8em; font-size: 0.9em; color: #ff6666; text-align: center; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .spinner { border: 3px solid rgba(0,0,0,0.1); border-left-color: #121212; border-radius: 50%; width: 16px; height: 16px; animation: spin 1s linear infinite; display: inline-block; } .stopwatch-icon { width: 16px; height: 16px; stroke: #121212; fill: none; stroke-width: 2; } .play-pause-btn.playing .stopwatch-icon path, .play-pause-btn.playing .stopwatch-icon circle { stroke: #121212; fill: #121212; } </style> <script> (function() { // Generate unique ID for this player instance const uniqueId = 'player-' + Math.random().toString(36).substr(2, 9); const container = document.currentScript.parentElement.querySelector('.radio-player-container'); container.id = uniqueId; const audio = container.querySelector('audio'); const playPauseBtn = container.querySelector('.play-pause-btn'); const btnIconSpan = playPauseBtn.querySelector('.btn-icon'); const btnTextSpan = playPauseBtn.querySelector('.btn-text'); const volumeSlider = container.querySelector('.volume-slider'); const titleEl = container.querySelector('.metadata .title'); const artistEl = container.querySelector('.metadata .artist'); const coverImg = container.querySelector('.cover-image'); const albumEl = container.querySelector('.metadata .album'); const yearEl = container.querySelector('.metadata .year'); const statusMessage = container.querySelector('.status-message'); // Configuration - update these for your station const streamUrlBase = "https://cdnstream1.typicalmedia.net/hotz100"; const fallbackCoverUrl = "http://hotz100baycity.unaux.com/wp-content/uploads/2025/06/cropped-cropped-image-10-1.png"; // Updated fallback URL const maxReconnectAttempts = 5; const reconnectDelayMs = 5000; // Player state let isPlaying = false; let autoReconnectAttempts = 0; let stopwatchInterval = null; let stopwatchStart = null; // Initialize volume audio.volume = volumeSlider.value; // SVG icons const spinnerSVG = `<span class="spinner" aria-hidden="true"></span>`; const playSVG = `<svg aria-hidden="true" fill="#121212" height="16" viewBox="0 0 24 24" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M8 5v14l11-7z"/></svg>`; const stopwatchSVG = `<svg aria-hidden="true" class="stopwatch-icon" viewBox="0 0 24 24" role="img" aria-label="Stopwatch icon" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="13" r="7" stroke="#121212" stroke-width="2" fill="none"/><path d="M12 6v4l2 2" stroke="#121212" stroke-width="2" fill="none" stroke-linecap="round"/></svg>`; // Helper functions function freshStreamUrl() { return streamUrlBase + `?cb=${Date.now()}`; } function formatStopwatchElapsed() { if (!stopwatchStart) return "00:00"; const elapsedMs = Date.now() - stopwatchStart; const totalSeconds = Math.floor(elapsedMs / 1000); const minutes = Math.floor(totalSeconds / 60); const seconds = totalSeconds % 60; return `${String(minutes).padStart(2,"0")}:${String(seconds).padStart(2,"0")}`; } function startStopwatch() { stopwatchStart = Date.now(); btnTextSpan.textContent = formatStopwatchElapsed(); if (stopwatchInterval) clearInterval(stopwatchInterval); stopwatchInterval = setInterval(() => { btnTextSpan.textContent = formatStopwatchElapsed(); }, 1000); } function stopStopwatch() { if (stopwatchInterval) { clearInterval(stopwatchInterval); stopwatchInterval = null; } stopwatchStart = null; } function showLoading() { btnIconSpan.innerHTML = spinnerSVG; btnTextSpan.textContent = "Loading..."; playPauseBtn.disabled = true; playPauseBtn.classList.remove("playing"); } function showPlaying() { btnIconSpan.innerHTML = stopwatchSVG; btnTextSpan.textContent = formatStopwatchElapsed(); playPauseBtn.disabled = false; playPauseBtn.classList.add("playing"); } function showPaused() { btnIconSpan.innerHTML = playSVG; btnTextSpan.textContent = "Play"; playPauseBtn.disabled = false; playPauseBtn.classList.remove("playing"); } function startStream() { statusMessage.textContent = ''; showLoading(); audio.src = freshStreamUrl(); audio.load(); audio.play().catch(err => { statusMessage.textContent = 'Error playing stream. Please click play again.'; console.warn('Playback error:', err); showPaused(); }); } function stopStream() { stopStopwatch(); audio.pause(); audio.removeAttribute('src'); audio.load(); isPlaying = false; showPaused(); statusMessage.textContent = ''; } function handleStreamInterruption(message) { if (autoReconnectAttempts < maxReconnectAttempts) { statusMessage.textContent = message + ` (Attempt ${autoReconnectAttempts + 1} of ${maxReconnectAttempts})`; autoReconnectAttempts++; setTimeout(() => { if (autoReconnectAttempts < maxReconnectAttempts) { startStream(); } }, reconnectDelayMs); } else { statusMessage.textContent = 'Stream connection lost. Please try again.'; stopStream(); } } function toTitleCase(text) { if (!text) return ""; return text.toLowerCase().split(' ').map(word => { return word.charAt(0).toUpperCase() + word.slice(1); }).join(' '); } // iOS Volume Slider Fix: Use 'change' event in addition to 'input' and call audio.setVolume explicitly function setVolume(value) { // Clamp value between 0 and 1 const vol = Math.min(Math.max(parseFloat(value), 0), 1); try { audio.volume = vol; } catch(e) { // fallback if needed } } // Event listeners playPauseBtn.addEventListener('click', () => { if (!isPlaying) { startStream(); } else { stopStream(); } }); volumeSlider.addEventListener('input', (e) => { setVolume(e.target.value); }); volumeSlider.addEventListener('change', (e) => { setVolume(e.target.value); }); audio.addEventListener('playing', () => { isPlaying = true; autoReconnectAttempts = 0; startStopwatch(); showPlaying(); }); audio.addEventListener('pause', () => { if (!audio.ended && isPlaying) { handleStreamInterruption('Stream interrupted, reconnecting...'); } else { stopStopwatch(); showPaused(); isPlaying = false; } }); audio.addEventListener('ended', () => { if (isPlaying) { handleStreamInterruption('Stream ended, reconnecting...'); } stopStopwatch(); showPaused(); isPlaying = false; }); audio.addEventListener('error', () => { if (isPlaying) { handleStreamInterruption('Stream error occurred'); } }); audio.addEventListener('stalled', () => { if (isPlaying) { handleStreamInterruption('Stream stalled, reconnecting...'); } }); // Metadata fetching functions async function fetchMetadata() { try { const response = await fetch('https://cdnstream1.typicalmedia.net/status-json.xsl'); if (!response.ok) throw new Error('Network response was not ok'); const json = await response.json(); if (json.icestats?.source) { const sources = Array.isArray(json.icestats.source) ? json.icestats.source : [json.icestats.source]; const mount = sources.find(s => s.listenurl?.includes('/hotz100')); if (mount) { const rawTitle = (mount.title || mount.song || '').trim(); if (!rawTitle) { titleEl.textContent = "No metadata available"; artistEl.textContent = ""; return; } const separators = ["-", "—", "–"]; let splitIndex = -1; let separatorUsed = null; for (const sep of separators) { const idx = rawTitle.indexOf(sep); if (idx !== -1) { splitIndex = idx; separatorUsed = sep; break; } } if (splitIndex > 0) { artistEl.textContent = toTitleCase(rawTitle.substring(0, splitIndex).trim()) || 'Unknown Artist'; titleEl.textContent = toTitleCase(rawTitle.substring(splitIndex + separatorUsed.length).trim()) || 'Unknown Title'; } else { titleEl.textContent = toTitleCase(rawTitle); artistEl.textContent = "Unknown Artist"; } } } } catch (error) { console.error('Metadata fetch error:', error); } } async function getNowPlaying() { try { const response = await fetch("https://api.echoaudio.io/public/4ef294b8-68b3-42cc-9471-fa62c90d206f/station/6846251f7e033acb7b4e3402"); const data = await response.json(); const nowMedia = data.now[0].media; // Update cover image if different if (nowMedia.cover?.trim() && nowMedia.cover !== coverImg.src) { coverImg.src = nowMedia.cover; coverImg.alt = `Album cover for ${nowMedia.album || nowMedia.title || 'Current Track'}`; } else if (!nowMedia.cover?.trim() && coverImg.src !== fallbackCoverUrl) { coverImg.src = fallbackCoverUrl; coverImg.alt = "Fallback album cover"; } // Update metadata albumEl.textContent = nowMedia.album ? `Album: ${toTitleCase(nowMedia.album)}` : ""; yearEl.textContent = nowMedia.year ? `Year: ${nowMedia.year}` : ""; if (nowMedia.title) titleEl.textContent = toTitleCase(nowMedia.title); if (nowMedia.artist) artistEl.textContent = toTitleCase(nowMedia.artist); } catch (error) { console.warn('Now Playing fetch error:', error); if (!coverImg.src || coverImg.src !== fallbackCoverUrl) { coverImg.src = fallbackCoverUrl; coverImg.alt = "Fallback album cover"; } } } // Initialize player fetchMetadata(); getNowPlaying(); setInterval(fetchMetadata, 10000); setInterval(getNowPlaying, 10000); showPaused(); })(); </script>
I'll update the radio player component to use the provided HTML player code for Hot Z100. This will give you a fully functional player with live streaming, metadata fetching, and the station's branding.
Perfect! I've updated the radio player component to use the provided HTML player code for Hot Z100. Here are the key features of the new player:
https://cdnstream1.typicalmedia.net/hotz100
Real-time Metadata: Fetches current song information from two APIs:
Smart Controls:
Dynamic Content:
The player now uses Hot Z100's actual streaming infrastructure and will display real-time information about what's currently playing on the station. The design maintains the energetic party station aesthetic while providing a professional listening experience.
add the chatroomembed <script src="https://minnit.chat/js/embed.js?c=1752216300" defer></script><span style="display: none;" class="minnit-chat-sembed" data-chatname="https://organizations.minnit.chat/203406804023972/c/Main?embed&transparent" data-style="width:1000px;height:500px;" data-version="1.52">Chat</span><p class="powered-by-minnit"><a href="https://minnit.chat" target="_blank">Embed a chatroom on your website for free with Minnit Chat</a></p>