You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If any of the three shows this is already done or underway, close this rather than duplicating the work.
Current state, read 2026-08-12
Upload already accepts two formats. src/lib/server/vr-models.ts sniffs by magic bytes and recognises VRM (glTF binary, glTF magic at offset 0) and FBX (both the Kaydara FBX Binary header and the ASCII ; FBX x.y.z comment convention). src/lib/server/vr-avatars.ts stores one of vrm, vrm0, or fbx. Accepted content types are application/octet-stream and model/gltf-binary.
The viewer renders VRM only.src/lib/components/VrViewer.svelte loads three, GLTFLoader, and the VRM loader plugin, then throws not a VRM model when the parsed result has no VRM data. So an FBX upload is accepted, stored, and downloadable, but cannot be previewed.
That makes the gap specific: it is not that other formats are rejected at the door, it is that the viewer only knows one of them.
What needs deciding
Which formats actually matter to people exporting from VRChat, and in what order. FBX is already half-supported and is the obvious first candidate, but "what VRChat users actually have on disk" should drive this rather than what the sniffer happens to recognise.
Whether unpreviewable formats stay uploadable. Accepting a file the viewer cannot show is defensible if the download is the point, and confusing if the visitor expects a 3D preview. Either way the UI should say which it is, rather than leaving a dead viewer.
Bundle cost. The viewer already defers three and the VRM plugin behind a click specifically so they never ride the initial page load. Any additional loader has to respect that, and a second loader is a second heavyweight import.
Tests
Sniffer tests for each newly supported format, including a rejection case.
A viewer test per format asserting it loads, and asserting the failure path stays graceful for anything unsupported.
Mentioned in a DM as work coming "soon," but never written down anywhere. Filed so it exists outside one person's head.
Confirm before starting
This issue was created from a passing remark, not from a spec, and the code moves fast. Before writing anything, check all three:
If any of the three shows this is already done or underway, close this rather than duplicating the work.
Current state, read 2026-08-12
Upload already accepts two formats.
src/lib/server/vr-models.tssniffs by magic bytes and recognises VRM (glTF binary,glTFmagic at offset 0) and FBX (both theKaydara FBX Binaryheader and the ASCII; FBX x.y.zcomment convention).src/lib/server/vr-avatars.tsstores one ofvrm,vrm0, orfbx. Accepted content types areapplication/octet-streamandmodel/gltf-binary.The viewer renders VRM only.
src/lib/components/VrViewer.svelteloads three, GLTFLoader, and the VRM loader plugin, then throwsnot a VRM modelwhen the parsed result has no VRM data. So an FBX upload is accepted, stored, and downloadable, but cannot be previewed.That makes the gap specific: it is not that other formats are rejected at the door, it is that the viewer only knows one of them.
What needs deciding
Which formats actually matter to people exporting from VRChat, and in what order. FBX is already half-supported and is the obvious first candidate, but "what VRChat users actually have on disk" should drive this rather than what the sniffer happens to recognise.
Whether unpreviewable formats stay uploadable. Accepting a file the viewer cannot show is defensible if the download is the point, and confusing if the visitor expects a 3D preview. Either way the UI should say which it is, rather than leaving a dead viewer.
Bundle cost. The viewer already defers three and the VRM plugin behind a click specifically so they never ride the initial page load. Any additional loader has to respect that, and a second loader is a second heavyweight import.
Tests