Skip to content
This repository was archived by the owner on Aug 6, 2026. It is now read-only.

Latest commit

 

History

History
190 lines (139 loc) · 6.69 KB

File metadata and controls

190 lines (139 loc) · 6.69 KB

Swapify Deployment

Prerequisites

Install these CLIs before running the setup script:

# Fly.io CLI
curl -L https://fly.io/install.sh | sh
flyctl auth login

# Neon CLI (for managed Postgres)
npm i -g neonctl
neonctl auth

# GitHub CLI (for setting repo secrets)
brew install gh
gh auth login

Quick Start (Automated)

The setup script handles: secret generation, Neon DB provisioning, Fly app creation, Fly + GitHub secrets, migrations, and first deploy.

./scripts/deploy-init.sh --spotify-client-id <your-client-id>

With optional services:

./scripts/deploy-init.sh \
  --spotify-client-id <id> \
  --resend-api-key re_... \
  --anthropic-api-key sk-ant-...

Preview what it would do:

./scripts/deploy-init.sh --spotify-client-id <id> --dry-run

What the script does

  1. Generates IRON_SESSION_PASSWORD, POLL_SECRET, TOKEN_ENCRYPTION_KEY, VAPID keys
  2. Creates a Neon Postgres project (us-east-2, closest to Fly ord)
  3. Creates the Fly.io app
  4. Sets all secrets on Fly.io
  5. Creates a FLY_API_TOKEN deploy token and sets it + DATABASE_URL as GitHub repo secrets
  6. Runs npm run db:migrate against the production DB
  7. Deploys to Fly.io
  8. Verifies the health check

Manual Steps (cannot be automated)

1. Spotify Developer Dashboard

  • Go to developer.spotify.com/dashboard
  • Create a new app (or use existing) — set the app name to "Swapify"
  • Under Settings > Redirect URIs, add: https://swapify.312.dev/api/auth/callback
  • Under Settings > APIs used, ensure Web API and Web Playback SDK are checked
  • Add beta tester emails under User Management (max 5 in dev mode)
  • Set SPOTIFY_DEV_MODE=true on Fly (see Spotify Dev Mode below)
  • To go public, submit a Quota Extension Request and set SPOTIFY_DEV_MODE=false

2. DNS

  • Add a CNAME record: swapify.312.dev -> swapify.fly.dev
  • After DNS propagates, provision TLS: flyctl certs add swapify.312.dev

3. Post-Deploy Smoke Test

  • Visit https://swapify.312.dev — landing page loads
  • Login with Spotify — redirects through OAuth and lands on /dashboard
  • Create a Swaplist — Spotify playlist created
  • Share invite link — second user can join
  • Add a track — appears in Spotify playlist and in app
  • Swipe to react — reaction saved
  • curl https://swapify.312.dev/api/health returns {"status":"ok"}

CI/CD Pipeline

Deploys happen automatically via GitHub Actions on push to main:

  1. CI — lint, type-check, build
  2. Migrate — runs npm run db:migrate against production (uses DATABASE_URL secret)
  3. Deploy — flyctl deploy --remote-only (uses FLY_API_TOKEN secret)

GitHub Secrets Required

Secret Set by script Purpose
FLY_API_TOKEN Yes Fly.io deploy token
DATABASE_URL Yes Production Postgres connection string

Workflow files


Infrastructure

Component Service Cost
App server Fly.io shared-cpu-1x, 512MB, always-on ~$3.32/mo
Database Neon free tier (0.5GB, auto-suspend) $0
Total ~$3.32/mo

The machine runs 24/7 (min_machines_running = 1) because the polling loop needs to stay alive to detect Spotify listens and refresh tokens.


Schema Changes

After modifying src/db/schema.ts:

npm run db:generate          # Generate new migration SQL in drizzle/
git add drizzle/ && git commit  # Commit the migration
git push                        # Triggers: CI → migrate → deploy

Migrations run automatically in the deploy pipeline before the new code is deployed.


Fly.io Secrets Reference

Secret Required Generated by script
SPOTIFY_CLIENT_ID Yes No (you provide it)
SPOTIFY_REDIRECT_URI Yes Yes
IRON_SESSION_PASSWORD Yes Yes
POLL_SECRET Yes Yes
TOKEN_ENCRYPTION_KEY Yes Yes
DATABASE_URL Yes Yes (from Neon)
NEXT_PUBLIC_VAPID_PUBLIC_KEY Yes Yes
VAPID_PRIVATE_KEY Yes Yes
VAPID_SUBJECT Yes Yes
RESEND_API_KEY No No (you provide it)
ANTHROPIC_API_KEY No No (you provide it)
SPOTIFY_DEV_MODE No No (default: false)

Spotify Dev Mode

Set SPOTIFY_DEV_MODE=true when your Spotify app is still in development mode (not yet approved for extended quota). This activates conservative rate limiting to stay within Spotify's lower API budget for dev apps.

fly secrets set SPOTIFY_DEV_MODE=true

What dev mode does

Setting Dev Mode (true) Production (false)
Max authenticated users 5 (Spotify's dev mode limit) Unlimited
API call budget (rolling 30s) 50 calls 300 calls
Poll interval 60s 30s
Search results per query 5 10
Saved-tracks check Every 10th poll cycle Every 4th cycle
Playlist audit Every 6th poll cycle Every 2nd cycle
Liked playlist sync Every 10th poll cycle Every 4th cycle
Per-user search rate limit 10 req/min 30 req/min
Per-user mutation rate limit 8 req/min 20 req/min
Per-user general API limit 20 req/min 60 req/min

When to disable dev mode

Set SPOTIFY_DEV_MODE=false (or remove it) after your Spotify app is approved for extended quota mode. Requirements for extended quota (as of May 2025):

  • Legally registered business entity
  • 250,000+ monthly active users
  • Available in key Spotify markets
  • Active, launched service

Until then, keep dev mode enabled to avoid hitting Spotify's rate limits.

How it works

  • Global API call budget (src/lib/spotify-config.ts): Tracks all Spotify API calls in a rolling 30-second window. Every spotifyFetch call checks the budget before proceeding. If the budget is exhausted, calls wait up to 10 seconds for capacity.
  • User cap enforcement: New user signups are rejected at the OAuth callback when the user count reaches the limit. Existing users can still log in.
  • Polling throttling: Background operations (audit, saved-tracks check, liked sync) run at reduced frequencies. The polling loop aborts early if the API budget is exhausted.
  • Per-user rate limits (src/lib/rate-limit.ts): Token-bucket limits on user-facing routes (search, mutations) are halved in dev mode.