Nightly job that reads tracks from source Spotify playlists, stores the unique track URI list in MongoDB, and replaces one destination playlist with that compiled list.
GET /loginstarts Spotify authorization.GET /callbackreceives Spotify's authorization code. Add this exact URL to the Spotify app redirect URI allowlist.POST /syncruns the whole sync. SendAuthorization: Bearer $CRON_SECRET.GET /auth/statusreturns non-secret authorization status.GET /statusreturns a basic health check.
Legacy endpoints still exist, but now require the cron secret:
GET /refresh_tokenGET /pull_songsGET /update_playlist
Set these in App Engine:
MONGOURI: MongoDB connection string.SPOTIFY_CLIENT_ID: Spotify Developer Dashboard client ID.SPOTIFY_CLIENT_SECRET: Spotify Developer Dashboard client secret.SPOTIFY_REDIRECT_URI: Full callback URL, for examplehttps://YOUR_PROJECT.REGION_ID.r.appspot.com/callback.PLAYLISTID: destination Spotify playlist ID.CRON_SECRET: long random value shared with GitHub Actions.
Optional:
SOURCE_PLAYLIST_IDS: comma-separated source playlist IDs. If omitted, the app reads MongoDB collectionspotifycompDB.playlistsdocument{ locator: "playlists" }and expects aplaylistsarray of strings or objects withid.MONGO_DB_NAME: defaults tospotifycompDB.MONGO_AUTH_COLLECTION: defaults toauth.MONGO_PLAYLISTS_COLLECTION: defaults toplaylists.MONGO_TRACKS_COLLECTION: defaults touris.
Do not commit secrets to app.yaml in this public repo.
Recommended deployment pattern:
- Create a local untracked deployment file, for example
app.deploy.yaml, with the same runtime settings plusenv_variables. - Add
app.deploy.yamlto.git/info/excludeor.gitignorebefore adding secrets. - Deploy from your machine with
gcloud app deploy app.deploy.yaml.
Example local-only app.deploy.yaml:
runtime: nodejs24
instance_class: F1
env: standard
env_variables:
NODE_ENV: production
MONGOURI: "mongodb+srv://..."
SPOTIFY_CLIENT_ID: "..."
SPOTIFY_CLIENT_SECRET: "..."
SPOTIFY_REDIRECT_URI: "https://YOUR_PROJECT.REGION_ID.r.appspot.com/callback"
PLAYLISTID: "..."
CRON_SECRET: "..."
SOURCE_PLAYLIST_IDS: "playlist_id_1,playlist_id_2"- Create or update a Spotify app.
- Add the exact redirect URI from
SPOTIFY_REDIRECT_URI. Spotify requires exact matching and HTTPS for non-loopback redirect URIs. - Use Authorization Code flow. This app stores only server-side tokens in MongoDB.
- Authorize once by visiting
/loginafter deployment.
Spotify refresh tokens for Developer Dashboard apps expire after 6 months. The app refreshes hourly access tokens automatically, but after the refresh token expires you must visit /login again. /auth/status reports the approximate refresh token expiration when known.
Set repository secrets:
APP_CRON_URL: base URL of the deployed App Engine service, for examplehttps://YOUR_PROJECT.REGION_ID.r.appspot.com.CRON_SECRET: same value as App EngineCRON_SECRET.
The workflow calls:
curl --fail --show-error --silent \
--request POST \
--header "Authorization: Bearer ${CRON_SECRET}" \
"${APP_CRON_URL}/sync"Create .env locally:
MONGOURI="mongodb://127.0.0.1:27017"
SPOTIFY_CLIENT_ID="..."
SPOTIFY_CLIENT_SECRET="..."
SPOTIFY_REDIRECT_URI="http://127.0.0.1:8080/callback"
PLAYLISTID="..."
CRON_SECRET="..."
SOURCE_PLAYLIST_IDS="playlist_id_1,playlist_id_2"For local Spotify auth, add http://127.0.0.1:8080/callback to the Spotify redirect URI allowlist. Spotify no longer accepts localhost for newly validated redirect URIs.