I found a better use for a 15-year-old iPad 2 than letting it sit in a drawer.
I turned it into a Spotify now-playing display and remote control, using nothing more than its stock Safari browser and a web app.
And then I got a little carried away.
It now also has a Winamp 2.x-style interface, an equalizer, a playlist window and a Milkdrop-style visualizer.
The whole project is open source:
GitHub: turbolego/iPad2Spotify
The original idea
The iPad 2 was released in 2011.
Mine is running iOS 9.3.6.
It obviously isn't going to run modern Spotify apps. The App Store isn't going to save me here, and I didn't want to jailbreak it just to turn it into a dedicated music display.
But it still has a browser.
So I started wondering:
Could I use the iPad's old Safari browser as a dedicated Spotify display?
The answer turned out to be yes.
The iPad doesn't actually play the Spotify audio. Instead, Spotify plays on another device, while the iPad acts as a remote control and display.
That turned out to be a much better fit for the hardware.
The result
The iPad can show:
- album artwork
- song title
- artist and album
- playback state
- elapsed and total time
- play/pause
- previous/next track
- a playback timeline
- Spotify artist search
- Spotify playlist search
It also has a minimalist display mode that basically turns the iPad into a dedicated album-art display.
The page polls Spotify adaptively rather than hammering the API constantly: roughly every 60 seconds when nothing is playing, around every 30 seconds during playback, with an additional check near the end of a track. When the page is hidden, polling stops altogether.
The constraint: no modern JavaScript
This was probably the most interesting part of the project.
The iPad 2's Safari is old.
Really old.
So the frontend intentionally avoids modern browser features such as:
fetch- ES modules
- promises
-
async/await -
letandconst - service workers
- modern build tooling
Instead, the frontend uses ES5 JavaScript and XMLHttpRequest.
In other words, I had to write a modern web application while pretending it was still 2011.
That is a surprisingly fun constraint.
But Spotify authentication was the real problem
There was another problem.
The iPad's Home Screen web apps run in a standalone fullscreen mode, but interactive Spotify OAuth doesn't reliably stay inside that old standalone browser context.
So I couldn't simply put a "Log in with Spotify" button on the iPad and call it a day.
Instead, I built a pairing flow.
It works like this
- Open the app in normal Safari on a phone or computer.
- Log in to Spotify.
- Spotify authorization produces a short-lived pairing code.
- Open the app on the iPad.
- Add it to the Home Screen.
- Enter the pairing code.
- The fullscreen iPad app receives its own authenticated session.
The pairing code expires after ten minutes and is deleted after it is claimed.
This means I can do the complicated OAuth dance somewhere modern, then hand the resulting session to the old iPad.
The backend is tiny
The iPad doesn't talk directly to Spotify with a client secret.
The architecture is essentially:
iPad 2 Safari
│
▼
Vercel Functions
│
├── Spotify OAuth
├── Spotify Web API
└── encrypted session cookie
│
▼
Spotify
Vercel holds the Spotify Client Secret and handles token refreshes.
The iPad simply asks the backend for the current playback state.
Redis is only used for state that actually needs to be shared between requests or browsers, such as the short-lived pairing code, badge records and rate limiting. Playback polling itself doesn't use Redis.
That was an important optimization because I didn't want an always-on iPad constantly burning through a Redis free tier.
Winamp 2.9-ish on an iPad 2
The Winamp interface is based on the classic Winamp 2.x look.
It has:
- the main player window
- scrolling track title
- elapsed/remaining time
- playback controls
- previous/play/pause/next
- position bar
- equalizer
- playlist window
- visualizer
- Milkdrop-style window
- draggable windows
- docked window layout
- saved window positions
- custom background
The UI uses the original Winamp 2.91 base-skin bitmaps, with the sprite coordinates following the Webamp skin mapping. The project converts the original bitmap assets into the PNG sheets used by the old-browser-compatible frontend.
And the frontend is still plain ES5 JavaScript.
No Webamp bundle.
No modern framework.
No build step required for Winamp Mode.
Demo on YouTube: WinAmp 2.9 on 15 year old iPad 2 (sort of)
But there is one big catch
This isn't actually Winamp playing Spotify audio.
The Spotify Web API gives me playback state and playback commands.
It does not give the web page the Spotify audio stream.
So the iPad cannot listen to the audio and perform a real audio analysis.
That means the visualizer isn't genuinely audio-reactive.
Instead, I generate a deterministic pseudo-spectrum based on information such as the track ID, playback position and tempo-like patterns.
The same moment of the same song therefore produces the same visualization.
It still looks like a visualizer.
It just isn't analyzing the actual Spotify audio.
I think that's an important distinction.
And the equalizer doesn't equalize anything
The Winamp equalizer has ten bands and a preamp, including the classic Winamp presets.
But again, the iPad isn't receiving the audio.
So the equalizer can't change the Spotify sound.
Instead, it affects the visualizer.
In other words:
The equalizer equalizes the pixels, not the music.
Which is probably the most technically honest way of describing it.
Milkdrop on a 15-year-old iPad
The Milkdrop window is powered by OldMilk.
It uses WebGL when available and falls back to a 2D canvas.
While playing it renders at roughly 30 fps, and it stops rendering when paused or hidden.
Getting something resembling a classic Winamp visualization running inside Safari on an iPad 2 in 2026 is honestly more satisfying than it has any right to be.
[youtube:aOBSWgWmSMo]
It can also put your music on your GitHub profile
Then I added another completely unrelated feature.
The app can generate a GitHub README badge showing the current or most recently played Spotify track.
It looks roughly like this:
[](https://your-project.vercel.app/)
The badge is generated dynamically as an SVG.
When GitHub requests it, the backend asks Spotify for the current track. If nothing is playing, it falls back to the most recently played track.
The album artwork is downloaded and embedded directly into the SVG, so GitHub doesn't have to load another remote image from inside the badge.
And the response is cached for five minutes, so constantly viewing a GitHub profile doesn't result in a Spotify API request every time.
The whole thing runs as a web app
That's probably my favourite part of this project.
There is no iPad app.
There is no App Store package.
There is no jailbreak.
There is no native code running on the iPad.
It's basically:
┌─────────────────┐
│ Spotify │
└────────┬────────┘
│
Spotify Web API
│
┌────────▼────────┐
│ Vercel Functions│
│ │
│ OAuth │
│ Sessions │
│ Playback API │
│ GitHub badge │
└────────┬────────┘
│
HTTP / JSON
│
┌────────▼────────┐
│ iPad 2 │
│ │
│ Safari / iOS 9 │
│ ES5 JavaScript │
└─────────────────┘
The iPad is basically just a very old web client.
And that's enough.
Why not just buy a cheap modern tablet?
Because that isn't the point.
I could obviously buy a modern tablet and install Spotify.
But there is something satisfying about taking hardware that most people would consider obsolete and finding a job it is still perfectly capable of doing.
The iPad 2 has a perfectly usable screen.
It has Wi-Fi.
It has a browser.
It can render HTML, CSS and JavaScript.
That's enough to turn it into a dedicated little music dashboard.
What I learned
The project started as:
"Can I make an old iPad show what Spotify is playing?"
It turned into a collection of interesting constraints:
- How do you authenticate Spotify from an iOS 9 Home Screen web app?
- How do you transfer an authenticated session between browsers?
- How do you write a modern application using ES5?
- How much of a 2010-era UI can you reproduce with web technologies?
- How do you make a Spotify visualizer when you can't access the audio?
- How much can you do with a browser on a 15-year-old tablet?
And perhaps most importantly:
Old hardware doesn't necessarily need modern software to be useful.
Sometimes it just needs a sufficiently weird project.
Try it
The project is open source and available on GitHub:
The repository contains the frontend, Vercel Functions, Winamp Mode, visualizer, badge generation and deployment instructions.
If you have an old iPad lying around, I'm curious:
What would you turn a 15-year-old iPad into?
And if you try this project, I'd especially like to see what you do with the Winamp mode. 😄
Note: this is an independent hobby project and is not affiliated with or endorsed by Spotify or Winamp. Spotify playback control also generally requires a Spotify Premium account and an active controllable device.


Top comments (0)