
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeI can see your issue! When you query a file field from Sanity, you're getting a file object/reference, not the actual URL string. That's why student.audio doesn't work directly with the Audio() constructor, but a direct URL does.
The file field in Sanity returns an object that contains metadata about the file, including a reference to the asset. To get the actual playable URL, you need to resolve that asset reference in your GROQ query.
Here's what you need to change:
In your GROQ query, instead of just querying audio, you need to get the URL from the asset:
*[_type == "student"] {
name,
bio,
image,
"audioUrl": audio.asset->url
}The key part is "audioUrl": audio.asset->url - this follows the reference (->) to the actual asset and retrieves its URL.
In your component, you'd then use:
const playAudio = () => {
let audio = new Audio(student.audioUrl);
audio.play();
}The reason your other fields work is that for images, you're probably using Sanity's image URL builder or a similar helper that automatically resolves the asset reference. For the file type with audio, you need to explicitly get the URL in your query.
As mentioned in the Sanity documentation on file types, the file field stores a reference to an asset, and you need to query asset->url to get the actual URL string you can use in your JavaScript.
Your schema looks correct (using type: 'file' for the audio field), so it's just the query that needs the adjustment!
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store