CarPlay Now Playing integration patterns. Use when implementing CarPlay audio controls, CPNowPlayingTemplate customization, or debugging CarPlay-specific issues.
View on GitHubSelect agents to install to:
npx add-skill https://github.com/CharlesWiltgen/Axiom/blob/main/.claude-plugin/plugins/axiom/skills/axiom-now-playing-carplay/SKILL.md -a claude-code --skill axiom-now-playing-carplayInstallation paths:
.claude/skills/axiom-now-playing-carplay/# CarPlay Integration
**Time cost**: 15-20 minutes (if MPNowPlayingInfoCenter already working)
## Key Insight
**CarPlay uses the SAME MPNowPlayingInfoCenter and MPRemoteCommandCenter as Lock Screen and Control Center.** If your Now Playing integration works on iOS, it automatically works in CarPlay with zero additional code.
## What CarPlay Reads
| iOS Component | CarPlay Display |
|---------------|-----------------|
| `MPNowPlayingInfoCenter.nowPlayingInfo` | CPNowPlayingTemplate metadata (title, artist, artwork) |
| `MPRemoteCommandCenter` handlers | CPNowPlayingTemplate button responses |
| Artwork from `nowPlayingInfo` | Album art in CarPlay UI |
No CarPlay-specific metadata needed. Your existing code works.
## CPNowPlayingTemplate Customization (iOS 14+)
For custom playback controls beyond standard play/pause/skip:
```swift
import CarPlay
@MainActor
class SceneDelegate: UIResponder, UIWindowSceneDelegate, CPTemplateApplicationSceneDelegate {
func templateApplicationScene(
_ templateApplicationScene: CPTemplateApplicationScene,
didConnect interfaceController: CPInterfaceController
) {
// ✅ Configure CPNowPlayingTemplate at connection time (not when pushed)
let nowPlayingTemplate = CPNowPlayingTemplate.shared
// Enable Album/Artist browsing (shows button that navigates to album/artist view in your app)
nowPlayingTemplate.isAlbumArtistButtonEnabled = true
// Enable Up Next queue (shows button that displays upcoming tracks)
nowPlayingTemplate.isUpNextButtonEnabled = true
// Add custom buttons (iOS 14+)
setupCustomButtons(for: nowPlayingTemplate)
}
private func setupCustomButtons(for template: CPNowPlayingTemplate) {
var buttons: [CPNowPlayingButton] = []
// Playback rate button
let rateButton = CPNowPlayingPlaybackRateButton { [weak self] button in
self?.cyclePlaybackRate()
}
buttons.append(rateButton)