Skip to main content

Media and assets

Fetch and display product images, videos and documents using Propeller's GraphQL API. Images support server-side transformations so you can request exactly the sizes and formats your UI needs.

Propeller supports three media types:

TypeContainsKey field
ImagesProduct photosimages with originalUrl, imageVariants for transformed URLs
VideosYouTube, Vimeo or hosted video URLsvideos with uri per language
DocumentsPDFs, spec sheets, manualsdocuments with originalUrl per language

All media types support localized alt text, description and tags. The priority field controls display order.

Querying product images

Use the media field on a product to fetch its images. Request imageVariants with named transformations to get URLs at the exact size you need.

query GetProductImages($productId: Int!) {
product(productId: $productId) {
... on Product {
media {
images(search: { sort: ASC, page: 1, offset: 12 }) {
items {
id
alt {
language
value
}
description {
language
value
}
priority
images {
originalUrl
mimeType
}
imageVariants(
input: {
transformations: [
{
name: "thumbnail"
transformation: {
width: 120
height: 120
fit: BOUNDS
bgColor: "transparent"
canvas: { width: 120, height: 120 }
}
}
{
name: "large"
transformation: {
width: 800
height: 800
fit: BOUNDS
}
}
]
}
) {
name
url
}
}
itemsFound
page
pages
}
}
}
}
}

Expected response:

{
"data": {
"product": {
"media": {
"images": {
"items": [
{
"id": "cb853191-b9b4-4a0e-9240-f2168f1e0ef7",
"alt": [
{
"language": "NL",
"value": "Ergonomic desk chair front view"
}
],
"description": [
{
"language": "NL",
"value": "Ergonomic desk chair front view"
}
],
"priority": 1,
"images": [
{
"originalUrl": "https://media.helice.cloud/example/images/en/cb853191-chair-front.jpg",
"mimeType": "image/jpeg"
}
],
"imageVariants": [
{
"name": "thumbnail",
"url": "https://media.helice.cloud/example/images/en/cb853191-chair-front.jpg?bg-color=transparent&canvas=120,120&fit=bounds&height=120&width=120"
},
{
"name": "large",
"url": "https://media.helice.cloud/example/images/en/cb853191-chair-front.jpg?fit=bounds&height=800&width=800"
}
]
},
{
"id": "8c77dcfc-737e-4345-921e-25570aae9232",
"alt": [
{
"language": "NL",
"value": "Ergonomic desk chair side view"
}
],
"description": [
{
"language": "NL",
"value": "Ergonomic desk chair side view"
}
],
"priority": 2,
"images": [
{
"originalUrl": "https://media.helice.cloud/example/images/en/8c77dcfc-chair-side.jpg",
"mimeType": "image/jpeg"
}
],
"imageVariants": [
{
"name": "thumbnail",
"url": "https://media.helice.cloud/example/images/en/8c77dcfc-chair-side.jpg?bg-color=transparent&canvas=120,120&fit=bounds&height=120&width=120"
},
{
"name": "large",
"url": "https://media.helice.cloud/example/images/en/8c77dcfc-chair-side.jpg?fit=bounds&height=800&width=800"
}
]
}
],
"itemsFound": 2,
"page": 1,
"pages": 1
}
}
}
}
}

Each image has two URL sources:

  • images contains the original uploaded file with originalUrl and mimeType.
  • imageVariants returns transformed URLs based on the transformations you define in the query. Each variant is identified by the name you assign.

Use imageVariants for display. Use originalUrl when you need the unmodified source file.

Image transformations

The imageVariants field applies server-side transformations before returning the image URL. You define transformations in the query, so no client-side resizing is needed.

Fit modes

The fit parameter controls how the image is constrained within the specified width and height. Both width and height must be specified for fit to take effect.

ModeBehavior
BOUNDSScales the image to fit within the dimensions, maintaining aspect ratio. The resulting image may be smaller than the specified size.
COVERScales the image to completely fill the dimensions, cropping if needed.
CROPResizes and crops the image centrally to exactly match the dimensions.

Output formats

Use the format parameter to control the output format:

FormatDescription
AUTOAutomatically selects the best format based on browser support and image characteristics. Recommended for most use cases.
WEBPGood compression with transparency support. Widely supported.
AVIFBest compression but slower to encode. Growing browser support.
JPGUniversal support. No transparency.
PNGLossless with transparency. Larger file sizes.

Other formats available: GIF, BJPG (baseline JPEG), PJPG (progressive JPEG), JXL (JPEG XL), PNG8 (palette PNG), WEBPLL (lossless WebP), WEBPLY (lossy WebP).

Canvas and background color

Use canvas and bgColor together to produce images with consistent dimensions. This is useful for product listing grids where all thumbnails should be the same size regardless of the original image proportions.

imageVariants(
input: {
transformations: [
{
name: "grid"
transformation: {
width: 200
height: 200
fit: BOUNDS
bgColor: "transparent"
canvas: { width: 200, height: 200 }
}
}
]
}
) {
name
url
}

The image is first scaled to fit within 200×200 pixels (fit: BOUNDS), then placed on a 200×200 canvas. The remaining space is filled with the bgColor. This guarantees every image in the grid is exactly 200×200 pixels, with the product centered.

Other transformation options

The transformation API supports additional parameters for advanced use cases:

ParameterDescription
qualityCompression quality (1 to 100)
dprDevice pixel ratio (1 to 10), for retina displays
blurGaussian blur (0.5 to 1000)
brightnessBrightness adjustment (-100 to 100)
contrastContrast adjustment (-100 to 100)
saturationSaturation adjustment (-100 to 100)
sharpenSharpening settings

Requesting multiple sizes in one query

Pass an array of transformations to request multiple sizes in a single query. This is efficient for responsive images where you need a thumbnail, a medium size and a large detail image.

imageVariants(
input: {
transformations: [
{
name: "thumbnail"
transformation: {
width: 100
height: 100
fit: BOUNDS
bgColor: "transparent"
canvas: { width: 100, height: 100 }
}
}
{
name: "medium"
transformation: {
width: 400
height: 400
fit: BOUNDS
format: WEBP
}
}
{
name: "large"
transformation: {
width: 800
height: 800
fit: BOUNDS
format: WEBP
}
}
]
}
) {
name
url
}

Each variant in the response is identified by name, so you can pick the right URL for each context: thumbnail for product listing cards, medium for category pages and large for product detail galleries.

Querying product videos

Use media.videos to fetch product videos:

query GetProductVideos($productId: Int!) {
product(productId: $productId) {
... on Product {
media {
videos(search: { sort: ASC, page: 1, offset: 12 }) {
items {
id
alt {
language
value
}
description {
language
value
}
priority
videos {
language
uri
mimeType
}
}
itemsFound
}
}
}
}
}

Expected response:

{
"data": {
"product": {
"media": {
"videos": {
"items": [
{
"id": "67e62e23-1eb0-4ef8-b1a4-65bea27a7422",
"alt": [
{
"language": "NL",
"value": "Product demonstration video"
}
],
"description": [
{
"language": "NL",
"value": "Product demonstration video"
}
],
"priority": 1,
"videos": [
{
"language": "NL",
"uri": "https://www.youtube.com/embed/example-product-demo",
"mimeType": "video/mp4"
}
]
}
],
"itemsFound": 1
}
}
}
}
}

The uri field contains the video URL. This can be a YouTube embed URL, a Vimeo URL or any hosted video URL. Videos are localized, so different languages can have different video URIs.

Querying product documents

Use media.documents to fetch downloadable files like spec sheets, manuals and safety data sheets:

query GetProductDocuments($productId: Int!) {
product(productId: $productId) {
... on Product {
media {
documents(search: { sort: ASC, page: 1, offset: 12 }) {
items {
id
alt {
language
value
}
description {
language
value
}
priority
documents {
language
originalUrl
mimeType
}
}
itemsFound
}
}
}
}
}

Expected response:

{
"data": {
"product": {
"media": {
"documents": {
"items": [
{
"id": "27760524-bce0-46ef-947d-464472f734fe",
"alt": [
{
"language": "NL",
"value": "Product specification sheet"
}
],
"description": [
{
"language": "NL",
"value": "Product specification sheet"
}
],
"priority": 1,
"documents": [
{
"language": "en",
"originalUrl": "https://media.helice.cloud/example/documents/en/27760524-product-spec-sheet.pdf",
"mimeType": "application/pdf"
}
]
}
],
"itemsFound": 1
}
}
}
}
}

Use mimeType to determine how to handle the file. For example, render PDFs inline or show a download button for other file types.

Querying media by cluster or category

The Cluster and Category types do not have a media field directly. To fetch media for a cluster or category, use the root-level media query with a clusterId or categoryId filter:

query GetClusterImages($clusterId: Int) {
media {
images(search: { clusterId: $clusterId, sort: ASC, page: 1, offset: 12 }) {
items {
id
alt {
language
value
}
priority
images {
originalUrl
mimeType
}
imageVariants(
input: {
transformations: [
{
name: "detail"
transformation: {
width: 600
height: 600
fit: BOUNDS
format: WEBP
}
}
]
}
) {
name
url
}
}
itemsFound
}
}
}

The root media query accepts productId, clusterId and categoryId as filters in its search input. The same pattern works for videos and documents.

Alternatively, you can access cluster media through the cluster's products:

query {
cluster(clusterId: 456) {
defaultProduct {
media {
images(search: { sort: ASC }) {
items {
id
imageVariants(
input: {
transformations: [
{
name: "detail"
transformation: { width: 600, height: 600, fit: BOUNDS }
}
]
}
) {
name
url
}
}
}
}
}
}
}

Pagination and sorting

All media queries support pagination and sorting through the search input:

ParameterDefaultDescription
page1Current page number
offset12Number of items per page
sortASCSort direction: ASC or DESC

The response includes pagination metadata:

FieldDescription
itemsFoundTotal number of media items matching the query
pageCurrent page number
pagesTotal number of pages
offsetItems per page

Images are sorted by priority. A lower priority value means the image appears first when sorted ASC. Use priority to control which image is shown as the primary product photo.

Next steps