packages/docs/plugins/favorites.md
The Favorites API lets Nuclear, as well as plugins, read and modify the user's library of saved tracks, albums, and artists.
{% hint style="info" %}
Access favorites via api.Favorites.* in your plugin's lifecycle hooks. All operations are asynchronous and return Promises.
{% endhint %}
Nuclear stores three types of favorites:
| Type | What's saved |
|---|---|
| Tracks | Full track metadata |
| Albums | Album reference |
| Artists | Artist reference |
Each favorite entry includes a timestamp (addedAtIso) recording when it was added.
Favorites are identified by their source field. It's a combination of provider name and ID. Because each metadata provider stores music data differently, favorites from each provider are treated separately.
type ProviderRef = {
provider: string; // e.g., "musicbrainz", "lastfm"
id: string; // Provider-specific identifier
url?: string; // Optional link to the source
};
Adding the same track twice (same provider + ID) is a no-op. The original entry and timestamp are preserved.
Favorites are saved to disk automatically after every add/remove operation. They persist across app restarts.
{% tabs %} {% tab title="Reading favorites" %}
import type { NuclearPluginAPI } from '@nuclearplayer/plugin-sdk';
export default {
async onEnable(api: NuclearPluginAPI) {
const tracks = await api.Favorites.getTracks();
const albums = await api.Favorites.getAlbums();
const artists = await api.Favorites.getArtists();
api.Logger.info(`Library: ${tracks.length} tracks, ${albums.length} albums, ${artists.length} artists`);
// Each entry has a ref and timestamp
for (const entry of tracks) {
api.Logger.debug(`${entry.ref.title} - added ${entry.addedAtIso}`);
}
},
};
{% endtab %}
{% tab title="Adding favorites" %}
import type { NuclearPluginAPI, Track, AlbumRef, ArtistRef } from '@nuclearplayer/plugin-sdk';
export default {
async onEnable(api: NuclearPluginAPI) {
// Add a track (requires full Track object)
const track: Track = {
title: 'Paranoid Android',
artists: [{ name: 'Radiohead', roles: ['main'] }],
source: { provider: 'musicbrainz', id: 'abc123' },
};
await api.Favorites.addTrack(track);
// Add an album (AlbumRef is lighter than full Album)
const album: AlbumRef = {
title: 'OK Computer',
source: { provider: 'musicbrainz', id: 'def456' },
};
await api.Favorites.addAlbum(album);
// Add an artist
const artist: ArtistRef = {
name: 'Radiohead',
source: { provider: 'musicbrainz', id: 'ghi789' },
};
await api.Favorites.addArtist(artist);
},
};
{% endtab %}
{% tab title="Removing favorites" %}
import type { NuclearPluginAPI } from '@nuclearplayer/plugin-sdk';
export default {
async onEnable(api: NuclearPluginAPI) {
// Remove by source reference (provider + ID)
await api.Favorites.removeTrack({ provider: 'musicbrainz', id: 'abc123' });
await api.Favorites.removeAlbum({ provider: 'musicbrainz', id: 'def456' });
await api.Favorites.removeArtist({ provider: 'musicbrainz', id: 'ghi789' });
},
};
{% endtab %}
{% tab title="Checking favorite status" %}
import type { NuclearPluginAPI } from '@nuclearplayer/plugin-sdk';
export default {
async onEnable(api: NuclearPluginAPI) {
const source = { provider: 'musicbrainz', id: 'abc123' };
if (await api.Favorites.isTrackFavorite(source)) {
api.Logger.info('Track is in favorites');
}
// Same pattern for albums and artists
const isAlbumSaved = await api.Favorites.isAlbumFavorite(source);
const isArtistSaved = await api.Favorites.isArtistFavorite(source);
},
};
{% endtab %}
{% tab title="Subscribing to changes" %}
import type { NuclearPluginAPI } from '@nuclearplayer/plugin-sdk';
export default {
async onEnable(api: NuclearPluginAPI) {
const unsubscribe = api.Favorites.subscribe((favorites) => {
api.Logger.info(`Favorites updated: ${favorites.tracks.length} tracks`);
// React to changes - sync to external service, update UI, etc.
});
// Return cleanup function
return () => {
unsubscribe();
};
},
};
{% endtab %} {% endtabs %}
// Reading
api.Favorites.getTracks(): Promise<FavoriteEntry<Track>[]>
api.Favorites.getAlbums(): Promise<FavoriteEntry<AlbumRef>[]>
api.Favorites.getArtists(): Promise<FavoriteEntry<ArtistRef>[]>
// Tracks
api.Favorites.addTrack(track: Track): Promise<void>
api.Favorites.removeTrack(source: ProviderRef): Promise<void>
api.Favorites.isTrackFavorite(source: ProviderRef): Promise<boolean>
// Albums
api.Favorites.addAlbum(ref: AlbumRef): Promise<void>
api.Favorites.removeAlbum(source: ProviderRef): Promise<void>
api.Favorites.isAlbumFavorite(source: ProviderRef): Promise<boolean>
// Artists
api.Favorites.addArtist(ref: ArtistRef): Promise<void>
api.Favorites.removeArtist(source: ProviderRef): Promise<void>
api.Favorites.isArtistFavorite(source: ProviderRef): Promise<boolean>
// Subscriptions
api.Favorites.subscribe(listener: FavoritesListener): () => void