Skip to content
Twilight React Playground
ثيم رائدaren

asset, cdn, isPlaceholder

functionBeginnerserverbrowserlive demo

Build URLs for your theme's own files and for Salla's asset CDN, as plain functions you can call outside components.

import { asset, cdn, isPlaceholder } from '@salla.sa/twilight-theme-engine/utils';

In plain words

useAsset() hands these three functions to components. Imported directly, they also work where a hook cannot be called: a route's head() function, a loader, or a plain helper file.

asset('images/logo.png') returns /assets/images/logo.png, a file your theme serves. cdn('images/og.jpg', 1200, 630) returns an address on https://cdn.assets.salla.network that asks for the image scaled to fit 1200 by 630 pixels.

Signature

function asset(path: string): string
function cdn(url: string | null | undefined, width?: number, height?: number): string
function isPlaceholder(url: string | null | undefined): boolean

Try it live

The same value through the plain URL helpers. They are functions, not hooks, so they work in a head() or a loader too.Try this: pick the product photo: cdn() hands it back untouched, while getCdnImageUrl() resizes it. Then pick the http:// URL and the empty value.
Storefront canvas · en · LTR
asset(value)
"/assets/images/og-cover.jpg"
cdn(value)
"https://cdn.assets.salla.network/images/og-cover.jpg"
cdn(value, width)
"https://cdn.assets.salla.network/cdn-cgi/image/fit=scale-down,width=1200,onerror=redirect,format=auto/images/og-cover.jpg"
getCdnImageUrl(value, { width })
"images/og-cover.jpg"
Controls
0 means not set.
What a theme writes
import { cdn } from '@salla.sa/twilight-theme-engine/utils';
import type { HeadDescriptor } from '@salla.sa/twilight-theme-engine/utils/head';

// A head() runs outside components, so it cannot call useAsset().
export function aboutHead(): HeadDescriptor {
  return {
    title: 'About us',
    openGraph: { images: cdn('images/og-cover.jpg', 1200) },
  };
}

Example

app/routes/about.head.ts
import { asset, cdn } from '@salla.sa/twilight-theme-engine/utils';
import type { HeadDescriptor } from '@salla.sa/twilight-theme-engine/utils/head';

export function aboutHead(): HeadDescriptor {
  return {
    title: 'About us',
    // Social networks need an absolute image URL: cdn() gives one.
    openGraph: { images: cdn('images/about-og.jpg', 1200, 630) },
    links: [{ rel: 'preload', as: 'image', href: asset('images/about-hero.webp') }],
  };
}

How it behaves

  • asset(path) removes leading slashes and returns the root-relative /assets/<path>.

  • cdn(path) returns https://cdn.assets.salla.network/<path>. With a width or a height it returns https://cdn.assets.salla.network/cdn-cgi/image/fit=scale-down,width=W,height=H,onerror=redirect,format=auto/<path>, leaving out the size that is not given.

  • Both add ?v=<VITE_TWILIGHT_VERSION> when that build-time variable is set, and nothing otherwise.

  • They are the same functions useAsset() returns; the hook adds no state.

Gotchas

  • cdn() returns any URL that starts with https:// unchanged and ignores the sizes. Images from the Salla API (products, categories, the store logo) are such URLs, so cdn(product.image.url, 400) downloads the full file. Resize those with getCdnImageUrl.

  • Only https:// counts as a full URL. http://example.com/a.jpg and //example.com/a.jpg are appended to the CDN origin and become broken addresses.

  • cdn(null), cdn(undefined) and cdn('') return the bare https://cdn.assets.salla.network, which is not an image. Check for a missing URL first.

  • isPlaceholder() always returns false: the placeholder URL it compares with is hard-coded to null in src/utils/asset.ts. docs/02-theme-engine-core.md describes it as a working check.

  • Importing @salla.sa/twilight-theme-engine/utils outside Vite (a plain Node script) throws Cannot read properties of undefined (reading 'VITE_TWILIGHT_VERSION'): asset.ts reads import.meta.env when the module loads. Vite, Vitest and the server are fine; the /utils/head, /utils/baseHead and /utils/cdn-image subpaths load anywhere.

  • Two exports are called cdn: this function, and an HTTP client in @salla.sa/twilight-theme-engine/api/client. Check the import path.

Related

Source and docs