A Nuxt module for integrating Apple MusicKit JS into your Nuxt application.
- 🎵 Seamless MusicKit JS integration
- 🔐 Server-side token management tools
- 🎧 Reactive MusicKit state with useMusicKit composable
- 🚀 TypeScript support with MusicKit types
- Install the module:
npx nuxi module add nuxt-musickit
- Configure your MusicKit credentials in
nuxt.config.ts
:
export default defineNuxtConfig({
modules: ['nuxt-musickit'],
musicKit: {
developerKey: process.env.MUSIC_KIT_DEVELOPER_KEY,
teamID: process.env.MUSIC_KIT_TEAM_ID,
keyID: process.env.MUSIC_KIT_KEY_ID,
appName: process.env.MUSIC_KIT_APP_NAME,
appBuild: process.env.MUSIC_KIT_APP_BUILD
}
})
Available Composables:
useMusicKit():
- Client-side composable that creates and initializes a MusicKit Instance- `generateMusicKitConfig(): Server-side composable that creates a valid MusicKitConfig instance
Use the composable with your token endpoint:
<script setup lang="ts">
import { useMusicKit } from '#imports'
import type { MusicKitConfig, MusicKitInstance } from 'nuxt-musickit';
const { musicKitLoaded, musicKitConnected, tokenExpired, getInstance, musicKitConfig } = useMusicKit()
const loading = ref(true)
const error = ref<string>('')
const searchQuery = ref('')
const searchResults = ref<MusicKitAlbum[]>([])
const renewToken = async () => {
const config = await $fetch('/api/token') as MusicKitConfig
if (!config?.developerToken || !config?.app?.name || !config?.app?.build) {
throw new Error('Invalid MusicKit configuration received from server')
}
musicKitConfig.value = config
}
const searchAlbums = async () => {
try {
if (!searchQuery.value) {
searchResults.value = []
return
}
const musicKit = await getInstance()
const storefrontId = musicKit.storefrontId
if (!storefrontId) {
throw new Error('No storefront ID available')
}
const response = await musicKit.api.music(`/v1/catalog/${storefrontId}/search`, {
term: searchQuery.value,
types: ['albums'],
limit: 10
})
searchResults.value = response.data.results.albums?.data || []
} catch (err: unknown) {
console.error('Search Albums Error:', err)
error.value = err instanceof Error ? err.message : String(err)
searchResults.value = []
}
}
watch(musicKitLoaded, async (loaded) => {
if (loaded) {
try {
loading.value = false
} catch (err: unknown) {
error.value = err instanceof Error ? err.message : String(err)
loading.value = false
}
}
})
watch(tokenExpired, (isExpired) => {
if (isExpired) {
renewToken()
}
})
</script>
Create a server API route to handle developer token updates:
// server/api/token.ts
import { defineEventHandler, createError } from 'h3'
import { generateMusicKitConfig } from "#imports"
export default defineEventHandler(async (_) => {
try {
// Get pre-validated config with fresh token
const musicKitConfig = await generateMusicKitConfig()
return musicKitConfig
} catch (error: unknown) {
// Type narrow the error before accessing properties
let message: string
if (error instanceof Error) {
// Handle the case where it's an Error object
message = error.message
} else {
// Handle the case where the error is something else
message = 'An unknown error occurred during token generation.'
}
// Throw a new error with a meaningful message
throw createError({
statusCode: 500,
statusMessage: message
})
}
})
To use this module, you'll need to create a MusicKit key in your Apple Developer account:
- Go to the Apple Developer MusicKit Page
- Create a new MusicKit key in your Developer Account
- Download the .p8 file and note the following information:
- Key ID: Found in the key details
- Team ID: Your Apple Developer Team ID
- Developer Key: Contents of the .p8 file
- Set up environment variables in your project:
# .env file
MUSIC_KIT_DEVELOPER_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
MUSIC_KIT_TEAM_ID="YOUR_TEAM_ID"
MUSIC_KIT_KEY_ID="YOUR_KEY_ID"
MUSIC_KIT_APP_NAME="Your App Name"
MUSIC_KIT_APP_BUILD="1.0"
Local development
# Install dependencies
npm install
# Generate type stubs
npm run dev:prepare
# Develop with the playground
npm run dev
# Build the playground
npm run dev:build
# Run Vitest
npm run test
npm run test:watch