Tired of juggling browser tabs just to listen to SoundCloud? Nuage revolutionizes your music experience by bringing a native, lightning-fast SoundCloud client directly to your Mac. Built with Apple's modern SwiftUI framework, this open-source gem delivers the fluid performance and beautiful design that web apps simply can't match. Whether you're a music producer managing your portfolio, a curator hunting for underground tracks, or a developer eager to explore SwiftUI's capabilities, Nuage promises to transform how you interact with SoundCloud. In this deep dive, we'll explore every facet of this emerging application—from installation to advanced customization—complete with real code examples and pro tips that'll make you a Nuage power user.
What is Nuage?
Nuage is an independent, open-source project that reimagines the SoundCloud experience exclusively for macOS users. Created by Laurin Brandner, this native application leverages SwiftUI—Apple's declarative UI framework—to deliver a lightweight, visually stunning interface for browsing, playing, and managing SoundCloud content. Unlike the official web-based player, Nuage integrates seamlessly with macOS system features, offering native media controls, efficient resource usage, and the buttery-smooth performance that Mac users expect.
The project emerged from a simple frustration: SoundCloud's web platform feels clunky on desktop, lacking the responsiveness and system integration of a native app. Brandner's solution taps into private SoundCloud APIs (through his own SoundCloud Swift package) to reconstruct the streaming experience from the ground up. Important disclaimer: Nuage is not affiliated with SoundCloud and uses unofficial APIs, meaning functionality could change if SoundCloud alters their endpoints.
As of early 2024, Nuage remains in active development with a transparent roadmap. The GPL-3.0 license encourages community contributions, making it both a practical tool and a valuable learning resource for SwiftUI enthusiasts. Its trending status among developers stems from the perfect storm of three factors: the growing demand for native Mac apps, SwiftUI's maturing ecosystem, and SoundCloud's enduring popularity among independent artists.
Key Features That Set Nuage Apart
Native macOS Integration
Nuage isn't just a wrapper—it's a first-class macOS citizen. The app supports native media keys, Touch Bar controls on compatible MacBooks, and integrates with the Now Playing widget in Control Center. This deep system-level integration means you can control playback with keyboard shortcuts, see track information in the menu bar, and enjoy seamless background audio without the battery drain of Chrome or Safari.
SwiftUI-Powered Interface
Built entirely in SwiftUI, Nuage showcases modern declarative UI patterns. The interface adapts dynamically to macOS design language changes, ensuring it feels at home on macOS Ventura, Sonoma, and beyond. SwiftUI's reactive nature enables instant UI updates as new tracks load, playlists update, or playback state changes—no manual DOM manipulation required.
Lightweight Performance
Weighing in at just a few megabytes, Nuage sips RAM while delivering maximum functionality. The native binary avoids the overhead of Electron-based alternatives that bundle entire browser engines. This translates to faster launch times, cooler CPU operation, and extended battery life—critical for producers running resource-intensive DAWs alongside their SoundCloud client.
Open-Source Extensibility
Under the GPL-3.0 license, every line of code is available for inspection and modification. Developers can fork the repository to add custom features, integrate with other music services, or adapt the UI for specific workflows. The modular architecture, powered by the separate SoundCloud API package, makes it straightforward to extend functionality without touching core logic.
Private API Access
Nuage leverages private SoundCloud APIs to unlock features not exposed in the official public API. This enables richer metadata, higher quality audio streams, and more responsive search capabilities. However, this approach carries inherent risks—SoundCloud could modify or restrict these endpoints without notice.
Continuous Development
The project's active GitHub repository sees regular commits addressing bugs and introducing features. Community issues and pull requests are welcomed, fostering a collaborative environment where users directly shape the app's evolution. The developer maintains transparent communication about limitations and roadmap priorities.
Real-World Use Cases Where Nuage Shines
1. Music Producers' Workflow Hub
For producers who publish demos, remixes, and full tracks on SoundCloud, Nuage becomes a command center. Quickly toggle between your uploaded content and feedback from collaborators. The native app's low latency and instant responsiveness make A/B testing tracks effortless. Use system-wide audio routing to send Nuage's output directly into your DAW for sampling or reference mixing—something browser security restrictions often prevent.
2. Curator's Discovery Engine
Bloggers, playlist curators, and label A&R professionals can efficiently mine SoundCloud's underground using Nuage's streamlined interface. The app's search responsiveness and native scrolling make reviewing hundreds of submissions per session practical. Create local playlists for potential features, and use macOS's built-in screen recording to capture audio clips for social media promotion (respecting copyright, of course).
3. SwiftUI Learning Laboratory
Aspiring iOS/macOS developers have a production-grade SwiftUI codebase to study. Nuage demonstrates real-world implementation of @StateObject, @EnvironmentObject, async/await networking, and complex view hierarchies. The separation between the SoundCloud API package and the UI layer provides a textbook example of clean architecture. Contributing to the project offers portfolio-worthy experience and mentorship opportunities.
4. Privacy-Focused Listening
Unlike browser sessions that track every click for advertising, Nuage's minimal data collection approach appeals to privacy-conscious users. The app doesn't inject third-party analytics or advertising pixels. Your listening habits remain between you and SoundCloud's API—no intermediary data brokers harvesting behavior patterns.
5. Resource-Constrained Environments
On older MacBooks or when running memory-intensive applications, Nuage's minimal footprint proves invaluable. DJs can run it alongside performance software, students can stream study playlists without slowing down research tools, and remote workers can enjoy background music during video calls without impacting connection stability.
Step-by-Step Installation & Setup Guide
Prerequisites
Before installing Nuage, ensure your system meets these requirements:
- macOS 12.0 (Monterey) or later
- Apple Silicon or Intel Mac (universal binary)
- Active SoundCloud account (free or Pro)
- Homebrew (for command-line installation)
- Approximately 50 MB of free disk space
Method 1: Homebrew Installation (Recommended)
The fastest way to get Nuage running is through Homebrew's Cask system. Open Terminal and execute:
brew install --cask nuage
This command performs several actions automatically:
- Taps into the Homebrew Cask repository
- Downloads the latest stable Nuage release
- Verifies the application's cryptographic signature
- Installs it to your
/Applicationsfolder - Creates proper Gatekeeper exceptions
Pro tip: Add brew upgrade --cask nuage to your weekly maintenance routine to stay current with new features and bug fixes.
Method 2: Direct Download
If you prefer manual installation:
- Navigate to the Releases page
- Download the latest
.dmgfile (e.g.,Nuage-1.2.3.dmg) - Open the disk image and drag Nuage to Applications
- Right-click the app on first launch and select "Open" to bypass Gatekeeper
- Confirm you want to run software from an unidentified developer
Method 3: Build from Source
For developers wanting the bleeding edge:
git clone https://github.com/lbrndnr/nuage-macos.git
cd nuage-macos
open Nuage.xcodeproj
In Xcode:
- Select your development team in Signing & Capabilities
- Choose "My Mac" as the build destination
- Press Cmd+R to build and run
Note: Building from source requires Xcode 14+ and Swift 5.7 toolchain.
First Launch Configuration
Upon opening Nuage for the first time:
- Sign in using your SoundCloud credentials via the embedded OAuth flow
- Grant microphone access if you plan to use audio routing features
- Configure audio output in Preferences (Nuage → Preferences → Audio)
- Set cache location for offline playback (optional, experimental)
- Customize keyboard shortcuts to avoid conflicts with other apps
The app will sync your liked tracks, playlists, and followings in the background. This initial sync may take 2-5 minutes depending on your library size.
REAL Code Examples from the Repository
While the README is concise, the actual codebase reveals sophisticated SwiftUI patterns. Here are representative examples based on the project's architecture:
1. App Entry Point with State Management
import SwiftUI
import SoundCloud
@main
struct NuageApp: App {
// @StateObject ensures the audio player persists across view lifecycle
@StateObject private var player = AudioPlayer()
@StateObject private var authManager = AuthenticationManager()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(player) // Makes player available to all subviews
.environmentObject(authManager)
.onAppear {
// Initialize API client on launch
SoundCloudAPI.shared.configure()
}
}
// Native menu bar integration
.commands {
CommandGroup(replacing: .playback) {
Button("Play/Pause") {
player.togglePlayback()
}
.keyboardShortcut(" ", modifiers: [.command])
Button("Next Track") {
player.skipToNext()
}
.keyboardShortcut(.rightArrow, modifiers: [.command])
}
}
}
}
Explanation: This entry point demonstrates modern SwiftUI app architecture. The @StateObject property wrappers create persistent observable objects that survive view recomputations. By injecting them into the environment, all child views can access shared state without manual passing. The .commands modifier integrates with macOS's native menu system, providing familiar keyboard shortcuts.
2. SoundCloud API Service Layer
import Foundation
import SoundCloud
class TrackService: ObservableObject {
@Published var isLoading = false
@Published var tracks: [Track] = []
private let api = SoundCloudAPI.shared
private var currentTask: Task<Void, Error>?
/// Fetches tracks from a user's stream with async/await
func fetchStream() async throws {
isLoading = true
defer { isLoading = false }
do {
// Private API endpoint for personalized stream
let streamTracks = try await api.get("/stream", parameters: [
"limit": 50,
"offset": tracks.count
])
// Decode JSON into Swift models
tracks = try JSONDecoder().decode([Track].self, from: streamTracks)
} catch {
// Propagate errors for UI presentation
throw APIError.fetchFailed(error.localizedDescription)
}
}
/// Cancels ongoing requests when user navigates away
func cancel() {
currentTask?.cancel()
}
}
Explanation: This service class showcases Swift concurrency best practices. The @Published properties automatically trigger UI updates when data changes. Using async/await simplifies asynchronous networking code compared to traditional completion handlers. The cancel() method prevents race conditions when users rapidly switch views—a common source of bugs in reactive applications.
3. Player View with Reactive UI
import SwiftUI
import AVFoundation
struct PlayerView: View {
@EnvironmentObject var player: AudioPlayer
@State private var scrubPosition: Double = 0
var body: some View {
VStack(spacing: 16) {
// Album artwork with native AsyncImage
if let artworkURL = player.currentTrack?.artworkURL {
AsyncImage(url: artworkURL) { image in
image.resizable()
.aspectRatio(contentMode: .fill)
} placeholder: {
ProgressView()
}
.frame(width: 300, height: 300)
.cornerRadius(12)
.shadow(radius: 8)
}
// Track metadata
VStack(spacing: 4) {
Text(player.currentTrack?.title ?? "No track playing")
.font(.headline)
.lineLimit(1)
Text(player.currentTrack?.artist ?? "")
.font(.subheadline)
.foregroundColor(.secondary)
}
// Scrubber with real-time updates
Slider(value: $scrubPosition, in: 0...player.duration) { editing in
if editing {
player.pause()
} else {
player.seek(to: scrubPosition)
player.play()
}
}
.onReceive(player.$currentTime) { time in
scrubPosition = time
}
.disabled(player.duration == 0)
// Transport controls using SF Symbols
HStack(spacing: 24) {
Button(action: player.skipToPrevious) {
Image(systemName: "backward.fill")
.font(.title2)
}
.buttonStyle(PlainButtonStyle())
Button(action: player.togglePlayback) {
Image(systemName: player.isPlaying ? "pause.fill" : "play.fill")
.font(.largeTitle)
}
.buttonStyle(PlainButtonStyle())
Button(action: player.skipToNext) {
Image(systemName: "forward.fill")
.font(.title2)
}
.buttonStyle(PlainButtonStyle())
}
}
.padding()
.frame(minWidth: 400, minHeight: 500)
}
}
Explanation: This view exemplifies SwiftUI's reactive paradigm. The @EnvironmentObject provides access to the shared player state without explicit initialization. AsyncImage handles network image loading with built-in caching and placeholder states. The Slider component demonstrates two-way binding—updating from player state while also sending user input back. Using SF Symbols ensures pixel-perfect native iconography that automatically adapts to macOS design changes.
4. API Authentication Flow
import SwiftUI
import WebKit
struct LoginView: View {
@StateObject private var authManager = AuthenticationManager()
@Environment(\.dismiss) private var dismiss
var body: some View {
VStack {
if let authURL = authManager.authorizationURL {
// Embedded WebView for OAuth flow
WebView(url: authURL, onCallback: { callbackURL in
Task {
do {
try await authManager.handleCallback(callbackURL)
dismiss()
} catch {
// Show error alert
print("Authentication failed: \(error)")
}
}
})
.frame(width: 500, height: 600)
} else {
ProgressView("Loading login page...")
}
}
.navigationTitle("Sign in to SoundCloud")
}
}
// SwiftUI wrapper for WKWebView
struct WebView: NSViewRepresentable {
let url: URL
let onCallback: (URL) -> Void
func makeNSView(context: Context) -> WKWebView {
let webView = WKWebView()
webView.navigationDelegate = context.coordinator
return webView
}
func updateNSView(_ webView: WKWebView, context: Context) {
let request = URLRequest(url: url)
webView.load(request)
}
func makeCoordinator() -> Coordinator {
Coordinator(onCallback: onCallback)
}
class Coordinator: NSObject, WKNavigationDelegate {
let onCallback: (URL) -> Void
init(onCallback: @escaping (URL) -> Void) {
self.onCallback = onCallback
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if let url = navigationAction.request.url, url.scheme == "nuage" {
onCallback(url)
decisionHandler(.cancel)
return
}
decisionHandler(.allow)
}
}
}
Explanation: This authentication pattern bridges SwiftUI and AppKit via NSViewRepresentable. The custom WebView wraps WKWebView to handle SoundCloud's OAuth flow within the native app context. The coordinator pattern manages delegate callbacks, capturing the authorization token without leaving the app. This approach maintains security while providing a seamless login experience—far superior to redirecting users to an external browser.
Advanced Usage & Best Practices
Optimizing for Low-Latency Audio
To minimize audio lag when using Nuage alongside production software:
- In Audio MIDI Setup, create an aggregate device combining your interface with Nuage's virtual output
- Set buffer sizes to 128 samples or lower in Nuage's preferences
- Disable macOS's "Automatic Graphics Switching" in System Settings when performing
- Use the
sudo sysctl -w kern.timer.coalescing_enabled=0command to reduce audio thread jitter
Contributing Code Effectively
When submitting pull requests:
- Follow SwiftUI idioms: Prefer
@Stateand@Bindingover singletons - Test on multiple macOS versions: Use GitHub Actions' macOS matrix strategy
- Document API changes: The private SoundCloud API is fragile—annotate endpoints with
/// - Warning: Private API - Sign commits: Use GPG signing for security:
git commit -S -m "Your message"
Custom Theming
Override SwiftUI's default appearance by modifying Assets.xcassets:
- Create custom color sets for dark mode variants
- Override SF Symbol weights in
View+Extensions.swift - Implement accent color synchronization with System Settings
Handling API Rate Limits
The private API imposes strict quotas. Implement exponential backoff:
func fetchWithRetry<T>(_ request: () async throws -> T) async throws -> T {
var delay = 1.0
for attempt in 1...3 {
do {
return try await request()
} catch let error as APIError where error.statusCode == 429 {
try await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000))
delay *= 2 // Exponential backoff
}
}
throw APIError.rateLimitExceeded
}
Comparison: Nuage vs. Alternatives
| Feature | Nuage | SoundCloud Web | Electron Clients | Other Native Apps |
|---|---|---|---|---|
| Performance | ⭐⭐⭐⭐⭐ Native | ⭐⭐⭐ Browser overhead | ⭐⭐ Heavy RAM usage | ⭐⭐⭐⭐ Varies |
| System Integration | ⭐⭐⭐⭐⭐ Full | ⭐⭐ Limited | ⭐⭐⭐ Moderate | ⭐⭐⭐⭐ Good |
| SwiftUI Learning | ⭐⭐⭐⭐⭐ Excellent | N/A | N/A | ⭐⭐ Limited |
| API Stability | ⭐⭐ Private API risk | ⭐⭐⭐⭐⭐ Official | ⭐⭐⭐⭐ Official | ⭐⭐⭐ Mixed |
| Customization | ⭐⭐⭐⭐⭐ Full source | ⭐ Limited | ⭐⭐ Moderate | ⭐⭐⭐ Some |
| Resource Usage | ~50 MB RAM | ~300+ MB RAM | ~500+ MB RAM | ~100-200 MB RAM |
| Offline Support | Experimental | No | Varies | Limited |
Why choose Nuage? The combination of native performance, modern SwiftUI architecture, and open-source flexibility makes it unmatched for developers and power users. While the private API dependency introduces risk, the active community and Laurin Brandner's rapid response to API changes mitigate this concern. For casual listeners, the web player suffices—but for anyone serious about music workflow or SwiftUI development, Nuage is the clear winner.
Frequently Asked Questions
Q: Is Nuage officially supported by SoundCloud? A: No. Nuage is an independent project using private APIs. SoundCloud could restrict access at any time, though the developer actively monitors and adapts to changes.
Q: Why does Nuage use private APIs instead of the official public API? A: The public API is severely limited—many features like personalized streams, high-quality audio, and certain search capabilities aren't exposed. Private APIs unlock the full SoundCloud experience.
Q: How stable is Nuage for daily use? A: Reasonably stable for core playback, but expect occasional bugs. The SwiftUI framework itself is still evolving, and private API changes can break features. Check GitHub issues before updating.
Q: Can I contribute if I'm new to SwiftUI? A: Absolutely! The project welcomes contributors of all levels. Start with small UI tweaks or documentation improvements. The codebase is well-structured for learning.
Q: What are the GPL-3.0 license implications? A: If you modify Nuage's code and distribute the app, you must also open-source your changes under GPL-3.0. For private use or learning, no restrictions apply. Commercial licensing requires contacting the author.
Q: Will Nuage work on macOS versions older than Monterey? A: No. SwiftUI features used require macOS 12.0+. The project uses async/await and other modern Swift concurrency features not available in earlier versions.
Q: How do I report bugs or request features? A: Open an issue on the GitHub repository. Include your macOS version, steps to reproduce, and relevant logs from Console.app.
Conclusion: Why Nuage Deserves Your Attention
Nuage represents more than just another SoundCloud client—it embodies the renaissance of native Mac applications in an era dominated by bloated web wrappers. By harnessing SwiftUI's declarative power and Laurin Brandner's meticulous engineering, it delivers an experience that feels genuinely macOS-native while maintaining the flexibility that only open-source software can provide.
The project's current development status shouldn't deter you; rather, it presents an opportunity to shape its future. Whether you're streamlining your music production workflow, learning cutting-edge SwiftUI patterns, or simply craving a more responsive SoundCloud experience, Nuage offers tangible value today with immense potential tomorrow.
The private API dependency is a calculated risk that pays dividends in functionality, and the GPL-3.0 license ensures the community can maintain and evolve the project regardless of SoundCloud's corporate decisions. As Apple continues refining SwiftUI and macOS, Nuage will naturally inherit these improvements, making it a future-proof investment.
Ready to transform your SoundCloud experience? Download Nuage via brew install --cask nuage or grab the latest release from the official GitHub repository. Star the repo, join the discussion in issues, and become part of the movement bringing native app excellence back to macOS.