Assets
Build CDN URLs for storefront brand assets, render them through `next/image`, and pass external image hosts (Cloudinary, Unsplash, merchant S3) through untouched. The SDK ships `assetUrl`, `isCimplifyAsset`, and `useImage`: pure functions; no network calls; SSR-safe.
The asset surface on the SDK is read-side only: building URLs for images you've already uploaded via cimplify assets upload. Customer-runtime uploads still go through client.uploads.upload(file).
assetUrl(path, opts?)
Pure URL builder. Prepends the CDN base for relative paths, passes absolute URLs through with the transform query contract appended.
import { assetUrl } from "@cimplify/sdk";
assetUrl("hero/main.jpg")
// "https://storefrontassetscdn.cimplify.io/hero/main.jpg"
assetUrl("hero/main.jpg", { w: 1200, format: "webp", quality: 80 })
// "https://storefrontassetscdn.cimplify.io/hero/main.jpg?w=1200&format=webp&quality=80"
assetUrl("hero/main.jpg", { base: "http://localhost:8787/storage" })
// "http://localhost:8787/storage/hero/main.jpg"
assetUrl("https://res.cloudinary.com/foo/bar.jpg")
// "https://res.cloudinary.com/foo/bar.jpg" (absolute → passthrough)Options
| Field | Type | Notes |
|---|---|---|
base | string | Override the CDN base. Defaults to DEFAULT_CDN_BASE_URL. |
w / h | number | Width / height in pixels (on-the-fly resizing) |
quality | number | 0–100 |
format | "auto" | "webp" | "avif" | "jpeg" | "auto" lets the CDN pick by Accept header |
The transform query is only meaningful when the URL terminates on the Cimplify storefront CDN (which supports on-the-fly resizing). For external hosts, unknown params are typically ignored; the image still loads at its original size.
isCimplifyAsset(src, base?)
Decides whether src is hosted on a Cimplify CDN. Used by the storefront's next/image loader to skip transforms for external URLs.
import { isCimplifyAsset } from "@cimplify/sdk";
isCimplifyAsset("hero/main.jpg") // true (relative → ours)
isCimplifyAsset("/img/seed/bakery/x.jpg") // true (dev mock passthrough)
isCimplifyAsset("https://storefrontassetscdn.cimplify.io/x.jpg") // true
isCimplifyAsset("https://cdn.cimplify.io/x.jpg") // true
isCimplifyAsset("https://static-tmp.cimplify.io/seed/x.jpg") // true
isCimplifyAsset("https://res.cloudinary.com/demo/upload/x.jpg") // false
isCimplifyAsset("https://images.unsplash.com/photo-xyz") // falseBuilt-in next/image loader
Every storefront template scaffolded by cimplify init ships lib/cimplify-loader.ts and points images.loaderFile at it. The loader:
import type { ImageLoader } from "next/image";
import { assetUrl, isCimplifyAsset } from "@cimplify/sdk";
const cdnBase = process.env.NEXT_PUBLIC_CIMPLIFY_CDN_URL?.trim() || undefined;
const cimplifyImageLoader: ImageLoader = ({ src, width, quality }) => {
if (isCimplifyAsset(src, cdnBase)) {
return assetUrl(src, { base: cdnBase, w: width, quality, format: "auto" });
}
return src;
};
export default cimplifyImageLoader;Cloudinary URLs from client.catalogue.getProducts() flow through untouched. Cimplify-hosted URLs get the transform query. The result: every <Image> works regardless of where its asset lives, and Cimplify-hosted ones get edge-optimized.
To point the loader at a different CDN (for testing, multi-CDN setups, etc.) set NEXT_PUBLIC_CIMPLIFY_CDN_URL in your .env.local:
NEXT_PUBLIC_CIMPLIFY_CDN_URL=http://localhost:8787/storageuseImage(path, opts?) (React)
Thin hook that returns { src, loader } for <Image>:
import Image from "next/image";
import { useImage } from "@cimplify/sdk/react";
export function Hero() {
const { src, loader } = useImage("hero/main.jpg", { format: "webp", quality: 85 });
return <Image src={src} loader={loader} alt="..." width={1200} height={800} />;
}If images.loaderFile is already set globally in your next.config.ts, you typically don't need useImage; just <Image src={assetUrl("hero/main.jpg")} /> works. useImage is useful when you want per-component transform overrides on a project that doesn't use a global loader.
Options
| Field | Notes |
|---|---|
base | Per-call CDN base override |
w, h | Default transform values; per-image width from <Image> still wins |
format, quality | Default transform values |
useImage is useMemo-stable across renders when the path + opts don't change.
Constants
import { DEFAULT_CDN_BASE_URL, CIMPLIFY_CDN_HOSTS } from "@cimplify/sdk";
DEFAULT_CDN_BASE_URL // "https://storefrontassetscdn.cimplify.io"
CIMPLIFY_CDN_HOSTS // readonly ["storefrontassetscdn.cimplify.io", "cdn.cimplify.io", "static-tmp.cimplify.io"]What's not in v1
useUploadhook: runtime customer-facing uploads with progress + cancel. Deferred to v1.1. Customer uploads today go throughclient.uploads.upload(file)(no progress, no cancel; justawait).SEED_IDStyped const tree: demo-only convenience for referencing seed-image slugs in code. Generate-from-seed-source step deferred to v1.1; today demos useseedImage(industry, slug)from the SDK's mock module.- Cloudinary / S3 path-transform support: the loader passes external hosts through unchanged; Cloudinary's
c_fill,w_500/path transforms aren't synthesized. assets rmserver-side delete: CLI removes manifest entries; the remote blob stays until v1.1's media-managerDELETEwiring.
Where it lives in the platform
- Wire format:
POST /v1/businesses/{id}/assets/{init,confirm}; see the management API reference - Backend service:
crate::uploads::service::UploadService::init_storefront_asset - Served from the Cimplify asset CDN at
storefrontassetscdn.cimplify.io - Storage key:
assets/{business_id}/{folder}/{filename}: deterministic, idempotent, agent-predictable
Related
cimplify assets: CLI surface for upload/ls/rm- Uploads (customer-runtime):
client.uploads.upload(file)for private 7-day-presigned uploads
Uploads
Three-step direct-to-storage upload: `init` hands you a presigned URL, ` PUT` the bytes, then `confirm` commits the upload. `upload(file)` is the one-call sugar that runs the whole sequence for you.
Support
Customer-side chat conversation. The server resolves the active conversation from the widget identity on every request; there is no `conversation_id` to thread through. Open, send, and poll.