Three Surfaces, One Client
Fastpotify's central design problem is not how to draw a Spotify-like window. It is how to decide which Spotify-facing surface is allowed to answer a particular question. This chapter traces the Web API, the librespot session, and librespot playback as three distinct sources of capability, then uses local and remote playback to show why the distinction matters. By the end, a new feature request can be tested against a practical question: which surface can provide it, who owns the resulting state, and what boundary may stop it?
What each surface can actually do
The Web API is the surface most visible to a library application. Fastpotify uses it for account information, playlists, saved tracks and albums, followed artists, catalogue pages, search, recommendations, playback commands, device lists, and queue access. It supplies the structured information needed to render a Home page or a playlist and the commands needed to ask Spotify to pause, seek, transfer playback, or add a song to a queue.
That breadth can create a misleading mental model. An API that can list a device and issue playback commands is not necessarily the API that supplies every fact about that device or every kind of playback. The Web API works through registered application identities and Spotify's rules for those applications. It can be rate-limited, and some application modes have reduced access to Spotify-owned playlists, related artists, recommendations, or other catalogue features. The surface is broad, but it is not a complete copy of Spotify's internal client protocol.
The consequence is visible in ordinary navigation. Fastpotify can load a playlist page, search for an artist, and show a device picker through Web API responses, but those responses do not imply that every requested page is equally available or equally fresh. A playlist owned by the signed-in user, a collaborative playlist, and a playlist owned by someone else may require different access decisions. A catalogue search and a playlist search may also have different coverage when Spotify places limits on development applications. The interface can present one search box, but the underlying operation still has to respect the surface's uneven rules.
This is why an API capability should be described as a contract rather than a promise. The contract says which request can be made, under which account and application conditions, and what kind of answer can be expected. It does not guarantee that the service is reachable, that a rate limit will not intervene, or that a catalogue object omitted by the service can be recovered elsewhere. Fastpotify's later routing and error handling depend on keeping this distinction visible.
The librespot session fills a different gap. It connects to Spotify through the protocol used for playback and can expose context that the Web API does not fully provide. Fastpotify uses it to read the account's playlist tree, including folders and order, and to learn which invitation-shared playlists can accept songs. It can ask the session for lyrics when Spotify has them, resolve display names for users attached to playlist songs, identify a precise EP type when the Web API groups a release as a single, and obtain Spotify's context for song radio or autoplay.
Those capabilities are not simply extra endpoints on the same service. They arrive through a session whose lifetime and connection are different from a Web API request. A playlist folder may be available through the streaming session even though the Web API is responsible for the playlist rows. A contributor name may be resolved through the session while the track itself came from a cached Web API response. The client therefore has to combine facts without confusing their origins. It can present one page to the reader, but it cannot assume that one authority produced the page.
The playlist tree is a useful example of the distinction. Spotify's streaming session can supply the account's folders and their order, and it can reveal which invited playlists are editable in ways the Web API's ordinary collaborative flag does not fully express. Fastpotify can use that information to arrange its Library and decide where a dragged song may go. But reading the tree is not the same as editing folders. The client can preserve the structure it has learned while leaving unsupported folder mutations out of its promises.
The same pattern appears in smaller details. The Web API may group a release as a single, while the streaming session can confirm that Spotify internally treats it as an EP. Spotify's own lyrics may be available through the session even when an external lyrics fallback is needed for other tracks. These are not reasons to declare one source superior. They are reasons to keep each fact attached to the path that can actually support it.
Librespot playback is the third surface. When local playback is enabled, Fastpotify creates an engine containing a Spotify session, a player, a mixer, and Spotify Connect state. That engine announces this computer as a Connect device and owns the local audio path. It can apply the selected bitrate within the documented range, play gaplessly, normalize volume, cache audio, seek, change volume, shuffle, repeat, and follow autoplay within the upstream library's limits.
The practical difference is ownership. The Web API can ask a selected device to play or pause. The local engine can act on its own player and report its state directly to Fastpotify. The Web API can return a snapshot of a phone or speaker, but that snapshot may arrive after the user has acted and may describe a moment that is already past. Fastpotify can make both targets look like destinations in one device picker, but the feedback loop is not the same. Local playback is an authority inside the process; remote playback is usually an authority elsewhere that the process observes and commands.
The local engine also has continuity responsibilities that a stateless request helper does not. Fastpotify derives a stable Connect device identity from the configured device name, so Spotify can continue to recognize the computer across restarts. The engine holds the current local state and sends changes back to the interface. If the session ends, the application can retain the interrupted track and position and attempt to bring up a replacement session. None of this makes the network reliable, but it gives the local path an owner that can remember what it was doing and decide how to recover.
This division explains why Fastpotify uses all three surfaces. The Web API is suited to account-visible library and catalogue operations. The session is suited to playback context and protocol-level information. Playback is suited to the continuous, stateful work of decoding and delivering audio. Replacing any one with another would not simplify the system. It would remove a capability while leaving the underlying question unanswered.
Imagine opening an album and pressing play. The catalogue and album rows can arrive from the Web API. The decision about whether the current item is an episode or a track may be represented in the data model shared by the client. If the target is this computer, a local load enters the Connect engine and the audio path reports progress back to Fastpotify. If the target is a speaker, the same user action becomes a Web API command addressed to that device. If the user then asks for the playlist order or autoplay context, the session may supply information that neither playback output nor the album endpoint owns. One gesture crosses several interfaces, but each crossing has a specific reason.
The relationships can be represented as a responsibility map rather than a file map:
The map also clarifies why a feature description should name its boundary. “Playback” is too broad to explain what happens. Local playback travels through the engine. Remote playback travels through Web API commands and later state. Playlist folders come from the session, while playlist editing uses Web API operations. Fastpotify's interface unifies these experiences, but the architecture stays reliable only if the unification is presentational rather than fictional.
A boundary is not only a place where a request is sent. It is also a place where a decision is made about which answer to trust. The local engine's track event can settle what this computer is actually playing. A Web API device snapshot may be the right evidence for a phone, but it can be stale by the time it is displayed. A folder order read from the session can organize the sidebar without granting permission to modify Spotify's folder structure. Fastpotify's visible simplicity comes from translating these different kinds of evidence into one view while retaining their different authority.
This is also why an apparently small feature can be architecturally expensive. “Show the exact release type” needs a second source and a way to associate its answer with the right session. “Keep the last song playing after the window closes” needs state that outlives the window and a desktop route back to the running process. “Control a speaker” needs remote polling and a way to avoid treating delayed state as a local fact. The surface map reveals those hidden obligations before implementation details obscure them.
Local playback is not remote control
Consider choosing Fastpotify in the device picker. The local case begins with a separately authorized streaming relationship. Once the engine connects, the computer appears as a Spotify Connect device and can receive playback from the app or from another Spotify client. Fastpotify's own controls can act on the local engine, and the engine reports changes such as the current track, position, volume, shuffle, and repeat state back to the interface.
This local authority is what makes features such as gapless playback, an on-disk audio cache, and local volume control meaningful. The client has an audio path whose output it can shape, not just a command endpoint that tells another device what to do. It can apply a volume preview locally without turning every small slider movement into a remote round trip, and it can keep the player active while the main window is hidden. The benefit is not that the local engine escapes Spotify's rules. It is that Fastpotify has a place where continuous audio state can be held and updated.
A remote case starts differently. The phone, speaker, or another computer already owns its playback session. Fastpotify uses the Web API to list devices, transfer playback, and send commands such as play, pause, skip, seek, shuffle, repeat, or volume changes. It may poll the remote state to learn what actually happened. The interface can respond to a command immediately, but it must remain prepared for the remote snapshot to disagree temporarily. That disagreement is not necessarily a bug. It is the normal consequence of commanding a separate device through a network boundary.
The remote device also determines what Fastpotify can observe. A device may appear in a list without providing the same local event stream that the engine has. A command may succeed while the next state read still describes the previous song. A device may refuse controls even though its name remains visible. Fastpotify can make the interaction feel unified by holding a short-lived user intent and polling again, but it cannot turn remote observation into direct ownership. The interface must eventually let fresh remote evidence settle the display.
The distinction affects failure messages as well. If local playback has not been set up, browsing and searching can still work because they use the Web API. If the local engine drops, a remote device may still be controllable. If a remote speaker stops answering, the local engine may remain healthy. Treating these cases as one global signed-in or disconnected state would make recovery less precise. Fastpotify's division lets it preserve useful capabilities while one path is unavailable.
It also explains why local playback has a stronger responsibility for continuity. The engine keeps an audio cache and tracks what was playing when its session ends. Fastpotify can reconnect and attempt to resume the interrupted song at its previous position. That behavior belongs to a local authority that can retain an interruption record and re-enter its own playback path. A remote device is not something the process can restart in the same way. Fastpotify can ask it to resume, but it cannot claim ownership of its audio engine.
The account plan is part of this architecture, not merely a commercial notice. Spotify Premium is required for playback through Fastpotify, including playback on another device because the relevant playback commands and librespot behavior depend on that account capability. A Free account can browse and search, but the client must not start a local engine that the underlying playback system cannot support. The result is a deliberately partial application: the library relationship may be usable even when the audio relationship is not.
The same boundary sets the ceiling for local audio. Fastpotify documents local playback up to 320 kbps and does not attempt to bypass Spotify's DRM to obtain lossless streams. It also does not add offline listening or downloads, local files, audiobooks, video podcasts, or social features. Some familiar Spotify experiences, including Smart Shuffle, Jam, and Blend, are generated for official clients rather than exposed through the surfaces Fastpotify uses. Playlist folders can be read, but the available session capability does not give Fastpotify a supported way to edit them.
A useful distinction is between absence and refusal. Lossless playback is not simply a switch that the interface has forgotten to expose when the upstream streaming path does not receive lawful lossless streams. Offline downloads are not just a cache-size question when the service's protection model does not permit the client to keep usable audio. Social features are not naturally recoverable from library endpoints when Spotify does not publish the necessary state. In each case, a more ambitious interface would not create the missing authority.
These limits have different causes, and that difference matters. A missing feature may be outside the current project scope, unavailable in the Web API, absent from librespot, or deliberately excluded because delivering it would require bypassing a technical protection. The conclusion should not be “the client has not tried hard enough.” It should be “the responsible surface does not support this operation under the project's stated rules.” Fastpotify's documentation treats substituting another audio source, scraping a private service, or circumventing DRM as outside the product boundary.
This provides a disciplined way to evaluate a new request. First, identify the user-visible capability. Then ask whether it concerns library data, playback context, local audio, remote control, or desktop integration. Next, identify the surface that would own the operation and the state that would confirm success. Finally, check the inherited constraint: account plan, application quota, API coverage, upstream playback support, or product policy. A request to reorder playlist rows and a request to add lossless playback may both sound like “Spotify features,” but they lead to entirely different evidence and limits.
Fastpotify's strength is therefore not that it erases the differences among Spotify's systems. It gives those differences a coherent place in one desktop experience. The Web API, the librespot session, and the playback engine cooperate because each is asked to do work it can actually own. Their boundaries also explain the next problem. Separate capabilities require separate identities, and a client that keeps them apart must authorize and store them without letting one account or one stale session take over another.