Standalone runtime images
Status: Operational guide for implementation preview. Runtime Image 0.1.0, Core 0.1.105, contract 54. Deployment and a live board-storage check are required before production use.
<vertcie-image> displays an existing image or renders a published model by its complete signature when that image is missing. Once captured, the 3D scene is disposed and the element displays an ordinary image. Render Studio is a separate authoring tool, not a dependency, render service, or required visual reference for this element.
Install and display
The image module is a separate entry point; loading the configurator wrapper alone does not register it. Use the following path on the host where the image release has been deployed:
<script type="module" src="/runtime/image/v0.1.0/index.js"></script>
<vertcie-image
id="product-image"
endpoint="https://app.vertcie.com"
published-file-id="PUBLISHED_FILE_ID"
signature="COMPLETE_PRODUCT_SIGNATURE"
view="front-3/4"
width="512" height="512"
alt="Configured product"
style="width:512px;height:512px"
></vertcie-image>HTML requires a closing tag for custom elements; do not use XML-style self-closing syntax. Use CSS for display size and width/height for captured pixel dimensions. alt is forwarded to the displayed image. loading="lazy" defers work until visible; calling decode() starts and waits for a lazy load.
A complete signature and permanent Published File ID are required for model fallback. sku is an alias for signature; it does not perform SKU translation or product search. Omit revision to resolve the active immutable revision or provide a positive revision to pin it.
Configure the element
await customElements.whenDefined('vertcie-image');
const image = document.querySelector('#product-image');
// These fields will now be controlled by the configuration object.
for (const name of ['width', 'height', 'view']) image.removeAttribute(name);
image.apiKey = browserScopedKey;
image.configuration = {
apiKey: browserScopedKey,
endpoint: 'https://app.vertcie.com',
publishedFileId: 'PUBLISHED_FILE_ID',
signature: 'COMPLETE_PRODUCT_SIGNATURE',
width: 1024,
height: 1024,
view: 'front-3/4',
modelRotation: [0, 30, 0],
fieldOfView: 35,
environmentPath: 'https://assets.example.com/studio.hdr',
environmentRotation: 90,
environmentIntensity: 1,
exposure: 1,
transparent: true,
pathtracer: true,
samples: [32, 256],
maxRenderTimeMs: 60000,
store: false,
};
await image.decode();Attributes override corresponding configuration fields. Remove an attribute before overriding that field through configuration. Use either one complete configuration object or reactive properties/attributes consistently. API keys belong in JavaScript properties, not URLs; never embed a server/admin key in a browser. For a browser key, allow the embedding origin and grant only the required resources and scopes.
Image properties
| Area | Properties | Meaning |
|---|---|---|
| Identity | publishedFileId, signature / sku, revision, endpoint | Exact published model and configuration; no selection guessing |
| Lookup | src, boardId, imageEndpoint | Exact image URL, board-backed lookup, or custom recipe-aware endpoint |
| View | view | front, back, left, right, top, bottom, front-3/4, back-3/4 |
| Camera | position, target, rotation, dolly, boom, targetHeight, fieldOfView / fov | Vectors and distances use model world units; angles use degrees |
| Model | modelRotation | Three Euler rotation components in degrees |
| Environment | environmentPath / hdri, environmentRotation, environmentIntensity / intensity, exposure | HDRI URL, rotation, lighting strength and exposure |
| Output | width, height, format, quality, transparent, background | Up to 4096 pixels per axis; PNG, JPEG or WebP; quality 0–1; hex background |
| Quality | pathtracer, samples, tiles, maxRenderTimeMs | Optional path tracing, bounded samples, tile count and render budget |
| Backdrop | backdrop | enabled, color, glossiness, filletRadius, width, depth, height |
| Grid | gridEnabled | Optional raster grid; not supported by path tracing |
| Storage | store, boardId | Opt-in persistent image storage on an authorized board |
Kebab-case attributes represent scalar values, for example published-file-id, environment-rotation, target-height, and board-id. Use JavaScript properties/configuration for vectors and backdrop objects. samples="32,256" is the attribute form of a sample range. Boolean attributes accept an empty value, true, or false.
Without explicit camera position, the runtime fits the model using the chosen view and field of view. dolly replaces the fitted camera distance; rotation rotates that view around the target. Explicit position takes precedence over view/dolly positioning. boom adds camera height; targetHeight adds target height. These are independent runtime controls, not instructions to open or run another tool.
The render object also accepts width, height, format, samples, tiles, transparency, exposure, gridEnabled and nonPathtraced for integrations that already hold those fields together. Explicit top-level fields take precedence. Queue priority, batch mode and output-job settings are not browser-image controls.
Path-traced quality
pathtracer defaults to false. samples accepts an integer or [minimum, maximum], from 1 through 4096. The renderer aims for maximum; the time budget may stop it earlier only after minimum has been reached. Otherwise the request fails instead of reporting an undersampled image as complete. The budget starts after path-tracer scene compilation; synchronous GPU compilation cannot be interrupted.
Custom/nodal shaders, toon, displacement, anisotropy and dispersion currently fail explicitly in path-traced mode. Use raster rendering for these materials. There is no silent quality downgrade. Raster contact-shadow helpers are not physical path-traced geometry; enable the physical backdrop when a traced floor/backdrop is needed.
Store on a board
image.store = true;
image.boardId = 'DESTINATION_BOARD_ID';
image.addEventListener('stored', event => {
console.log('Saved image card:', event.detail.cardId);
});
image.addEventListener('storeerror', event => {
console.error('Image is displayable but was not saved:', event.detail.message);
});store defaults to false: no persistent writes. store=true requires boardId. A board ID with store=false performs read-only lookup and can render a miss locally without saving it. The intended test board is Vertcie Demo Images; use its assigned board ID, not its display name.
The API key needs runtime:read, runtime:write, render:create, and assets:write, access to the published model, and a write grant on the destination board in the key's organization. A readable board alone does not authorize storage. Do not broaden unrelated board grants. Workspace session authentication does not automatically grant storage on arbitrary destination boards.
The element calls POST /api/runtime/publications/{publishedFileId}/images using three actions: lookup, prepare, and finalize. This Runtime endpoint returns raw JSON, not the /api/v1 envelope. The browser PUTs the captured bytes only to the short-lived upload URL returned by prepare. Never construct storage paths yourself.
Requests include boardId, resolved revision, complete signature, endpoint, normalized settings, and renderKey. Prepare/finalize additionally include content sha256, sizeInBytes, and actual completed samples. The element computes these fields; integrations should normally use its storage flow instead of manufacturing recipes.
Storage is limited to 16 MiB per image. The server verifies permission, publication/signature, recipe hash, content checksum, image format and dimensions before activating an ImageVersion. Exact completed recipes reuse their existing image card. Failed/interrupted finalization does not activate an incomplete image; partial uploads or records may need normal housekeeping.
Existing images and custom endpoints
src is an explicit exact image URL. HTTP 404/410 triggers model fallback; authorization, network and decode failures remain errors. Existing src images are displayed, not copied into a board by store.
A custom same-origin imageEndpoint receives signature, PID, revision, render key and settings as query parameters. It must return {found:false} or {found:true,url,renderKey}. A returned render key must match the requested recipe. Do not point it at a legacy endpoint that ignores lighting or camera settings: that could return the wrong image. Use src for external exact-image URLs.
Events, memory and failure handling
| Event | Meaning |
|---|---|
load | Image ready; detail includes source, samples, stored, and optional cardId |
progress | Completed path-tracer samples and requested minimum/maximum |
error | Lookup, signature, asset, lighting, rendering or decoding failed |
stored | Board storage finalized successfully |
storeerror | Persistence failed; the locally generated image can still display |
Model rendering is lazy-imported only on a miss. The runtime loads selected meshes, waits for materials and HDRI, captures the image, disposes the scene and WebGL resources, then displays the decoded image. Input changes and removal cancel stale work. Some in-flight mesh requests may finish before their results are disposed.
One fallback render runs at a time per module instance. The browser cache is bounded to 64 entries / 32 MiB and includes credentials, endpoint, PID, resolved revision, signature and every normalized rendering setting. Cookie-only callers have an instance-private cache partition. clearImageCache() clears completed local captures. Storage is durable only after the stored confirmation, not merely after load.
Release checklist
- Deploy matching runtime, app route and backend versions; module availability alone does not enable storage.
- Verify the complete create/store/reload cycle on the authorized demo board.
- Test real published products for correct signature, selected geometry, materials and requested view; no Render Studio dependency is involved.
- Exercise upload failure, repeated requests, cancellation, unsupported GPU/material behavior and target browsers.
- Never log API keys or signed upload/download URLs.