I'm a singer-songwriter who codes. Two months ago I launched Fretlist — a web app for musicians to organize their songs, chords, and setlists. Last week I shipped the biggest update yet: it works offline now.
This is the story of why I built it, how I approached it, and what I learned.
The message that started it
A few weeks after launch, a user named Geoff emailed me. He'd been importing his songs, was clearly engaged, but said something that stuck:
"The main reason that I haven't given it a good run is that I've no WiFi or signal in our rehearsal room."
There it was. Fretlist is built for the stage and the rehearsal room — the two places where WiFi is least reliable. Without offline support, I was building a tool that breaks exactly where it matters most.
That email went to the top of my priority list.
Why I went with a PWA
Fretlist is a Next.js app. I had a few options for offline: build native apps, use a framework like React Native, or go the PWA route.
I chose PWA for one reason: I never wanted Fretlist to be locked to one platform. Not an iPhone app, not "just" Android. One codebase, every device, every OS. A musician should be able to edit a song on their MacBook and pull it up on their phone at the gig — regardless of what phone they use.
I followed the official Next.js PWA guide. No third-party PWA packages. Custom service worker, IndexedDB for local data, and the standard Web App Manifest. The fewer dependencies, the fewer things that break.
The architecture
The offline setup has three layers:
Layer 1: Service worker. Caches the app shell — HTML, CSS, JS, fonts. When you open Fretlist without a connection, the app loads instantly. No blank screen, no browser error.
Layer 2: IndexedDB. This is where the user's actual data lives locally. Every song, every setlist, every piece of metadata. On every app load, Fretlist syncs from Supabase to IndexedDB. When the connection drops, the app reads from the local database instead.
Layer 3: Live sync. When you're online, changes sync in real-time across all your devices via Supabase Realtime. Edit a song on your laptop — it updates on your phone instantly. Then when you go offline, the latest version is already there.
I went with full sync on load — every song downloads to IndexedDB when you open the app. For my users, this is fine. A musician with 50 songs is storing maybe a few hundred kilobytes of text. It's not like syncing a photo library.
The offline mode is read-only for now. You can browse songs, view chords, use play mode, transpose — everything you need on stage. Editing requires a connection. This was a deliberate choice: offline editing means conflict resolution, and that's a rabbit hole I didn't need to go down at this stage.
The iOS splash screen rabbit hole
Once you're building a PWA, you want it to feel native. On Android, the system generates a splash screen from your manifest automatically. On iOS? You need to provide a separate static image for every possible screen size. We're talking 25+ images.
I used a generator tool to create all the sizes, added the meta tags, and it works. But it's a reminder that Apple still treats PWAs as second-class citizens. Every browser on iOS uses WebKit under the hood, so PWA capabilities are entirely at Apple's discretion.
Still — when you tap the Fretlist icon on your home screen and it opens with a branded splash screen, no browser chrome, instant load? That's a moment. It feels like a real app.
What I removed to ship this
Here's something I don't see enough devs talk about: what you delete to move forward.
Fretlist had client-side encryption on all song data stored in Supabase. Chord charts encrypted with PBKDF2, the whole thing. It sounded great on paper. In practice, it was causing problems everywhere — slow fetches, complex data handling, and when it came time to build offline mode, it was a wall.
I asked myself: who am I protecting here? My users store chord charts and lyrics. Not credit cards, not medical records. The encryption was solving a theoretical problem while creating real ones.
So I removed it. Added 2FA to my Supabase dashboard instead. Simpler, more practical, and it unblocked offline mode overnight.
Sometimes the best engineering decision is deleting code.
The real test
The day I shipped offline mode, I messaged Geoff — the user who told me about his rehearsal room. His response will determine if this feature actually works where it matters.
But I've been testing it myself: load the app, toggle airplane mode, browse through my songs, open a setlist, transpose a chord chart. It all works. And switching songs is basically instant now because everything reads from the local database.
The speed improvement alone was worth the effort, even for users with good WiFi.
What I've learned since launch
This is my second month building in public. A few honest observations:
Users don't activate on your timeline. Fretlist is a vitamin, not a painkiller. Musicians have systems that "work" — until they don't. Most people sign up and don't add a single song. Not because the product is bad, but because they don't have a gig this week. Activation is tied to real-world moments, not feature launches.
Talk to your users before building features. Every major decision I've made came from a conversation, not analytics. Geoff told me about offline. Sage told me about sharing with bandmates. A post-punk band told me about setlist randomization. The admin dashboard tells me who's active. The conversations tell me why.
Asking questions beats sharing tips. On Threads, my best-performing content is always a question: "How do you organize your songs?" or "Any singer-songwriters around?" Tips and feature announcements die. Questions start conversations.
Crafting a product is like writing songs. I pour myself into both. The fear of putting it out there is the same. And the truth is the same too: not every song connects with everyone, but the right song finds its people.
The numbers
- 60+ users in Early Access
- 50 founding "Early Bird" members
- 8-9 users showing real activation progress
- 0 paying customers (not charging yet)
- 1 founder, 2 kids, nights and weekends
What's next
I'm designing a Band Plan — shared workspaces where each member sees the same songs with their own player settings. Your guitarist sees capo II in Em. Your uke player sees the same song in Dm. Same setlist, personal views. It's the feature I built in WordPress years ago for my duo, now designed properly.
But first: I need more activated users. The product is ready. The distribution and activation are the bottleneck. So I'm talking to musicians, posting on Threads, and letting the product do its thing.
If you're a musician: fretlist.com
If you're building a side project: I'm happy to chat. The messy middle is real, and it helps to talk about it.
Follow the journey: @dearjohnmusic on Threads
Top comments (0)