Skip to content

Migrate to typescript & tauri - #1

Draft
Advik-B wants to merge 26 commits into
cupidbity:mainfrom
Advik-B:tauri
Draft

Migrate to typescript & tauri#1
Advik-B wants to merge 26 commits into
cupidbity:mainfrom
Advik-B:tauri

Conversation

@Advik-B

@Advik-B Advik-B commented May 15, 2026

Copy link
Copy Markdown

Title.
For some context, I am coming from this comment(s):
image
image

Basically,

  1. I migrated all the JavaScript files to typescript for better type safety and intellisense
  2. I removed the dependency on electron because its bloated, slow, and inefficient, also because JavaScript does NOT belong on the server (desktop in this case)
  3. Rewrote the backend in rust for tauri
  4. Made it so that yt-dlp is auto downloaded/updated on app start-up. (Note: This may cause slow start-up on the FIRST launch, however, the subsequent launches will be significantly faster)
  5. App now comes around at 14 MB because the bloat has been removed. [1]
image

This PR is in a draft since I have NOT tested out the ACTUAL music playback myself. The time is 3:15 AM for me, and I've interrupted my doomscrolling for this sidequest, and I want to go to bed.

There are already some bugfix commits.
More will follow once I wake up and have my coffee.

[1]: The windows executable. I've yet to test it for MacOS. If we bundle yt-dlp (which I do not recommend), then its 23MB

Advik-B added 22 commits May 16, 2026 01:27
Introduce Tauri Rust side scaffolding for the Cupid Player app. Adds Cargo.toml and build.rs, tauri.conf.json, a small lib/main pair that runs a Tauri builder (with debug logging plugin enabled in debug builds), and a default capabilities file. Includes .gitignore and a full set of app icons (desktop, Android, iOS) and launcher resources. Bundling config maps frontend dist, resources (audio/assets), external binaries, deep link protocol (cupid), and platform bundle settings. Dependencies added: tauri, tauri-build, tauri plugins, serde, tokio, jsonwebtoken, and related crates.
Extend the Tauri backend with state, utilities and commands for streaming, Apple Music auth, window management and theming. Adds StreamCache, AppleMusicState and MaximizeState plus helpers (yt_dlp_path, EXE_SUFFIX, ASPECT) and a CACHE_TTL. Implements get_stream_url (yt-dlp invocation with 15s timeout and 25min in-memory cache), get_apple_music_token (ES256 JWT creation from .p8 key with caching), window_resize and window_maximize (aspect-preserving resizing/restore), and set_theme (load favicon as window icon). Registers tauri plugins (shell, deep_link), manages the new states and forwards deep-link URLs to the frontend.
Replace Electron-based build/dev setup with Tauri: update package.json scripts and dependencies to use cargo tauri and @tauri-apps/cli/api, adjust vite config (publicDir, host). Integrate Tauri APIs in the frontend (invoke, listen, getCurrentWindow, plugin-shell open) and update Spotify/Apple auth flows and window controls to use Tauri commands. Add deep-link plugin and capability permissions in tauri.conf.json and forward cupid:// callbacks from Rust to the renderer. Add image crate and adjust Rust icon loading to decode images with the image crate, plus minor Tauri setup changes in src-tauri (Cargo.toml). Include yt-dlp binary and add public/audio/.gitkeep; update audio path usage in player hooks.
Replace Electron tooling and dependencies with Tauri equivalents. Updates include package.json/package-lock.json to remove Electron, electron-builder and other Electron-specific dev deps and add @tauri-apps/api, @tauri-apps/cli and @tauri-apps/plugin-shell; switch some browser-oriented packages (e.g. music-metadata -> music-metadata-browser). Also update src-tauri/Cargo.toml and src-tauri/tauri.conf.json to configure the Tauri runtime. This migrates the app from an Electron-based build to Tauri for a smaller, native wrapper and simplified dev tooling.
Add reqwest (0.12 with rustls-tls, json and stream features) and futures-util (0.3) to src-tauri/Cargo.toml to enable HTTP client and async utilities in the Tauri backend. Cargo.lock was updated to record the resolved transitive dependencies.
Rename React entry and components to .tsx/.ts, convert Spotify and Apple modules to TypeScript, and add strong typings. Added src/types.ts for shared types and updated imports across App, auth, api, player, hooks and playlist. Replaced JS Spotify player wrapper with a typed player.ts, migrated MusicKit helpers to auth.ts, and updated main.tsx. Small runtime/logic cleanups and type annotations (error handling, event payloads, DOM refs, timers) and removal of the old .js/.jsx files.
Rename vite.config.js to vite.config.ts to use a TypeScript Vite config. No functional changes aside from a minor whitespace edit; existing plugins and base config are preserved to enable typed config and improved editor/tooling support.
Introduce yt-dlp management: add YtDlpState to cache a resolved binary path and helpers to compute platform asset and binary names. Implement async fetch_latest_yt_dlp_version, download_yt_dlp (emits yt-dlp-progress), resolve_yt_dlp resolution logic (managed app data, sidecar, system), and update_yt_dlp_if_needed which writes a version file and emits yt-dlp-updated. Use resolve_yt_dlp from get_stream_url and add STREAM_CACHE_TTL constant. Kick off a non-blocking startup update/download task and register YtDlpState with the app. Also include minor refactors and cleanup: compact struct initializers, improve Apple Music key lookup error message, tighten JWT/claims formatting, and simplify window resize/maximize sizing/position logic and other small formatting tweaks.
Replace Electron-focused docs with Tauri migration notes and TypeScript/Rust details. Update local audio path to public/audio and clarify MP3 metadata handling and recommended tag editors. Add OS-specific prerequisites (Node 18+, Rust, MSVC/toolchain, Xcode CLI, Linux WebKit/GTK deps). Update Spotify setup (add localhost and custom cupid:// callbacks, .env example) and Apple Music setup (move .p8 to src-tauri, provide APPLE_TEAM_ID/APPLE_KEY_ID env vars, note private-key bundling). Document yt-dlp auto-download/update behavior and fallback to system PATH. Change packaging command to npm run build, update build output/installer paths and install instructions per platform, add scripts table, and refresh the tech stack to list Tauri 2, React 18, TypeScript, Rust, and other updated deps.
Add core:window:allow-close to default capabilities. In window_resize, convert dx/dy from logical (CSS) to physical pixels by multiplying by the window scale factor and rounding to fix resize behavior on HiDPI displays. In useAudioPlayer, add an error listener to stop playback on errors and update togglePlay to set isPlaying only after audio.play() resolves (and false on rejection) to avoid incorrect playing state.
Extract core backend responsibilities into three new modules: src-tauri/src/apple.rs (Apple Music JWT caching/generation), src-tauri/src/ytdlp.rs (yt-dlp resolution, download/update, and stream URL caching), and src-tauri/src/window.rs (window resizing/maximizing and theme icon handling). Update src-tauri/src/lib.rs to import these modules, wire their state constructors, and adjust the startup background task to use the ytdlp module's updater and cached path setter. This refactor improves modularity, isolates platform/update logic, and keeps the main run() glue code smaller and clearer.
@cupidbity

cupidbity commented May 15, 2026

Copy link
Copy Markdown
Owner

hey, tried testing this out and ran into a few things:

spotify redirect uri the pr switches to http://localhost:5173/callback but spotify doesn't actually allow localhost, it has to be http://127.0.0.1:5173/callback. here's the docs on it: https://developer.spotify.com/documentation/web-api/concepts/redirect_uri

window dragging the window isn't draggable right now. in the electron version this is done with -webkit-app-region: drag on the frame, needs something equivalent for tauri

window sizing there's extra whitespace around the pixel art, the visible frame doesn't match the actual window bounds. the electron version uses frame: false, transparent: true, backgroundColor: '#00000000', and hasShadow: false to make the window match the art exactly (lines 97-104 in electron/main.cjs)

local playback local mp3 playback also seem to be working, buttons are not working as expected

@cupidbity
cupidbity marked this pull request as ready for review May 15, 2026 22:14
@cupidbity
cupidbity marked this pull request as draft May 15, 2026 22:15

@cupidbity cupidbity left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tested this out, left some notes on specific lines

Comment thread src/spotify/auth.ts Outdated
Comment thread src-tauri/tauri.conf.json
Comment thread src-tauri/tauri.conf.json Outdated
"identifier": "com.cupidbity.cupid-player",
"build": {
"frontendDist": "../dist",
"devUrl": "http://localhost:5173",

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is fine for the dev server but the spotify callback in auth.ts also uses localhost which spotify blocks, just making sure the callback uri specifically uses 127.0.0.1

Advik-B added 2 commits May 16, 2026 13:00
Add backgroundColor "#00000000" to src-tauri/tauri.conf.json window settings to ensure the window is fully transparent (addresses default opaque background on some platforms).
@Advik-B

Advik-B commented May 16, 2026

Copy link
Copy Markdown
Author

@Advik-B Will test in soon. and let you know

@Advik-B
Advik-B marked this pull request as ready for review May 16, 2026 07:53
@Advik-B
Advik-B marked this pull request as draft May 16, 2026 07:53
Claude and others added 2 commits May 17, 2026 13:32
… URI

- next/prev now always start playback, matching useSpotifyPlayer behavior
  and standard music player UX (navigating tracks always resumes play)
- Bind Vite dev server to 127.0.0.1 to match Spotify redirect URI
  (Spotify disallows localhost but accepts 127.0.0.1)
- Update Tauri devUrl to 127.0.0.1:5173 for consistency

Also verified with 5 real tracks downloaded via yt-dlp from SoundCloud:
Lovers Rock, Come Inside Of My Heart, Pluto Projector, Lovesick, Apocalypse
Fix audio playback state and dev server configuration
@Advik-B

Advik-B commented May 17, 2026

Copy link
Copy Markdown
Author

Ran claude code to figure out the playback issue, please check

@Advik-B
Advik-B requested a review from cupidbity May 17, 2026 13:50
@cupidbity

Copy link
Copy Markdown
Owner

tested again, couple things still happening:

  • after logging into spotify the browser doesnt redirect back to the desktop app, the flow just dead-ends in the browser
  • theres still a visible background around the window that doesnt fit the frame of the app, the transparency isnt working on mac. looks like the tauri config sets transparent: true but macOSPrivateApi isnt enabled in tauri.conf.json, which mac needs for actual transparency

@Advik-B

Advik-B commented May 17, 2026

Copy link
Copy Markdown
Author

Since I don't have MacOS, could you please supply a screenshot?

@cupidbity

Copy link
Copy Markdown
Owner
Screenshot 2026-05-18 at 3 08 07 PM window is also not draggable

@Advik-B

Advik-B commented May 20, 2026

Copy link
Copy Markdown
Author

Screenshot 2026-05-18 at 3 08 07 PM window is also not draggable

Woah... okay...

@Advik-B

Advik-B commented May 20, 2026

Copy link
Copy Markdown
Author

@cupidbity I am genuinely clueless rn I do NOT have a mac🥲

@cupidbity

Copy link
Copy Markdown
Owner

is it working as expected on windows? i can try to fix mac if windows is where it needs to be

@Advik-B

Advik-B commented May 22, 2026

Copy link
Copy Markdown
Author

Yepp, it is on windows.. I even ran it side by side with your original source code

@cupidbity
cupidbity force-pushed the main branch 3 times, most recently from b03cc89 to 08dbece Compare June 7, 2026 22:32
@Advik-B
Advik-B marked this pull request as ready for review June 17, 2026 14:19
@Advik-B
Advik-B marked this pull request as draft June 17, 2026 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants