@mangod33/syncgo
v1.0.0
Published
SyncGo is a single-process, single-port web app that syncs or transfers tracks from a **public** Spotify playlist into Navidrome (Subsonic API). The backend (Fastify) and frontend (React + Vite) run together on `localhost:3000` by default.
Readme
SyncGo
SyncGo is a single-process, single-port web app that syncs or transfers tracks from a public Spotify playlist into Navidrome (Subsonic API). The backend (Fastify) and frontend (React + Vite) run together on localhost:3000 by default.
Requirements
- Node.js 18+
- pnpm
- Navidrome with Subsonic API enabled
- Spotify API Client Credentials (public playlists only)
Setup
pnpm install
cp .env.example .envFill in .env with your Spotify app credentials (optional), Navidrome URL (optional), and database path.
SPOTIFY_CLIENT_ID=...
SPOTIFY_CLIENT_SECRET=...If you do not set Spotify credentials in .env, SyncGo will start and prompt for them after Navidrome login. The credentials entered in the UI are used only for the current session and are not saved.
If you set NAVIDROME_URL in .env, the login screen will auto-fill it (unless you already have a saved cookie), and you can also tap the link icon to apply the default.
Environment
PORT- server port (default3000)NODE_ENV-developmentorproductionNAVIDROME_URL- optional; default Navidrome URL for the login screenDATABASE_URL- SQLite file path (default./data/syncgo.db)SPOTIFY_CLIENT_ID/SPOTIFY_CLIENT_SECRET- optional; if omitted, the UI will ask per session
Development (single port)
pnpm devFastify starts on http://localhost:3000 and serves the Vite frontend through middleware.
Production (single port)
pnpm build
NODE_ENV=production pnpm startVite builds the frontend to dist/client and Fastify serves both the API and static UI from the same port.
Hosting on a domain
SyncGo is a single-port app, so you can run it on an internal port and put a reverse proxy in front of it for TLS.
- Point your domain to the server (DNS A/AAAA record).
- Open ports 80/443 on the server firewall.
- Run SyncGo on an internal port (for example
3000) withNODE_ENV=production. - Put a reverse proxy in front of it to terminate TLS and forward traffic.
NODE_ENV=production enables secure cookies, so be sure to serve SyncGo behind HTTPS in production.
Example: Caddy (recommended for automatic TLS)
yourdomain.com {
reverse_proxy 127.0.0.1:3000
}Example: Nginx
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Then enable TLS (for example with Certbot) and reload Nginx.
Service tips
- Run SyncGo under a process manager (systemd, pm2) so it stays up.
- Keep
DATABASE_URLon persistent storage. - Protect the SQLite file; it stores active Navidrome session credentials.
- If you deploy to a public server, always use HTTPS.
User flow (required order)
- Navidrome login (URL, username, password)
- Choose mode (sync or transfer)
- Validate Spotify playlist (URL or ID)
- Run job and review results / export failures
Features
- Sync / transfer modes: Sync adds missing matches; transfer creates a new Navidrome playlist.
- Dry run + apply: Dry runs do not create or modify playlists. You can apply changes after review.
- Run history: Session-only run history and summaries (no extra storage).
- Manual match: Open a failed track, search Navidrome, and add/remove a match manually.
- Preview: Spotify embed preview for the selected Spotify track and Navidrome stream previews for search results (requires Subsonic streaming enabled).
- Match tuning: Adjust fuzzy match threshold and exact duration tolerance per run.
Common troubleshooting
- INVALID_NAVIDROME_CREDENTIALS: the username/password is wrong or Subsonic API is disabled.
- NAVIDROME_UNREACHABLE: the URL is invalid, unreachable, or the server did not return JSON.
- SPOTIFY_NOT_CONFIGURED:
SPOTIFY_CLIENT_ID/SPOTIFY_CLIENT_SECRETmissing. - SPOTIFY_PRIVATE_OR_UNAVAILABLE: playlist is not public or cannot be accessed with client credentials.
Notes
- Sync mode never removes tracks; it only adds missing matches and can update the playlist public/private flag when toggled.
- Transfer mode creates a new Navidrome playlist.
- Matching order: ISRC → exact (title/artist + duration within tolerance; default 25s, adjustable 0–60s) → fuzzy (weighted title/artist; default threshold 82%).
- Failed matches can be exported from the results panel as JSON or CSV.
