Small open source macOS app for turning Spotify playlist CSV exports into clean, deduplicated public track URLs.
CSV2URLs is a native macOS app that converts Spotify playlist CSV exports into a plain text list of public Spotify track URLs.
It is built for a narrow and practical workflow:
- open a
.csvexport - read the
Track URIcolumn - convert
spotify:track:<id>values intohttps://open.spotify.com/track/<id> - remove duplicates while preserving the first occurrence
- export the final list as
.txt
Spotify exports and third-party playlist tools often provide track references as Spotify URIs, while many downstream workflows need public web URLs instead.
CSV2URLs removes that manual conversion step and keeps the workflow local, deterministic, and fast.
Typical use cases:
- preparing track lists for sharing
- importing URLs into automation tools
- building clean text datasets from Spotify exports
- deduplicating repeated tracks from playlist dumps
- Native macOS SwiftUI interface
- Local-first processing with no network dependency
- Strict validation for the
Track URIcolumn - Duplicate removal with stable ordering
- Plain text export with one Spotify URL per line
- Small codebase with focused unit tests
- Local scripts for build/run and signed DMG release packaging
- macOS 14.0 or later
- Xcode 26.3 or later
Clone the repository and build locally:
git clone <your-fork-or-repo-url>
cd csv2urls
./script/build_and_run.shThis local run path builds the app with CODE_SIGNING_ALLOWED=NO, so a contributor can verify the project without setting up Apple Developer release signing first.
- Open a playlist CSV from Finder.
- The app reads the
Track URIcolumn. - Valid Spotify track URIs are converted into public URLs.
- Invalid rows are skipped.
- Duplicate tracks are removed while preserving first appearance order.
- Export the resulting list as a
.txtfile.
The importer expects:
- a valid CSV file
- a column named exactly
Track URI - values shaped as
spotify:track:<id>
The importer will:
- skip empty rows
- skip malformed values
- report how many invalid rows were ignored
- preserve the order of the first valid occurrences
App/ App entry point
Core/ Pure models and parsing utilities
Features/Main/ Main window and view model
Services/ CSV import service and protocol
Support/ Export document and domain errors
Tests/ Unit tests for parser and importer behavior
script/ Local developer and release scripts
The codebase is intentionally small and split by responsibility:
TrackURIExtractorvalidates and extracts the Spotify track identifier.SpotifyURLBuilderconverts a track identifier into a public Spotify URL.CSVTrackImportServiceloads CSV data withTabularData, validates rows, removes duplicates, and produces the final conversion result.ImportViewModelcoordinates file import/export and exposes UI-ready state.ContentViewrenders the desktop workflow and result preview.
This keeps parsing, transformation, UI state, and presentation separate without introducing unnecessary abstraction.
Build and run:
./script/build_and_run.shOptional modes:
./script/build_and_run.sh --debug
./script/build_and_run.sh --logs
./script/build_and_run.sh --telemetry
./script/build_and_run.sh --verifyOpen in Xcode:
open CSV2URLs.xcodeprojFor local development, the repository is intentionally not tied to a specific Apple team. If Xcode asks for signing before running or archiving on your machine, use your own local signing setup. For release builds, use your own Apple Developer signing identity, team, and notarization profile.
Run tests with:
xcodebuild -project CSV2URLs.xcodeproj -scheme CSV2URLs -destination 'platform=macOS' testCovered behavior includes:
- valid Spotify URI extraction
- malformed URI rejection
- URL generation
- missing column failures
- quoted CSV parsing
- duplicate removal
Regular contributors do not need release signing to build or test the project. Release signing is only required for creating a signed and notarized distributable DMG.
The release script:
- archives the app
- exports a signed
.app - creates a
.dmg - signs the DMG
- submits it for notarization
- staples the notarization ticket
Run:
./script/release_dmg.shBefore running the release script, configure your own signing values:
export DEVELOPER_ID_APPLICATION="Developer ID Application: Your Name (TEAMID)"
export TEAM_ID="TEAMID"
export NOTARY_PROFILE="your-notary-profile"
./script/release_dmg.shThe repository does not include personal signing identities or notarization profiles. Release signing is expected to be configured locally through environment variables.
Before using notarization, create and validate your own local notary profile:
xcrun notarytool store-credentials "your-notary-profile" \
--apple-id "your-apple-id@example.com" \
--team-id "TEAMID" \
--password "app-specific-password"
xcrun notarytool history --keychain-profile "your-notary-profile"If you plan to redistribute the app under your own Apple account, also review:
- bundle identifiers in
CSV2URLs.xcodeproj - signing settings in Xcode
- release environment variables used by
script/release_dmg.sh
Expected artifact:
build/release/CSV2URLs.dmg
Recommended GitHub repository description:
Native macOS app that converts Spotify playlist CSV exports into deduplicated public track URLs.
Recommended GitHub topics:
macosswiftswiftuispotifycsvdesktop-appplaylist-toolsdeveloper-tools
This project is licensed under the MIT License. See the LICENSE file for details.
Contributions are welcome. Start with CONTRIBUTING.md.