Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save juanmackie/407e6c8d5f7c598dedc7b53b283b3e6b to your computer and use it in GitHub Desktop.

Select an option

Save juanmackie/407e6c8d5f7c598dedc7b53b283b3e6b to your computer and use it in GitHub Desktop.
Nothing Style Last FM Widget
##ENSURE TO UPDATE WITH YOUR DETAILS
<style>
@import url('https://fonts.googleapis.com/css2?family=Space+Mono:wght=400;700&display=swap');
#lfm-container, #lfm-container *, #lfm-container *::before, #lfm-container *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
#lfm-container {
--bg: #000000;
--surface: #060606;
--border: rgba(255,255,255,0.07);
--text: #FFFFFF;
--text-dim: rgba(255,255,255,0.45);
--text-muted: rgba(255,255,255,0.18);
--accent: #ffe927;
--accent-glow: rgba(255,233,39,0.35);
--mono: 'Space Mono', monospace;
width: 100% !important;
max-width: 460px;
margin: 0 auto;
position: relative;
border: 1px solid var(--border);
background: var(--bg);
background-image: radial-gradient(circle, rgba(255,255,255,0.025) 1px, transparent 1px) !important;
background-size: 20px 20px;
color: var(--text);
font-family: var(--mono);
line-height: 1.6;
}
/* Target registration corners */
#lfm-container .reg-mark { position: absolute; width: 10px; height: 10px; pointer-events: none; }
#lfm-container .reg-mark::before, #lfm-container .reg-mark::after { content: ''; position: absolute; background: var(--text-muted); }
#lfm-container .reg-mark.tl { top: -1px; left: -1px; } #lfm-container .reg-mark.tl::before { width: 10px; height: 1px; top: 0; left: 0; } #lfm-container .reg-mark.tl::after { width: 1px; height: 10px; top: 0; left: 0; }
#lfm-container .reg-mark.tr { top: -1px; right: -1px; } #lfm-container .reg-mark.tr::before { width: 10px; height: 1px; top: 0; right: 0; } #lfm-container .reg-mark.tr::after { width: 1px; height: 10px; top: 0; right: 0; }
#lfm-container .reg-mark.bl { bottom: -1px; left: -1px; } #lfm-container .reg-mark.bl::before { width: 10px; height: 1px; bottom: 0; left: 0; } #lfm-container .reg-mark.bl::after { width: 1px; height: 10px; bottom: 0; left: 0; }
#lfm-container .reg-mark.br { bottom: -1px; right: -1px; } #lfm-container .reg-mark.br::before { width: 10px; height: 1px; bottom: 0; right: 0; } #lfm-container .reg-mark.br::after { width: 1px; height: 10px; bottom: 0; right: 0; }
#lfm-container .scan-line {
position: absolute; inset: 0; height: 1px;
background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.05) 40%, rgba(255,255,255,0.05) 60%, transparent 100%);
animation: scan 7s ease-in-out infinite; pointer-events: none; z-index: 5;
}
@keyframes scan { 0% { top: -1px; opacity: 0; } 5% { opacity: 1; } 95% { opacity: 1; } 100% { top: calc(100% + 1px); opacity: 0; } }
#lfm-container .lfm-header { padding: 28px 28px 14px; display: flex; align-items: flex-end; justify-content: space-between; }
#lfm-container .lfm-logo-fallback { font-weight: 700; font-size: 16px; letter-spacing: 0.12em; color: var(--text); }
#lfm-container .lfm-user {
font-size: 9px;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--text-muted);
line-height: 1;
text-decoration: none;
transition: color 0.2s ease;
}
#lfm-container .lfm-user:hover {
color: var(--accent);
}
#lfm-container .glyph-bar { padding: 0 28px; display: flex; align-items: center; gap: 5px; height: 24px; }
#lfm-container .glyph-seg { height: 3px; border-radius: 1.5px; background: var(--border); }
#lfm-container .glyph-seg:nth-child(1) { width: 10px; } #lfm-container .glyph-seg:nth-child(2) { width: 28px; } #lfm-container .glyph-seg:nth-child(3) { width: 52px; } #lfm-container .glyph-seg:nth-child(4) { width: 80px; } #lfm-container .glyph-seg:nth-child(5) { width: 52px; } #lfm-container .glyph-seg:nth-child(6) { width: 28px; } #lfm-container .glyph-seg:nth-child(7) { width: 10px; }
#lfm-container.is-active .glyph-seg { background: var(--accent); box-shadow: 0 0 6px var(--accent-glow); }
#lfm-container .divider { margin: 0 28px; border: none; border-top: 1px dashed var(--border); }
#lfm-container #now-playing { display: flex; align-items: center; gap: 14px; padding: 18px 28px; min-height: 56px; }
#lfm-container .led { width: 8px; height: 8px; border-radius: 50%; background: var(--text-muted); flex-shrink: 0; }
#lfm-container.is-active .led { background: var(--accent); box-shadow: 0 0 14px var(--accent-glow); animation: pulse-led 2.2s ease-in-out infinite; }
@keyframes pulse-led { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }
#lfm-container .np-info { min-width: 0; flex: 1; }
#lfm-container .np-label { font-size: 9px; letter-spacing: 0.22em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 3px; }
#lfm-container.is-active .np-label { color: var(--accent); }
#lfm-container .np-text { font-size: 13px; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.5; }
#lfm-container.is-active .np-text { color: var(--text); }
#lfm-container #track-list { list-style: none !important; padding: 0 28px !important; margin: 0 !important; }
#lfm-container .track-row { display: flex; align-items: center; gap: 12px; padding: 8px 0; border-bottom: 1px dotted var(--border); }
#lfm-container .track-row:last-child { border-bottom: none; }
#lfm-container .t-idx { font-size: 9px; color: var(--text-muted); min-width: 20px; text-align: right; font-variant-numeric: tabular-nums; flex-shrink: 0; }
#lfm-container .t-art { width: 34px; height: 34px; border: 1px solid var(--border); object-fit: cover; flex-shrink: 0; background: var(--surface); display: block; }
#lfm-container .t-art-placeholder { width: 34px; height: 34px; border: 1px solid var(--border); flex-shrink: 0; background: var(--surface); position: relative; }
#lfm-container .t-art-placeholder::after { content: ''; position: absolute; top: 50%; left: 50%; width: 4px; height: 4px; border-radius: 50%; background: var(--text-muted); transform: translate(-50%, -50%); }
#lfm-container .t-meta { flex: 1; min-width: 0; }
#lfm-container .t-name { font-size: 12px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.5; }
#lfm-container .t-artist { font-size: 11px; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.4; }
#lfm-container .lfm-footer { padding: 14px 28px 22px; display: flex; justify-content: space-between; align-items: center; font-size: 9px; color: var(--text-muted); letter-spacing: 0.18em; text-transform: uppercase; }
#lfm-container .lfm-dot { display: inline-block; width: 3px; height: 3px; border-radius: 50%; background: var(--text-muted); margin: 0 10px; vertical-align: middle; }
@media (max-width: 500px) {
#lfm-container .lfm-header { padding: 22px 18px 12px; }
#lfm-container .glyph-bar { padding: 0 18px; }
#lfm-container .divider { margin: 0 18px; }
#lfm-container #now-playing { padding: 14px 18px; }
#lfm-container #track-list { padding: 0 18px !important; }
#lfm-container .lfm-footer { padding: 12px 18px 18px; }
}
</style>
<div id="lfm-container">
<div class="reg-mark tl"></div><div class="reg-mark tr"></div><div class="reg-mark bl"></div><div class="reg-mark br"></div>
<div class="scan-line"></div>
<header class="lfm-header">
<div class="lfm-logo-fallback">LAST.FM</div>
<a class="lfm-user" href="http://last.fm/user/juanmackie" target="_blank" rel="noopener noreferrer">full history of @juanmackie</a>
</header>
<div class="glyph-bar">
<div class="glyph-seg"></div><div class="glyph-seg"></div><div class="glyph-seg"></div>
<div class="glyph-seg"></div><div class="glyph-seg"></div><div class="glyph-seg"></div><div class="glyph-seg"></div>
</div>
<hr class="divider">
<div id="now-playing">
<div class="led"></div>
<div class="np-info">
<div class="np-label" id="np-status-label">OFFLINE</div>
<div class="np-text" id="np-status-text">Currently Offline</div>
</div>
</div>
<hr class="divider">
<div id="recent-tracks">
<ul id="track-list"></ul>
</div>
<footer class="lfm-footer">
<span>Data Stream</span>
<span class="lfm-dot"></span>
<span id="track-count">0 tracks</span>
</footer>
</div>
<script>
(function() {
const username = 'juanmackie';
const apiKey = '29db0717585301fa01228bda7b30002e';
const url = `https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=${username}&api_key=${apiKey}&format=json&limit=11`;
fetch(url)
.then(response => response.json())
.then(data => {
if (!data || !data.recenttracks || !data.recenttracks.track) return;
const tracks = data.recenttracks.track;
const container = document.getElementById('lfm-container');
const list = document.getElementById('track-list');
const statusLabel = document.getElementById('np-status-label');
const statusText = document.getElementById('np-status-text');
const totalCount = document.getElementById('track-count');
let displayCount = 0;
tracks.forEach((track, index) => {
const isNowPlaying = track['@attr'] && track['@attr'].nowplaying === 'true';
const artistName = track.artist ? track.artist['#text'] : 'Unknown Artist';
const trackName = track.name || 'Unknown Track';
if (isNowPlaying && index === 0) {
if (container) container.classList.add('is-active');
if (statusLabel) statusLabel.textContent = "NOW PLAYING";
if (statusText) statusText.textContent = `${artistName} — ${trackName}`;
} else if (list && displayCount < 10) {
displayCount++;
const li = document.createElement('li');
li.className = 'track-row';
const imgs = track.image || [];
const smallImg = imgs.length > 0 ? imgs[0]['#text'] : '';
const artHtml = (smallImg && !smallImg.includes('2a96cbd8b46e442fc41c2b86b821562f'))
? `<img class="t-art" src="${smallImg}" alt="">`
: '<div class="t-art-placeholder"></div>';
li.innerHTML = `
<span class="t-idx">${String(displayCount).padStart(2, '0')}</span>
${artHtml}
<div class="t-meta">
<div class="t-name">${trackName}</div>
<div class="t-artist">${artistName}</div>
</div>
`;
list.appendChild(li);
}
});
if (totalCount) totalCount.textContent = `${displayCount} tracks`;
})
.catch(err => {
console.error('Last.fm Error:', err);
const text = document.getElementById('np-status-text');
if (text) text.textContent = 'Unable to connect to stream.';
});
})();
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment