Skip to main content

Extensions

Extensions are JavaScript files that run alongside Spotify's main code. They can add UI elements, modify behavior, integrate with external services, and more.

Extension Structure

~/.config/spicetify/Extensions/   # Linux/macOS
%appdata%\spicetify\Extensions\ # Windows
├── myExtension.js
├── anotherExtension.js
└── ...

Extensions are single JavaScript files. For complex extensions with multiple files, use Spicetify Creator.

Getting Started

Location

Place your extension file in the Extensions folder:

PlatformPath
Windows%appdata%\spicetify\Extensions\
Linux / macOS~/.config/spicetify/Extensions/

Minimal Extension

// myExtension.js
(function myExtension() {
// Wait for Spicetify to be ready
if (!Spicetify.Player || !Spicetify.Platform) {
setTimeout(myExtension, 100);
return;
}

console.log("My extension loaded!");

// Your code here
})();

Testing Your Extension

  1. Save your file to the Extensions folder

  2. Enable it:

    spicetify config extensions myExtension.js
    spicetify apply
  3. Open DevTools in Spotify to see console output:

    • Windows/Linux: Ctrl + Shift + I
    • macOS: Cmd + Option + I

The Spicetify API

Extensions access Spotify through the global Spicetify object. Key namespaces:

NamespacePurpose
Spicetify.PlayerPlayback control (play, pause, skip, volume)
Spicetify.PlatformCore platform APIs (history, library, playlists)
Spicetify.CosmosAsyncHTTP requests to Spotify's internal API
Spicetify.URIParse and create Spotify URIs
Spicetify.ReactReact instance for UI components
Spicetify.ReactDOMReactDOM for rendering
Spicetify.TopbarAdd buttons to the top bar
Spicetify.PlaybarAdd buttons to the player bar
Spicetify.ContextMenuAdd items to right-click menus

See the API Wrapper Reference for complete documentation.


Common Patterns

Waiting for Spicetify

Always wait for Spicetify to be ready before accessing its APIs:

(function init() {
if (!Spicetify.Player || !Spicetify.Platform) {
setTimeout(init, 100);
return;
}

main();
})();

function main() {
// Safe to use Spicetify here
}

Adding a Top Bar Button

const button = new Spicetify.Topbar.Button(
"My Button",
`<svg>...</svg>`, // SVG icon
() => {
console.log("Button clicked!");
}
);

Adding a Context Menu Item

new Spicetify.ContextMenu.Item(
"My Menu Item",
(uris) => {
console.log("Selected URIs:", uris);
},
(uris) => {
// Return true to show this item
return true;
},
`<svg>...</svg>` // Optional icon
).register();

Listening to Player Events

Spicetify.Player.addEventListener("songchange", (event) => {
const track = Spicetify.Player.data?.item;
console.log("Now playing:", track?.name);
});

Making API Requests

// GET request
const response = await Spicetify.CosmosAsync.get(
"https://api.spotify.com/v1/me/player"
);

// POST request
await Spicetify.CosmosAsync.post(
"https://api.spotify.com/v1/me/player/play",
{ uris: ["spotify:track:..."] }
);

Storing Data

// Save
Spicetify.LocalStorage.set("myExtension:setting", "value");

// Load
const value = Spicetify.LocalStorage.get("myExtension:setting");

Showing Notifications

Spicetify.showNotification("Hello from my extension!");

UI Development

Using React

Spicetify exposes React for building UI:

const { React, ReactDOM } = Spicetify;
const { useState, useEffect } = React;

function MyComponent() {
const [count, setCount] = useState(0);

return React.createElement("button", {
onClick: () => setCount(c => c + 1)
}, `Clicked ${count} times`);
}

Using Spotify's Components

Access Spotify's internal React components:

const { Button, Toggle } = Spicetify.ReactComponent;

// Use in your components
React.createElement(Button, {
onClick: () => console.log("clicked")
}, "Click me");

Creating Modals

Spicetify.PopupModal.display({
title: "My Modal",
content: React.createElement("div", null, "Hello!"),
});

Spicetify Creator

For a better development experience with TypeScript, JSX, and hot reloading, use Spicetify Creator.

npx spicetify-creator

Benefits:

  • TypeScript support with full type definitions
  • JSX syntax (no manual React.createElement)
  • Hot reloading during development
  • Build tooling (bundling, minification)

Best Practices

Performance

  • Avoid polling. Use event listeners when possible
  • Debounce expensive operations
  • Clean up listeners when no longer needed

Error Handling

try {
const data = await Spicetify.CosmosAsync.get("...");
} catch (error) {
console.error("Request failed:", error);
Spicetify.showNotification("Something went wrong", true);
}

Compatibility

  • Test with both light and dark themes
  • Check for API existence before using (APIs can change between Spotify versions)
  • Use feature detection:
if (Spicetify.Topbar?.Button) {
// Safe to use
}

Naming

  • Use a unique prefix for localStorage keys: myExtension:key
  • Use descriptive function and variable names

Publishing

To share your extension:

  1. GitHub: Create a repository with your extension file(s) and installation instructions

  2. Marketplace: Submit to the Spicetify Marketplace for easy discovery and installation


Resources