All widgets

Now playing: Spotify
Comes with Chopstick
Spotify while it plays: cover, track, timeline you can scrub, play/pause, skip and shuffle.
Already installed? It's in your widget library.


Type it in the notch's search
- Play Spotify
- Show Spotify
- Pause Spotify
- Next track in Spotify
- Previous track in Spotify
What it runs
A widget is a folder of plain files. Here is all of its code.
widget.json
{
"id": "now-playing-spotify",
"name": "Now playing: Spotify",
"icon": "app:com.spotify.client",
"description": "Spotify while it plays: cover, track, timeline you can scrub, play/pause, skip and shuffle.",
"ambient": true,
"watch": [
{
"notification": "com.spotify.client.PlaybackStateChanged",
"as": "spotify",
"refresh": "spotify_live"
},
{
"script": "state.sh",
"every": 2,
"as": "spotify_live"
}
],
"show_when": {
"spotify.Player State": "Playing"
},
"initial": "playing",
"anytime": true,
"preview": {
"data": {
"spotify_live": {
"state": "playing",
"name": "Ivy",
"artist": "Frank Ocean",
"album": "Blonde",
"artwork": "https://image-cdn-fa.spotifycdn.com/image/ab67616d00001e02c5649add07ed3720be9d5526",
"position": 83,
"duration_s": 189,
"shuffling": true,
"shuffle_tint": "green",
"toggle": "pause.fill"
}
}
},
"commands": {
"play": { "phrase": "Play Spotify",
"description": "Start or resume playback in Spotify.",
"do": [
{
"set": {
"command": "play"
}
},
{
"run": "control.sh"
},
{
"refresh": "spotify_live"
}
]
},
"show": { "phrase": "Show Spotify",
"description": "Bring Spotify to the front.",
"do": [ { "set": { "command": "activate" } }, { "run": "control.sh" }, { "refresh": "spotify_live" } ]
},
"pause": { "phrase": "Pause Spotify",
"description": "Pause Spotify.",
"do": [
{
"set": {
"command": "pause"
}
},
{
"run": "control.sh"
},
{
"refresh": "spotify_live"
}
]
},
"next": { "phrase": "Next track in Spotify",
"description": "Skip to the next track.",
"do": [
{
"set": {
"command": "next track"
}
},
{
"run": "control.sh"
},
{
"refresh": "spotify_live"
}
]
},
"previous": { "phrase": "Previous track in Spotify",
"description": "Go back to the previous track.",
"do": [
{
"set": {
"command": "previous track"
}
},
{
"run": "control.sh"
},
{
"refresh": "spotify_live"
}
]
}
},
"states": {
"playing": {
"compact": {
"leading": {
"image": "{{spotify_live.artwork}}"
},
"trailing": {
"equalizer": {
"active_when": {
"spotify_live.state": "playing"
},
"tint_from_image": "{{spotify_live.artwork}}"
}
}
},
"expanded": {
"blocks": [
{
"row": [
{
"image": "{{spotify_live.artwork}}",
"size": "medium"
},
{
"stack": [
{
"text": "{{spotify_live.name | Nothing playing}}",
"style": "title",
"lines": 1
},
{
"text": "{{spotify_live.artist | Spotify}}",
"tint": "gray",
"lines": 1
}
],
"spacing": "tight"
},
"spacer",
{
"equalizer": {
"active_when": {
"spotify_live.state": "playing"
},
"tint_from_image": "{{spotify_live.artwork}}"
}
}
],
"align": "center"
},
{
"slider": {
"value": "{{spotify_live.position | 0}}",
"max": "{{spotify_live.duration_s | 0}}",
"format": "time",
"ticking_when": {
"spotify_live.state": "playing"
},
"tint_from_image": "{{spotify_live.artwork}}",
"on_change": [
{
"set": {
"command": "set player position to {{item.value}}"
}
},
{
"run": "control.sh"
},
{
"refresh": "spotify_live"
}
]
}
},
{
"row": [
"spacer",
{
"button": {
"style": "plain",
"do": [
{
"set": {
"command": "set shuffling to not shuffling"
}
},
{
"run": "control.sh"
},
{
"refresh": "spotify_live"
}
],
"symbol": "shuffle",
"tint": "{{spotify_live.shuffle_tint}}"
}
},
"spacer",
{
"button": {
"style": "plain",
"do": [
{
"set": {
"command": "previous track"
}
},
{
"run": "control.sh"
},
{
"refresh": "spotify_live"
}
],
"symbol": "backward.fill"
}
},
"spacer",
{
"button": {
"style": "plain",
"do": [
{
"set": {
"command": "playpause"
}
},
{
"run": "control.sh"
},
{
"refresh": "spotify_live"
}
],
"symbol": "{{spotify_live.toggle | play.fill}}",
"size": "large"
}
},
"spacer",
{
"button": {
"style": "plain",
"do": [
{
"set": {
"command": "next track"
}
},
{
"run": "control.sh"
},
{
"refresh": "spotify_live"
}
],
"symbol": "forward.fill"
}
},
"spacer",
{
"button": {
"style": "plain",
"do": [
{
"set": {
"command": "activate"
}
},
{
"run": "control.sh"
},
{
"refresh": "spotify_live"
}
],
"image": "app:com.spotify.client"
}
},
"spacer"
],
"align": "center"
}
],
"size": "compact"
},
"keys": [
{
"key": "space",
"do": [
{
"set": {
"command": "playpause"
}
},
{
"run": "control.sh"
}
]
},
{
"key": "esc",
"do": [
"dismiss"
]
}
]
}
}
}
control.sh
#!/bin/sh # Sends $CHOPSTICK_COMMAND to Spotify: "playpause", "next track", "previous track", # or "set player position to <seconds>". Asks once for permission to control Spotify. osascript -e "tell application id \"com.spotify.client\" to $CHOPSTICK_COMMAND"
state.sh
#!/bin/sh
# Everything the widget shows, read from Spotify as JSON: state, track, cover,
# position, length, shuffle. Prints {} without launching Spotify if it's closed.
pgrep -xq Spotify || { echo '{}'; exit 0; }
osascript -l JavaScript -e '
const s = Application("com.spotify.client"), t = s.currentTrack, state = s.playerState()
JSON.stringify({
state, name: t.name(), artist: t.artist(), album: t.album(), artwork: t.artworkUrl(),
position: Math.round(s.playerPosition()), duration_s: Math.round(t.duration() / 1000),
shuffling: s.shuffling(), shuffle_tint: s.shuffling() ? "green" : "",
toggle: state === "playing" ? "pause.fill" : "play.fill" })' 2>/dev/null || echo '{}'