Skip to main content

Thumbnail Presets

The File Storage service auto-generates thumbnail variants for every uploaded image. Modules retrieve thumbnails by preset name — no manual resize or URL construction required.


Preset Reference

PresetDimensionsAuto-generatedTypical use case
icon_3232 × 32 px✅ AlwaysFavicons, sidebar icons, compact lists
avatar_6464 × 64 px☐ On-demandUser avatars in nav, comments, cards
card_300300 × 200 px✅ AlwaysFile cards, grid thumbnails, table previews
preview_600600 × 400 px☐ On-demandModal previews, lightbox preview
full_12001 200 × auto☐ On-demandFull-size display, image viewer

icon_32 and card_300 are generated automatically when any image is uploaded. The remaining three presets are generated on the first GET /files/:id/thumbnail/:preset request (lazy generation), or when explicitly requested in uploadImage({ presets: [...] }).


Retrieve a Thumbnail

SDK

const url = await kernel.files().thumbnail(
'01j9paf1l000000000000000',
'avatar_64'
);
// 'https://api.septemcore.com/v1/files/01j9paf1l.../thumbnail/avatar_64'

REST

GET https://api.septemcore.com/v1/files/01j9paf1l000000000000000/thumbnail/avatar_64
Authorization: Bearer <access_token>

Response options:

Thumbnail ready — 302 Found:

HTTP/1.1 302 Found
Location: https://s3.septemcore.com/01j9p3kz.../avatars/01j9paf1l..._avatar_64.webp?X-Amz-Signature=...
Cache-Control: public, max-age=31536000

The redirect target is a presigned S3 URL valid for 1 year (Cache-Control: max-age=31536000). CDN can cache the thumbnail indefinitely — a new presigned URL is generated when the cache expires.

Thumbnail pending (being generated) — 202 Accepted:

{
"status": "pending",
"preset": "avatar_64",
"message": "Thumbnail is being generated. Retry in 2–5 seconds."
}

Preset not valid — 400 Bad Request:

{
"type": "https://api.septemcore.com/problems/validation-error",
"status": 400,
"detail": "Unknown preset 'banner_800'. Valid presets: icon_32, avatar_64, card_300, preview_600, full_1200.",
"code": "INVALID_PRESET"
}

Request Thumbnails at Upload Time

To avoid lazy-generation latency, specify all required presets in uploadImage():

const result = await kernel.files().uploadImage({
file: imageBlob,
filename: 'hero.png',
bucket: 'assets',
presets: ['icon_32', 'avatar_64', 'card_300', 'preview_600', 'full_1200'],
// All 5 thumbnails generated synchronously before the response is returned
});

// result.thumbnails:
// {
// icon_32: 'https://api.septemcore.com/v1/files/01j9paf1l.../thumbnail/icon_32',
// avatar_64: 'https://api.septemcore.com/v1/files/01j9paf1l.../thumbnail/avatar_64',
// card_300: 'https://api.septemcore.com/v1/files/01j9paf1l.../thumbnail/card_300',
// preview_600: 'https://api.septemcore.com/v1/files/01j9paf1l.../thumbnail/preview_600',
// full_1200: 'https://api.septemcore.com/v1/files/01j9paf1l.../thumbnail/full_1200'
// }

All five thumbnails are generated synchronously and their URLs are included in the upload response — no separate requests needed.


Thumbnail URLs in Metadata

File metadata (GET /files/:id with Accept: application/json) includes all generated thumbnail URLs:

{
"fileId": "01j9paf1l000000000000000",
"filename": "hero.png",
"mimeType": "image/webp",
"size": 84320,
"status": "available",
"thumbnails": {
"icon_32": "https://api.septemcore.com/v1/files/01j9paf1l.../thumbnail/icon_32",
"card_300": "https://api.septemcore.com/v1/files/01j9paf1l.../thumbnail/card_300",
"avatar_64": null,
"preview_600": null,
"full_1200": null
}
}

null means the thumbnail has not been generated yet. Request it via GET /files/:id/thumbnail/:preset to trigger lazy generation.


Using with the ImageUpload Component

The <ImageUpload> component accepts a presets prop to control which thumbnails are generated during upload:

import { ImageUpload } from '@platform/ui-shell';

<ImageUpload
bucket="avatars"
aspectRatio="1:1"
presets={['icon_32', 'avatar_64']}
onUploadComplete={(result) => {
const avatarUrl = result.thumbnails.avatar_64;
updateProfile({ avatarUrl });
}}
/>

Only the presets listed in presets are generated during upload. Unspecified presets are generated lazily on first access.


Thumbnail Generation Rules

RuleDetail
Auto-generated presetsicon_32 and card_300 always generated on upload
Lazy presetsavatar_64, preview_600, full_1200 generated on first GET
FormatAlways WebP regardless of original format (smallest size)
Aspect ratioThumbnails are center-cropped to match the preset's ratio
Processing timeout30 s (FILES_IMAGE_PROCESSING_TIMEOUT_SEC)
On timeoutThumbnail status = pending; background retry queued
Non-image filesGET /files/:id/thumbnail/:preset415 Unsupported Media Type

Error Reference

ScenarioHTTPCode
Invalid preset name400INVALID_PRESET
File is not an image415UNSUPPORTED_MEDIA_TYPE
File not found404not-found
File belongs to different tenant403forbidden
Thumbnail still generating202status: "pending" — retry in 2–5 s