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:
| Type | Contains | Key field |
|---|---|---|
| Images | Product photos | images with originalUrl, imageVariants for transformed URLs |
| Videos | YouTube, Vimeo or hosted video URLs | videos with uri per language |
| Documents | PDFs, spec sheets, manuals | documents 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:
imagescontains the original uploaded file withoriginalUrlandmimeType.imageVariantsreturns transformed URLs based on the transformations you define in the query. Each variant is identified by thenameyou 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.
| Mode | Behavior |
|---|---|
BOUNDS | Scales the image to fit within the dimensions, maintaining aspect ratio. The resulting image may be smaller than the specified size. |
COVER | Scales the image to completely fill the dimensions, cropping if needed. |
CROP | Resizes and crops the image centrally to exactly match the dimensions. |
Output formats
Use the format parameter to control the output format:
| Format | Description |
|---|---|
AUTO | Automatically selects the best format based on browser support and image characteristics. Recommended for most use cases. |
WEBP | Good compression with transparency support. Widely supported. |
AVIF | Best compression but slower to encode. Growing browser support. |
JPG | Universal support. No transparency. |
PNG | Lossless 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:
| Parameter | Description |
|---|---|
quality | Compression quality (1 to 100) |
dpr | Device pixel ratio (1 to 10), for retina displays |
blur | Gaussian blur (0.5 to 1000) |
brightness | Brightness adjustment (-100 to 100) |
contrast | Contrast adjustment (-100 to 100) |
saturation | Saturation adjustment (-100 to 100) |
sharpen | Sharpening 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:
| Parameter | Default | Description |
|---|---|---|
page | 1 | Current page number |
offset | 12 | Number of items per page |
sort | ASC | Sort direction: ASC or DESC |
The response includes pagination metadata:
| Field | Description |
|---|---|
itemsFound | Total number of media items matching the query |
page | Current page number |
pages | Total number of pages |
offset | Items 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
- Understanding products and categories for how products, clusters and categories relate
- Querying products for filtering, pagination and search
- Get product images with responsive transformations for a ready-to-use recipe