Two weeks ago I put Spotify on a $25 Win98 desk player. That one was an ESP32 with no PSRAM showing now-playing on a 4" screen.
This one is the browser version, and it got out of hand.
winampify.exe started as "Spotify, but it looks like Windows 98." Now it's a whole retro desktop: Windows 98, XP and 7 skins, a Windows Media Player-style player, sticky notes, a MilkDrop visualizer, and a CD mascot named Disky who reads your notes and nags you about the dentist.
The big change is the music source. It doesn't have to be Spotify anymore. Bring your own library with Navidrome.
Repo: github.com/UribeJr/winampify-exe (MIT)
What it is
- A retro desktop. Draggable windows, a taskbar with a working clock, Start menu, right-click menus, Run… and Shut Down… dialogs.
- A WMP-style player. Library, search, queue/playlist pane, shuffle/repeat, media keys.
- Two music sources. A logon-style picker lets you choose Navidrome (through the OpenSubsonic API) or Spotify.
- Three skins. Windows 98 Classic, an XP-style look (Blue, Olive Green, Silver) and a Windows 7-style look with optional see-through Aero glass. Each skin has its own Start menu, player styling, logon screen and boot screen.
- Display Properties. Original wallpapers or your own picture, centered/tiled/stretched.
- Visualizations. Classic bars and waves, plus the full MilkDrop preset library via butterchurn.
- A 10-band graphic EQ (31 Hz–16 kHz, presets included). Navidrome only, more on that below.
- A phone layout. Full-screen player, view tabs, drill-down library, big touch targets.
Stack: React 18 + Vite on the front, a small Express server as the API/proxy, 98.css / XP.css / 7.css for the widgets (the XP and 7 stylesheets only load when you pick that skin), and butterchurn for MilkDrop. Tests run on Node's built-in test runner.
Meet Disky
Every retro OS needs an assistant who's mostly helpful.
Disky is an original CD mascot (not Clippy, legally distinct, emotionally identical). He gives you a first-visit tour, drops one-time tips, naps when you go idle, and hides a few easter eggs.
The part I actually like: he reads your sticky notes, locally. Write "dentist 3pm" on a note and he'll ask if you want a reminder. Finish every [ ] on a checklist and he cheers. He also docks himself into the tray when a window covers his corner, because he has manners.
Fair warning: reminders only fire while Winampify is open. He's a CD, not a calendar server.
The DRM tradeoff (why the EQ is Navidrome-only)
This is the part that changed the whole project.
Spotify's Web Playback SDK plays DRM-protected audio. The browser won't let you touch it. No Web Audio graph, no analyser, no EQ. So with Spotify:
- the equalizer is off (the panel just tells you Spotify's audio is protected), and
- the visualizer runs on a simulated signal, not the actual song.
With Navidrome, it's your own files streamed through the proxy as plain HTML5 audio. The EQ really shapes the sound, and on desktop the visualizer reacts to the actual music.
I could have faked an EQ for Spotify. I didn't. A slider that does nothing is worse than no slider.
The 5-user wall
The Spotify version is live at winampify.vercel.app, but it's invite-only.
That's not me being exclusive. Spotify apps in development mode can only serve people the owner manually adds (up to 5), and the owner needs Premium. Spotify's February 2026 dev-mode rules also tightened things: you can only list tracks from playlists you own or collaborate on, search caps at 10 results per page, and some catalog endpoints are gone.
So the hosted copy is basically for me and a few friends. Anyone else who signs in gets told it's invite-only.
That's why Navidrome became the real path. You self-host your library, Winampify talks to it through an allowlisted Express proxy, and Spotify's rules stop mattering. Your Navidrome password never reaches the browser. The server signs each request with Subsonic token auth, and streams and cover art are proxied, so no tokens end up in <audio> or <img> URLs.
The deploy saga (the funny part)
The first version (December 2025) deployed to Render. Real commit messages from that day:
fixed dist pathfixed dist locationfixed dist path again for the 100th timeWhats wrongfinally fixed
About nine commits of me fighting one folder. At one point server.js was checking six candidate dist paths, including a hardcoded /opt/render/project/dist, and dumping directory listings to the logs when none of them existed.
Same day: Spotify kept returning 403s. The fix was one missing OAuth scope, user-library-modify. A wall of 403s, fixed by one string.
The current version runs on Vercel with an app/server split (api/index.js wraps the same Express app), and server.js is about ten lines. Growth.
The last two weeks
The December version sat untouched for months. Then it all landed at once:
-
Sep 28: ported the Win98 shell and mobile layout from my
98-portfolioproject - Oct 2: Navidrome (OpenSubsonic) provider, the music-service picker, Display Properties, sticky notes with a working Recycle Bin, and Disky
- Oct 5: real-audio visualizer upgrade, the 10-band EQ, the playlist pane, the XP skin (6 stages: shell, color schemes, Start menu, WMP 9-style player, welcome/boot screens, phones), and the shared Spotify build on Vercel
- Oct 8–9: Windows 7 skin, also in 6 stages, starting with making skins table-driven so a third one didn't mean copy-pasting the second
Rough edges (honest list)
- With Spotify, fullscreen visualizer has gone black on me.
- Spotify playback has sometimes stopped on its own.
- Phones can't run Spotify's Web Playback SDK, so on mobile Winampify acts as a Spotify Connect remote for your Spotify app.
- iOS doesn't let web pages set volume, so the slider is disabled there. Use the hardware buttons.
- The self-hosted server has no login of its own. Don't expose it to the internet as-is.
The last three are spelled out in the README too.
Try it / self-host it
You need Node 18+ and either a Navidrome server or a Spotify developer app (Premium to play).
git clone https://github.com/UribeJr/winampify-exe.git
cd winampify-exe
npm install
cp .env.example .env # add your Navidrome and/or Spotify settings
npm run dev
Open http://127.0.0.1:3000 (not localhost, because Spotify's sign-in only redirects back to the loopback IP). Pick your service after the boot screen.
Want a Spotify copy for friends? The README has a Vercel section. Just never put NAVIDROME_* variables on a public host.
Fan project, not affiliated with Microsoft, Spotify, Winamp or Navidrome.
Your turn
Which skin should come next: Windows 2000, ME (lol), or a real Winamp 2 classic skin? And if you already self-host music, what are you running, Navidrome or something else?







Top comments (1)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.