Skip to content

skerjie/csv2urls

CSV2URLs

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 .csv export
  • read the Track URI column
  • convert spotify:track:<id> values into https://open.spotify.com/track/<id>
  • remove duplicates while preserving the first occurrence
  • export the final list as .txt

Why This App Exists

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

Features

  • Native macOS SwiftUI interface
  • Local-first processing with no network dependency
  • Strict validation for the Track URI column
  • 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

Requirements

  • macOS 14.0 or later
  • Xcode 26.3 or later

Quick Start

Clone the repository and build locally:

git clone <your-fork-or-repo-url>
cd csv2urls
./script/build_and_run.sh

This 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.

Screens and Workflow

  1. Open a playlist CSV from Finder.
  2. The app reads the Track URI column.
  3. Valid Spotify track URIs are converted into public URLs.
  4. Invalid rows are skipped.
  5. Duplicate tracks are removed while preserving first appearance order.
  6. Export the resulting list as a .txt file.

Input Rules

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

Project Structure

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

Architecture Summary

The codebase is intentionally small and split by responsibility:

  • TrackURIExtractor validates and extracts the Spotify track identifier.
  • SpotifyURLBuilder converts a track identifier into a public Spotify URL.
  • CSVTrackImportService loads CSV data with TabularData, validates rows, removes duplicates, and produces the final conversion result.
  • ImportViewModel coordinates file import/export and exposes UI-ready state.
  • ContentView renders the desktop workflow and result preview.

This keeps parsing, transformation, UI state, and presentation separate without introducing unnecessary abstraction.

Local Development

Build and run:

./script/build_and_run.sh

Optional modes:

./script/build_and_run.sh --debug
./script/build_and_run.sh --logs
./script/build_and_run.sh --telemetry
./script/build_and_run.sh --verify

Open in Xcode:

open CSV2URLs.xcodeproj

For 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.

Testing

Run tests with:

xcodebuild -project CSV2URLs.xcodeproj -scheme CSV2URLs -destination 'platform=macOS' test

Covered behavior includes:

  • valid Spotify URI extraction
  • malformed URI rejection
  • URL generation
  • missing column failures
  • quoted CSV parsing
  • duplicate removal

Release Packaging

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.sh

Before 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.sh

The 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

Open Source Metadata

Recommended GitHub repository description:

Native macOS app that converts Spotify playlist CSV exports into deduplicated public track URLs.

Recommended GitHub topics:

  • macos
  • swift
  • swiftui
  • spotify
  • csv
  • desktop-app
  • playlist-tools
  • developer-tools

License

This project is licensed under the MIT License. See the LICENSE file for details.

Contributing

Contributions are welcome. Start with CONTRIBUTING.md.