Skip to contentRyan Katayi
    All work

    Droplyst / Independent product / iOS

    A set, saved in order.

    An app that recognizes the music around you and turns a listening session into a playlist.

    RoleIndependent developer
    StatusOn the App Store

    Built with

    Application
    • TypeScript
    • React Native
    • Expo
    • Expo Router
    Native audio
    • ShazamKit
    • react-native-apple-shazamkit
    • Expo Audio
    Data & sessions
    • Supabase
    • PostgreSQL
    • Supabase Auth
    Music integration
    • Spotify Web API
    • OAuth 2.0
    • Expo AuthSession
    Device storage
    • Expo SecureStore
    Build & release
    • EAS Build
    • EAS Submit
    • TypeScript compiler

    Native audio lifecycle · Track identity · Cross-catalog export

    Inside the engineering
    Droplyst App Store screenshot showing the new session form
    Inside Droplyst

    Original App Store screenshots.

    My contribution

    I built and shipped the app, from song recognition and session storage to playlist export and the iOS release.

    Under the surface

    The engineering.

    A recognition result is only the beginning. The app has to decide whether it is new, preserve its place in a session, survive a pause, and find the corresponding recording in another music catalog.

    1. Listen

      Native ShazamKit events, with a timed fallback.

    2. Resolve identity

      Check recording IDs and normalized artist/title.

    3. Keep the sequence

      Append new matches to the session timeline.

    4. Export

      Resolve Spotify tracks and report unmatched entries.

    Decision / 01

    One song can arrive under several identities.

    Consecutive recognition windows can return the same recording. A resumed session also needs to remember what it already captured.

    How it works

    The capture loop checks a shared set of keys: Shazam ID, ISRC, and a lowercased title/artist pair. Any matching key suppresses the duplicate; a new result registers all available keys. Continuing a saved session rebuilds that set from its tracks, including any Spotify IDs already resolved.

    The tradeoff

    The text fallback catches matches with missing IDs, but identical artist/title metadata can collapse different versions. Deduplication applies across the session, so an intentional replay of the same song is also suppressed. This favors a clean playlist over a complete performance log.

    Decision / 02

    Pause has to stop the work behind the screen.

    Native recognition can finish after a user pauses or leaves capture. Without lifecycle handling, a late callback could append a track to a stopped session.

    How it works

    The native adapter exposes continuous match/error events when available. Stopping removes subscriptions and guards callbacks. The fallback races recognition against cancellation and a 15-second timeout, then releases the native listener in a finally block. Returning to the foreground restarts capture for an active, unpaused session.

    The tradeoff

    This adds native lifecycle code beyond the React interface. Continuous capture and the timed fallback have separate paths to maintain, and device interruptions still need testing on real hardware.

    Decision / 03

    Recognized does not mean available on Spotify.

    Shazam and Spotify use different catalog identities. A successful recognition cannot be treated as a successful playlist addition.

    How it works

    Spotify resolution tries the recording’s ISRC first, then searches by title and artist. Results are resolved in session order and sent in batches of up to 100 URIs. Export returns a result for each track plus added and not-found counts. Concurrent token refresh requests share one in-flight promise.

    The tradeoff

    The text fallback accepts the first search result, so it can choose a different version. Sequential resolution keeps ordering straightforward but takes longer for large sessions. Export status is explicit rather than assuming every detected track transferred.

    Edge cases

    What happens when…

    The same Shazam ID arrives again
    Suppress the duplicate even if its displayed metadata changes.
    Capture resumes on an existing session
    Seed the identity set from saved tracks before listening again.
    A track has no Spotify match
    Keep its session entry and report it as not found in the export result.
    Recognition → sessionImplementation walkthrough · sample tracks

    Select a recognition

    Saved session

    01Track A

    1 saved · First matches, in order.

    Existing ISRC → suppress duplicate

    02

    Recognized twice. Saved once.

    Any known identity is enough to suppress a duplicate. Even if the display title changes, a matching Shazam ID or ISRC keeps the result from being appended again.

    Next

    Fraq

    Property operations software spanning assignment, housekeeping, and maintenance.

    Client work / Web application