Static Assets
Verse supports four types of visual assets for artworks: images, videos, SVGs, and iframes (interactive/generative content). Each type has a different URL structure and rendering strategy.
Quick Start — Displaying an Asset
The baseUrl returned by the API is a template, not a ready-to-use URL. Replace {{SIZE}} and {{FORMAT}} before use:
// Turn a baseUrl template into a displayable image URL (works in any framework)
function resolveImageUrl(baseUrl, width = "w640", format = "webp") {
return baseUrl.replace("{{SIZE}}", width).replace("{{FORMAT}}", format);
}
// Example
const imageUrl = resolveImageUrl(cover.baseUrl);
// "https://verse.works/content/w640/artwork@webp"
Which field to use depends on the asset type:
| Asset type | Display as image (thumbnail) | Display natively |
|---|---|---|
ImageAsset | baseUrl — replace {{SIZE}} and {{FORMAT}} | Same as thumbnail |
VideoAsset | previewImageUrl — replace {{SIZE}} and {{FORMAT}} | baseUrl — direct video URL, use in <video src> |
SVGAsset | previewImageUrl — replace {{SIZE}} and {{FORMAT}} | baseUrl — use with size = "source" and no format |
IFrameAsset | previewImageUrl — replace {{SIZE}} and {{FORMAT}} | iframeUrl — load in an <iframe src> |
If you see literal {{SIZE}} or {{FORMAT}} in your browser's network tab, the placeholders were not replaced. Every image baseUrl and previewImageUrl must be resolved before use.
Asset Types
Every artwork has a cover field that resolves to one of four GraphQL types:
| Type | Purpose | Key fields |
|---|---|---|
ImageAsset | Static or animated images | baseUrl, isGif, width, height, aspectRatio |
VideoAsset | Native video files | baseUrl, previewImageUrl, previewAspectRatio |
SVGAsset | Vector artwork | baseUrl, previewImageUrl, previewAspectRatio |
IFrameAsset | Interactive / generative content | baseUrl, iframeUrl, previewImageUrl, aspectRatio |
All types share id, caption, and mimeType. ImageAsset and VideoAsset also carry fileSize.
URL Construction — The Template System
The backend returns template URLs with two placeholders:
https://verse.works/content/{{SIZE}}/artwork@{{FORMAT}}
| Placeholder | Replaced with | Example |
|---|---|---|
{{SIZE}} | A width token or named size | w320, w640, w1400, w3840, source |
{{FORMAT}} | An image format | webp, jpeg, png, gif, avif |
Resolving a Template URL
Replace both placeholders to get a usable URL:
// Standard image — serve as WebP at 640px wide
const url = baseUrl.replace("{{SIZE}}", "w640").replace("{{FORMAT}}", "webp");
// → "https://verse.works/content/w640/artwork@webp"
// Source file — strip the format segment entirely
const originalUrl = baseUrl.replace("{{SIZE}}", "source").replace("@{{FORMAT}}", "");
// → "https://verse.works/content/source/artwork"
When you don't want a specific format (SVGs, original GIFs), remove the @{{FORMAT}} segment entirely.
Available Sizes
From the GraphQL ImageSizes enum:
THUMBNAIL | MEDIUM | FULLSCREEN
W80 | W160 | W320 | W480 | W640 | W980 | W1400 | W2400 | W3840
Plus special string values "source" (original file) and "sq1200" (1200px square crop).
Available Formats
From the GraphQL ImageFormats enum:
JPEG | WEBP | PNG | GIF | AVIF
Default format is WebP. Recommended format selection:
| Asset | Context | Format to use |
|---|---|---|
| Regular image | Any | webp (default) |
| GIF image | Animated display (artwork page) | gif (preserves animation) |
| GIF image | Static thumbnail | jpeg (faster than GIF-to-WebP conversion) |
| SVG | Any | Strip @{{FORMAT}} — serve as original |
Responsive Images
To serve responsive images (e.g. in an <img srcset>), generate multiple URLs at different widths:
const widths = [320, 640, 980, 1400];
const srcset = widths
.map(w => `${baseUrl.replace("{{SIZE}}", `w${w}`).replace("{{FORMAT}}", "webp")} ${w}w`)
.join(", ");
Video Rendering
Videos (VideoAsset) use a direct URL — no template placeholders:
<video autoplay loop muted playsinline preload="auto">
<source src="{cover.baseUrl}" type="video/mp4" />
</video>
baseUrlpoints directly to the video file- For thumbnails, use
previewImageUrl(this is a template URL — resolve it like any image)
IFrame Rendering
IFrame assets (IFrameAsset) represent interactive or generative content. They can be displayed in two ways:
Live Mode
Render the interactive content in an iframe:
<iframe src="{cover.iframeUrl}" loading="lazy"></iframe>
Use loading="lazy" to defer loading until the iframe is near the viewport. Consider using location.replace() instead of setting src to avoid polluting browser back/forward history.
Static Preview
Display the previewImageUrl as a regular image (resolve the template as usual). This is useful for thumbnails, grids, and contexts where interactive content is not needed.
GLB (3D Models)
If the iframeUrl ends in .glb, the content is a 3D model. On verse.works, these are routed through a dedicated viewer. For your own integration, you can use any glTF/GLB viewer library (e.g. <model-viewer>).
4K Live Links
Some artworks support a high-resolution variant via query parameters appended to the iframeUrl.
SVG Rendering
SVGs are always served at original size with no format conversion:
const svgUrl = baseUrl.replace("{{SIZE}}", "source").replace("@{{FORMAT}}", "");
Image Preview / Fullscreen
When displaying assets in a fullscreen or preview context, each type renders differently:
- ImageAsset — Full-resolution image. For GIFs, use the original format to preserve animation.
- SVGAsset — Source-size image with no format conversion.
- VideoAsset — Native
<video>with aspect ratio preserved. - IFrameAsset —
<iframe>with aspect ratio preserved.
GraphQL Fragment
A recommended fragment for fetching all asset fields needed for rendering:
fragment AllArtworkCoverFormats on Artwork {
cover {
... on ImageAsset {
id, isGif, width, height, baseUrl, aspectRatio, caption, mimeType, fileSize
}
... on VideoAsset {
id, width, height, baseUrl, caption, previewAspectRatio, previewImageUrl,
mimeType, fileSize
}
... on SVGAsset {
id, baseUrl, caption, previewAspectRatio, previewImageUrl, mimeType, fileSize
}
... on IFrameAsset {
id, baseUrl, caption, previewImageUrl, iframeUrl, aspectRatio
}
}
}
Troubleshooting
Images are broken / return 404:
- Check your browser's network tab. If the request URL contains literal
{{SIZE}}or{{FORMAT}}, the placeholders were not replaced. Apply the substitution from the Quick Start section.
Image loads but is the wrong size:
- Make sure you're using a valid size token. Valid values:
w80,w160,w320,w480,w640,w980,w1400,w2400,w3840,source,thumbnail,medium,fullscreen,sq1200.
Video won't play:
VideoAsset.baseUrlis a direct URL (no placeholders). Use it in a<video>or<source>element. Don't apply{{SIZE}}/{{FORMAT}}substitution to video URLs.
Thumbnail is blank for a video/iframe/SVG:
- For non-image asset types, use
previewImageUrl(notbaseUrl) to display a still thumbnail. See the Quick Start table.