{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreiefpbhl6msqm2ladjqq3yrln6qotqvnqpmkenmslnfqtn2pq6l55e",
"uri": "at://did:plc:tluyx3vljilbzmtwqljwzkib/app.bsky.feed.post/3mpc7nmtgqxl2"
},
"path": "/article/lastfm-eleventy",
"publishedAt": "2026-06-27T19:40:48.139Z",
"site": "https://michaelbishop.me",
"tags": [
"Listening",
"LastFM API",
"dotenv",
"template",
"@11ty"
],
"textContent": "I made some improvements to my Listening page which was one of the first things I built when I got this site up and running. I’ve been using LastFM for years to track my listening habits and I wanted to be able to display that information on my site. I’ve been using the LastFM API to pull in my recently played tracks and display them on my site.\n\nFirst, using 11ty Fetch plugin I have a file in my `__data` directory `lastfm.js` that pulls in my recently played tracks from LastFM. You need to install fetch `npm install @11ty/eleventy-fetch` and then you can use it in your project. It doesn’t need to be added to your `.eleventy.js` file.\n\n\n const EleventyFetch = require(\"@11ty/eleventy-fetch\");\n require('dotenv').config();\n\n const API_KEY = process.env.LFM_API_KEY;\n\n module.exports = async function() {\n const url = `http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=miklb&api_key=${API_KEY}&limit=20&format=json`;\n\n /* This returns a promise */\n return EleventyFetch(url, {\n duration: \"1h\", // save for 1 hour\n type: \"json\" // we’ll parse JSON for you\n });\n };\n\nNote I’m storing my API key in a `.env` file and using the dotenv package to load it into my project.\n\nThen in my template I’m using the data from that file to display the recently played tracks.\n\nOne of the issues I had was that LastFM was returning duplicate tracks. I wanted to display the most recent 20 tracks but not have duplicates. I was able to use Liquid to filter the data and only display unique tracks.\n\n\n {% assign recentTracks= lastfm.recenttracks.track %}\n {% assign uniqueTrackNames = \"\" %}\n {% assign uniqueTracks =\"\" %}\n {% for track in recentTracks %}\n {% unless uniqueTrackNames contains track.name %}\n {% assign uniqueTrackNames = uniqueTrackNames | push: track.name %}\n {% assign uniqueTracks = uniqueTracks | push: track %}\n {% endunless %}\n {% endfor %}\n <ul class=\"recently-played\">\n {% for track in uniqueTracks offset:1 %}\n\nFor some reason I was getting an empty track in the first position of the array, so I’m using the `offset` filter to skip that track.",
"title": "LastFM Recently Played with Eleventy"
}