diff --git a/INSTANCES.md b/INSTANCES.md
index 399ff12..3fac04f 100644
--- a/INSTANCES.md
+++ b/INSTANCES.md
@@ -18,48 +18,30 @@ The official Monochrome instance maintained by the core team:
## Community Instances
-### Community Monochrome Instances
-
-These instances are community instances of Monochrome & its WebUI:
-
-| Provider | URL | Status |
-| ------------- | ---------------------------------------- | --------- |
-| **Squid.WTF** | [mono.squid.wtf](https://mono.squid.wtf) | Community |
-
-### UI-Only Instances
-
-These instances provide the tidal-ui web interface, not monochrome:
-
-| Provider | URL | Status |
-| ------------- | ------------------------------------------- | --------- |
-| **squid.wtf** | [tidal.squid.wtf](https://tidal.squid.wtf) | Community |
-| **QQDL** | [tidal.qqdl.site](https://tidal.qqdl.site/) | Community |
-
----
+PLEASE do not use any rehost of monochrome and complain to us about features not working. They are usually out of date, and do not provide the latest features, and accounts are always broken.
## API Instances
Monochrome uses the Hi-Fi API under the hood. Live, up-to-date status trackers (which return JSON) can be found below:
-- https://tidal-uptime.jiffy-puffs-1j.workers.dev/
-- https://tidal-uptime.props-76styles.workers.dev/
+- [https://tidal-uptime.jiffy-puffs-1j.workers.dev](https://tidal-uptime.jiffy-puffs-1j.workers.dev/)
+- [https://tidal-uptime.props-76styles.workers.dev](https://tidal-uptime.props-76styles.workers.dev/)
These are available API endpoints that can be used with Monochrome or other Hi-Fi based applications:
### Official & Community APIs
-| Provider | URL | Notes |
-| ----------------- | ----------------------------------- | ----------------------------------------------------------------------- |
-| **Monochrome** | `https://monochrome-api.samidy.com` | Official API |
-| | `https://api.monochrome.tf` | Official API |
-| | `https://arran.monochrome.tf` | Official API |
-| **squid.wtf** | `https://triton.squid.wtf` | Community hosted |
-| **Lucida (QQDL)** | `https://wolf.qqdl.site` | Community hosted |
-| | `https://maus.qqdl.site` | Community hosted |
-| | `https://vogel.qqdl.site` | Community hosted |
-| | `https://katze.qqdl.site` | Community hosted |
-| | `https://hund.qqdl.site` | Community hosted |
-| **Kinoplus** | `https://tidal.kinoplus.online` | Community hosted - [Limited/No-Sub](https://rentry.co/limitedtidalaccs) |
+| Provider | URL | Notes |
+| ----------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------ |
+| **Monochrome** | `https://monochrome-api.samidy.com` | Official API |
+| | `https://api.monochrome.tf` | Official API |
+| **geeked.wtf** | `https://hifi.geeked.wtf` | Community hosted - uses the [TypeScript Rewrite](https://github.com/monochrome-music/hifi-api-workers) |
+| **Lucida (QQDL)** | `https://wolf.qqdl.site` | Community hosted |
+| | `https://maus.qqdl.site` | Community hosted |
+| | `https://vogel.qqdl.site` | Community hosted |
+| | `https://katze.qqdl.site` | Community hosted |
+| | `https://hund.qqdl.site` | Community hosted |
+| **Kinoplus** | `https://tidal.kinoplus.online` | Community hosted - [Limited/No-Sub](https://rentry.co/limitedtidalaccs) |
---
diff --git a/functions/album/[id].js b/functions/album/[id].js
index 5f73a01..b75c0bf 100644
--- a/functions/album/[id].js
+++ b/functions/album/[id].js
@@ -72,16 +72,18 @@ class ServerAPI {
}
if (data) {
- this.apiInstances = (data.api || []).map((item) => item.url || item);
+ this.apiInstances = (data.api || [])
+ .map((item) => item.url || item)
+ .filter((url) => !/\.squid\.wtf/i.test(url));
return this.apiInstances;
}
console.error('Failed to load instances from all uptime APIs');
return [
+ 'https://hifi.geeked.wtf',
'https://eu-central.monochrome.tf',
'https://us-west.monochrome.tf',
'https://arran.monochrome.tf',
- 'https://triton.squid.wtf',
'https://api.monochrome.tf',
'https://monochrome-api.samidy.com',
'https://maus.qqdl.site',
@@ -135,9 +137,10 @@ class ServerAPI {
export async function onRequest(context) {
const { request, params, env } = context;
const userAgent = request.headers.get('User-Agent') || '';
- const isBot = /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot/i.test(
- userAgent
- );
+ const isBot =
+ /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot|telegrambot|linkedinbot|mastodon|signal|snapchat|redditbot|skypeuripreview|viberbot|linebot|embedly|quora|outbrain|tumblr|duckduckbot|yandexbot|rogerbot|showyoubot|kakaotalk|naverbot|seznambot|mediapartners|adsbot|petalbot|applebot|ia_archiver/i.test(
+ userAgent
+ );
const albumId = params.id;
if (isBot && albumId) {
diff --git a/functions/artist/[id].js b/functions/artist/[id].js
index bef8df8..1c62591 100644
--- a/functions/artist/[id].js
+++ b/functions/artist/[id].js
@@ -135,9 +135,10 @@ class ServerAPI {
export async function onRequest(context) {
const { request, params, env } = context;
const userAgent = request.headers.get('User-Agent') || '';
- const isBot = /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot/i.test(
- userAgent
- );
+ const isBot =
+ /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot|telegrambot|linkedinbot|mastodon|signal|snapchat|redditbot|skypeuripreview|viberbot|linebot|embedly|quora|outbrain|tumblr|duckduckbot|yandexbot|rogerbot|showyoubot|kakaotalk|naverbot|seznambot|mediapartners|adsbot|petalbot|applebot|ia_archiver/i.test(
+ userAgent
+ );
const artistId = params.id;
if (isBot && artistId) {
diff --git a/functions/playlist/[id].js b/functions/playlist/[id].js
index f254bf5..15fe6f6 100644
--- a/functions/playlist/[id].js
+++ b/functions/playlist/[id].js
@@ -72,7 +72,9 @@ class ServerAPI {
}
if (data) {
- this.apiInstances = (data.api || []).map((item) => item.url || item);
+ this.apiInstances = (data.api || [])
+ .map((item) => item.url || item)
+ .filter((url) => !/\.squid\.wtf/i.test(url));
return this.apiInstances;
}
@@ -81,7 +83,6 @@ class ServerAPI {
'https://eu-central.monochrome.tf',
'https://us-west.monochrome.tf',
'https://arran.monochrome.tf',
- 'https://triton.squid.wtf',
'https://api.monochrome.tf',
'https://monochrome-api.samidy.com',
'https://maus.qqdl.site',
@@ -135,9 +136,10 @@ class ServerAPI {
export async function onRequest(context) {
const { request, params, env } = context;
const userAgent = request.headers.get('User-Agent') || '';
- const isBot = /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot/i.test(
- userAgent
- );
+ const isBot =
+ /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot|telegrambot|linkedinbot|mastodon|signal|snapchat|redditbot|skypeuripreview|viberbot|linebot|embedly|quora|outbrain|tumblr|duckduckbot|yandexbot|rogerbot|showyoubot|kakaotalk|naverbot|seznambot|mediapartners|adsbot|petalbot|applebot|ia_archiver/i.test(
+ userAgent
+ );
const playlistId = params.id;
if (isBot && playlistId) {
diff --git a/functions/podcasts/[id].js b/functions/podcasts/[id].js
new file mode 100644
index 0000000..25586fe
--- /dev/null
+++ b/functions/podcasts/[id].js
@@ -0,0 +1,99 @@
+// functions/podcasts/[id].js
+
+const PODCASTINDEX_API_BASE = 'https://api.podcastindex.org/api/1.0';
+const PODCAST_API_KEY = 'YU5HMSDYBQQVYDF6QN4P';
+const PODCAST_API_SECRET = '8hCvpjSL7T$S7^5ftnf5MhqQwYUYVjM^fmUL3Ld$';
+
+async function sha1(str) {
+ const encoder = new TextEncoder();
+ const data = encoder.encode(str);
+ const hashBuffer = await crypto.subtle.digest('SHA-1', data);
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
+ return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
+}
+
+async function getAuthHeaders() {
+ const apiHeaderTime = Math.floor(Date.now() / 1000).toString();
+ const combined = PODCAST_API_KEY + PODCAST_API_SECRET + apiHeaderTime;
+ const authHeader = await sha1(combined);
+ return {
+ 'User-Agent': 'MonochromeMusic/1.0',
+ 'X-Auth-Key': PODCAST_API_KEY,
+ 'X-Auth-Date': apiHeaderTime,
+ Authorization: authHeader,
+ };
+}
+
+export async function onRequest(context) {
+ const { request, params, env } = context;
+ const userAgent = request.headers.get('User-Agent') || '';
+ const isBot =
+ /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot|telegrambot|linkedinbot|mastodon|signal|snapchat|redditbot|skypeuripreview|viberbot|linebot|embedly|quora|outbrain|tumblr|duckduckbot|yandexbot|rogerbot|showyoubot|kakaotalk|naverbot|seznambot|mediapartners|adsbot|petalbot|applebot|ia_archiver/i.test(
+ userAgent
+ );
+ const podcastId = params.id;
+
+ if (isBot && podcastId) {
+ try {
+ const headers = await getAuthHeaders();
+ const response = await fetch(`${PODCASTINDEX_API_BASE}/podcasts/byfeedid?id=${podcastId}&pretty`, {
+ method: 'GET',
+ headers,
+ });
+
+ if (!response.ok) throw new Error(`PodcastIndex error: ${response.status}`);
+
+ const data = await response.json();
+ const feed = data.status === 'true' && data.feed ? data.feed : null;
+
+ if (feed && feed.title) {
+ const title = feed.title;
+ const author = feed.author || feed.ownerName || '';
+ const episodeCount = feed.episodeCount || 0;
+ const rawDescription = feed.description || '';
+ const description = author
+ ? `Podcast by ${author} • ${episodeCount} Episodes\nListen on Monochrome`
+ : `Podcast • ${episodeCount} Episodes\nListen on Monochrome`;
+ const imageUrl = feed.image || feed.artwork || 'https://monochrome.tf/assets/appicon.png';
+ const pageUrl = new URL(request.url).href;
+
+ const metaHtml = `
+
+
+
+
+ ${title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${title}
+ ${description}
+
+
+
+ `;
+
+ return new Response(metaHtml, { headers: { 'content-type': 'text/html;charset=UTF-8' } });
+ }
+ } catch (error) {
+ console.error(`Error for podcast ${podcastId}:`, error);
+ }
+ }
+
+ const url = new URL(request.url);
+ url.pathname = '/';
+ return env.ASSETS.fetch(new Request(url, request));
+}
diff --git a/functions/track/[id].js b/functions/track/[id].js
index bf2205d..cf50d44 100644
--- a/functions/track/[id].js
+++ b/functions/track/[id].js
@@ -165,9 +165,10 @@ class ServerAPI {
export async function onRequest(context) {
const { request, params, env } = context;
const userAgent = request.headers.get('User-Agent') || '';
- const isBot = /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot/i.test(
- userAgent
- );
+ const isBot =
+ /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot|telegrambot|linkedinbot|mastodon|signal|snapchat|redditbot|skypeuripreview|viberbot|linebot|embedly|quora|outbrain|tumblr|duckduckbot|yandexbot|rogerbot|showyoubot|kakaotalk|naverbot|seznambot|mediapartners|adsbot|petalbot|applebot|ia_archiver/i.test(
+ userAgent
+ );
const trackId = params.id;
if (isBot && trackId) {
diff --git a/functions/user/@[username].js b/functions/user/@[username].js
index 507d9cd..a603acf 100644
--- a/functions/user/@[username].js
+++ b/functions/user/@[username].js
@@ -3,9 +3,10 @@
export async function onRequest(context) {
const { request, params, env } = context;
const userAgent = request.headers.get('User-Agent') || '';
- const isBot = /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot/i.test(
- userAgent
- );
+ const isBot =
+ /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot|telegrambot|linkedinbot|mastodon|signal|snapchat|redditbot|skypeuripreview|viberbot|linebot|embedly|quora|outbrain|tumblr|duckduckbot|yandexbot|rogerbot|showyoubot|kakaotalk|naverbot|seznambot|mediapartners|adsbot|petalbot|applebot|ia_archiver/i.test(
+ userAgent
+ );
const username = params.username;
if (isBot && username) {
diff --git a/functions/userplaylist/[id].js b/functions/userplaylist/[id].js
new file mode 100644
index 0000000..631b4c9
--- /dev/null
+++ b/functions/userplaylist/[id].js
@@ -0,0 +1,116 @@
+// functions/userplaylist/[id].js
+
+const POCKETBASE_URL = 'https://data.samidy.xyz';
+const PUBLIC_COLLECTION = 'public_playlists';
+
+export async function onRequest(context) {
+ const { request, params, env } = context;
+ const userAgent = request.headers.get('User-Agent') || '';
+ const isBot =
+ /discordbot|twitterbot|facebookexternalhit|bingbot|googlebot|slurp|whatsapp|pinterest|slackbot|telegrambot|linkedinbot|mastodon|signal|snapchat|redditbot|skypeuripreview|viberbot|linebot|embedly|quora|outbrain|tumblr|duckduckbot|yandexbot|rogerbot|showyoubot|kakaotalk|naverbot|seznambot|mediapartners|adsbot|petalbot|applebot|ia_archiver/i.test(
+ userAgent
+ );
+ const playlistId = params.id;
+
+ if (isBot && playlistId) {
+ try {
+ const filter = `uuid="${playlistId}"`;
+ const apiUrl = `${POCKETBASE_URL}/api/collections/${PUBLIC_COLLECTION}/records?filter=${encodeURIComponent(filter)}&perPage=1`;
+
+ const response = await fetch(apiUrl);
+ if (!response.ok) throw new Error(`PocketBase error: ${response.status}`);
+
+ const result = await response.json();
+ const record = result.items && result.items.length > 0 ? result.items[0] : null;
+
+ if (record) {
+ let extraData = {};
+ try {
+ extraData = record.data ? JSON.parse(record.data) : {};
+ } catch {
+ extraData = {};
+ }
+
+ const title =
+ record.title ||
+ record.name ||
+ (extraData && (extraData.title || extraData.name)) ||
+ 'Untitled Playlist';
+
+ let tracks = [];
+ try {
+ tracks = record.tracks ? JSON.parse(record.tracks) : [];
+ } catch {
+ tracks = [];
+ }
+
+ const trackCount = tracks.length;
+
+ let rawCover = record.image || record.cover || record.playlist_cover || '';
+ if (!rawCover && extraData && typeof extraData === 'object') {
+ rawCover = extraData.cover || extraData.image || '';
+ }
+
+ let imageUrl = '';
+ if (rawCover && (rawCover.startsWith('http') || rawCover.startsWith('data:'))) {
+ imageUrl = rawCover;
+ } else if (rawCover) {
+ imageUrl = `${POCKETBASE_URL}/api/files/${PUBLIC_COLLECTION}/${record.id}/${rawCover}`;
+ }
+
+ if (!imageUrl && tracks.length > 0) {
+ const firstCover = tracks.find((t) => t.album?.cover)?.album?.cover;
+ if (firstCover) {
+ const formattedId = String(firstCover).replace(/-/g, '/');
+ imageUrl = `https://resources.tidal.com/images/${formattedId}/1080x1080.jpg`;
+ }
+ }
+
+ if (!imageUrl) {
+ imageUrl = 'https://monochrome.tf/assets/appicon.png';
+ }
+
+ const description = `Playlist • ${trackCount} Tracks\nListen on Monochrome`;
+ const pageUrl = new URL(request.url).href;
+
+ const metaHtml = `
+
+
+
+
+ ${title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${title}
+ ${description}
+
+
+
+ `;
+
+ return new Response(metaHtml, { headers: { 'content-type': 'text/html;charset=UTF-8' } });
+ }
+ } catch (error) {
+ console.error(`Error for user playlist ${playlistId}:`, error);
+ }
+ }
+
+ const url = new URL(request.url);
+ url.pathname = '/';
+ return env.ASSETS.fetch(new Request(url, request));
+}
diff --git a/js/listenbrainz.js b/js/listenbrainz.js
index e894a61..0310c16 100644
--- a/js/listenbrainz.js
+++ b/js/listenbrainz.js
@@ -249,7 +249,7 @@ export class ListenBrainzScrobbler {
}
async loveTrack(track) {
- if (!track.artist?.name || track.title) return;
+ if (!track.artist?.name || !track.title) return;
const trackKey = `${track.artist.name}-${track.title}`;
if (!this.isEnabled() || this.lovingTracks.has(trackKey)) return;
this.lovingTracks.add(trackKey);
diff --git a/js/settings.js b/js/settings.js
index b8af8f3..741fbb9 100644
--- a/js/settings.js
+++ b/js/settings.js
@@ -2731,15 +2731,6 @@ export async function initializeSettings(scrobbler, player, api, ui) {
});
}
- const sidebarShowDownloadToggle = document.getElementById('sidebar-show-download-bottom-toggle');
- if (sidebarShowDownloadToggle) {
- sidebarShowDownloadToggle.checked = sidebarSectionSettings.shouldShowDownload();
- sidebarShowDownloadToggle.addEventListener('change', (e) => {
- sidebarSectionSettings.setShowDownload(e.target.checked);
- sidebarSectionSettings.applySidebarVisibility();
- });
- }
-
const sidebarShowDiscordToggle = document.getElementById('sidebar-show-discordbtn-toggle');
if (sidebarShowDiscordToggle) {
sidebarShowDiscordToggle.checked = sidebarSectionSettings.shouldShowDiscord();
diff --git a/js/storage.js b/js/storage.js
index 570f1cc..6f8a0a4 100644
--- a/js/storage.js
+++ b/js/storage.js
@@ -77,28 +77,25 @@ export const apiSettings = {
console.error('Failed to load instances from all uptime APIs:', fetchError);
this.defaultInstances = {
api: [
- { url: 'https://eu-central.monochrome.tf', version: '2.4' },
- { url: 'https://us-west.monochrome.tf', version: '2.4' },
- { url: 'https://arran.monochrome.tf', version: '2.4' },
- { url: 'https://triton.squid.wtf', version: '2.4' },
- { url: 'https://api.monochrome.tf', version: '2.3' },
+ { url: 'https://hifi.geeked.wtf', version: '2.7' },
+ { url: 'https://eu-central.monochrome.tf', version: '2.7' },
+ { url: 'https://us-west.monochrome.tf', version: '2.7' },
+ { url: 'https://api.monochrome.tf', version: '2.5' },
{ url: 'https://monochrome-api.samidy.com', version: '2.3' },
- { url: 'https://maus.qqdl.site', version: '2.2' },
- { url: 'https://vogel.qqdl.site', version: '2.2' },
- { url: 'https://katze.qqdl.site', version: '2.2' },
- { url: 'https://hund.qqdl.site', version: '2.2' },
+ { url: 'https://maus.qqdl.site', version: '2.6' },
+ { url: 'https://vogel.qqdl.site', version: '2.6' },
+ { url: 'https://katze.qqdl.site', version: '2.6' },
+ { url: 'https://hund.qqdl.site', version: '2.6' },
{ url: 'https://tidal.kinoplus.online', version: '2.2' },
{ url: 'https://wolf.qqdl.site', version: '2.2' },
],
streaming: [
- { url: 'https://arran.monochrome.tf', version: '2.4' },
- { url: 'https://triton.squid.wtf', version: '2.4' },
- { url: 'https://maus.qqdl.site', version: '2.2' },
- { url: 'https://vogel.qqdl.site', version: '2.2' },
- { url: 'https://katze.qqdl.site', version: '2.2' },
- { url: 'https://hund.qqdl.site', version: '2.2' },
- { url: 'https://wolf.qqdl.site', version: '2.2' },
- { url: 'https://hifi.p1nkhamster.xyz/', version: '2.6' },
+ { url: 'https://hifi.geeked.wtf', version: '2.7' },
+ { url: 'https://maus.qqdl.site', version: '2.6' },
+ { url: 'https://vogel.qqdl.site', version: '2.6' },
+ { url: 'https://katze.qqdl.site', version: '2.6' },
+ { url: 'https://hund.qqdl.site', version: '2.6' },
+ { url: 'https://wolf.qqdl.site', version: '2.6' },
],
};
this.instancesLoaded = true;
@@ -108,12 +105,17 @@ export const apiSettings = {
let groupedInstances = { api: [], streaming: [] };
+ const isBlockedInstance = (item) => {
+ const url = typeof item === 'string' ? item : item.url;
+ return url && /\.squid\.wtf/i.test(url);
+ };
+
if (data.api && Array.isArray(data.api)) {
- groupedInstances.api = data.api;
+ groupedInstances.api = data.api.filter((item) => !isBlockedInstance(item));
}
if (data.streaming && Array.isArray(data.streaming)) {
- groupedInstances.streaming = data.streaming;
+ groupedInstances.streaming = data.streaming.filter((item) => !isBlockedInstance(item));
} else if (groupedInstances.api.length > 0) {
groupedInstances.streaming = [...groupedInstances.api];
}
@@ -1806,7 +1808,6 @@ export const sidebarSectionSettings = {
SHOW_DONATE_KEY: 'sidebar-show-donate',
SHOW_SETTINGS_KEY: 'sidebar-show-settings',
SHOW_ABOUT_KEY: 'sidebar-show-about',
- SHOW_DOWNLOAD_KEY: 'sidebar-show-download',
SHOW_DISCORD_KEY: 'sidebar-show-discord',
SHOW_GITHUB_KEY: 'sidebar-show-github',
ORDER_KEY: 'sidebar-menu-order',
@@ -1818,7 +1819,6 @@ export const sidebarSectionSettings = {
'sidebar-nav-donate',
'sidebar-nav-settings',
'sidebar-nav-about-bottom',
- 'sidebar-nav-download-bottom',
'sidebar-nav-discordbtn',
'sidebar-nav-githubbtn',
],
@@ -1919,19 +1919,6 @@ export const sidebarSectionSettings = {
localStorage.setItem(this.SHOW_ABOUT_KEY, enabled ? 'true' : 'false');
},
- shouldShowDownload() {
- try {
- const val = localStorage.getItem(this.SHOW_DOWNLOAD_KEY);
- return val === null ? true : val === 'true';
- } catch {
- return true;
- }
- },
-
- setShowDownload(enabled) {
- localStorage.setItem(this.SHOW_DOWNLOAD_KEY, enabled ? 'true' : 'false');
- },
-
shouldShowDiscord() {
try {
const val = localStorage.getItem(this.SHOW_DISCORD_KEY);
@@ -2016,7 +2003,6 @@ export const sidebarSectionSettings = {
{ id: 'sidebar-nav-donate', check: this.shouldShowDonate() },
{ id: 'sidebar-nav-settings', check: this.shouldShowSettings() },
{ id: 'sidebar-nav-about-bottom', check: this.shouldShowAbout() },
- { id: 'sidebar-nav-download-bottom', check: this.shouldShowDownload() },
{ id: 'sidebar-nav-discordbtn', check: this.shouldShowDiscord() },
{ id: 'sidebar-nav-githubbtn', check: this.shouldShowGithub() },
];
diff --git a/js/tracker.js b/js/tracker.js
index fe8350d..8c95654 100644
--- a/js/tracker.js
+++ b/js/tracker.js
@@ -107,7 +107,7 @@ function transformErasImages(eras) {
}
async function fetchTrackerData(sheetId) {
- const endpoints = ['https://trackerapi-2.artistgrid.cx/get/', 'https://trackerapi-2.artistgrid.cx/get/'];
+ const endpoints = ['https://trackerapi-1.artistgrid.cx/get/', 'https://trackerapi-2.artistgrid.cx/get/'];
let lastError = null;
for (const baseUrl of endpoints) {