Theme assets and media
Ship images, fonts and icons in a theme's assets/ folder and name them from code, settings and CSS. Covers the size caps, the store's media library (media://), the media/* rules of the theme check and the code editor's asset tools.
On this page
A theme draws two kinds of pictures, and they live in different places:
| Kind | Owner | Where it lives | How a theme names it |
|---|---|---|---|
| Theme assets | The theme | The theme's assets/ folder, versioned with code | asset('images/hero.jpg') in code, asset://images/hero.jpg in settings |
| Store files | The store | The store's media library (Media library in the admin) | media://<id> in settings a merchant fills; never in code |
Assets travel with the theme: they are copied when the theme is duplicated, and installed with it. Store files belong to the store: a merchant uploads them once and uses them in every theme, product, email and page. Ship drawn pictures, patterns, icons and fonts as assets, and leave photos to the merchant. The shipped themes carry no photos.
The assets/ folder
Every binary file of a theme sits under assets/, in folders of your choice
(assets/images/hero.svg, assets/fonts/display.woff2). A binary file anywhere else is refused,
by the code editor, the CLI and theme install alike.
| Type | Extensions | Cap |
|---|---|---|
| Image | jpg, jpeg, png, webp, avif, gif | 5 MB a file; over 2 MB still installs, with a warning |
| Vector | svg | 256 KB; sanitized on the way in |
| Font | woff2 | 1 MB; other font formats are refused, convert to WOFF2 |
| Icon | ico | 5 MB; over 2 MB still installs, with a warning |
| Theme | everything under assets/ | 50 MB in total |
Sizes are binary: 1 MB is 1024 × 1024 bytes.
- A path is relative to
assets/, at most 256 characters, with letters and digits of any script plus.,_and-in each folder name; no leading dot, no spaces, and the file needs an extension. - The bytes are checked against the type: an image must decode as the type its extension names, a font and an icon must carry their file signature, and an SVG goes through the same sanitizer as the store's library (scripts, event handlers, external links and embedded rasters refuse the file).
- Each asset is stored once per store, by its content, so two themes with the same file share it and a duplicated theme copies only the reference.
Example assets
Every shipped theme carries one or two small examples under assets/images/. Each one is used,
so media/unused-asset stays quiet, and together they show the patterns:
backdrop.svg, a quiet still life in the theme's palette. It is theasset://images/backdrop.svgdefault of an image setting (the promo card of the default theme, the cover plate of Editorial, the feature image of Launch) and the value the home page starts with.hatch.svg, a hairline tile thaturl(asset:images/hatch.svg)lays under an empty image plate in the default, Editorial and Essential themes.
The files are drawn from plain SVG shapes, so there is no third-party artwork to license. A theme whose code you changed before these files shipped did not receive them. Delete them if you do not want them.
In code: asset()
import { MediaImage, asset } from '@poltura/theme-sdk/media';
export function Hero() {
return <MediaImage image={asset('images/hero.svg')} role='hero' alt='' />;
}| Function | Returns |
|---|---|
asset(path) | The reference asset://<path>, for any prop that takes a picture (MediaImage). Throws on a malformed path |
useAssetUrl(path, role?) | A URL: the role's rendition of an image, or the whole file without a role (always for SVG, fonts and icons). Null when the asset is missing |
useThemeAsset(path) | The resolved file (url, width, height, hasAlpha) or null. An asset has no alt text of its own |
Roles are the same as for library files: thumb, card, tile, pdp, zoom, hero, og,
logo and icon. MediaImage draws an asset the way it draws a library file: a <picture>
with AVIF and WebP where the role allows, srcset for high-density screens, and the stored width
and height so the layout does not shift.
The theme build writes an asset manifest into every built version of the theme: each
asset's path, hash, type, size, pixel size and URLs. A path missing from the manifest renders a
placeholder, never a broken image, and the check reports it (below). Write the path as a literal
where you can. An asset() call with a computed path is allowed, but it turns off the
unused-asset report for the whole theme.
media:// never appears in code. A store's file is something a merchant chooses, so it comes in
through a setting.
In settings and pages: asset://
Image settings, style backgrounds and every picture value of a page or layout JSON take a
reference: media://<id> for a store file the merchant picked, asset://<path> for a theme asset.
import { field } from '@poltura/theme-sdk/elements';
const settings = {
background: field.image({ label: 'Background', default: 'asset://patterns/dots.svg' }),
};An image setting may default to an asset, and only to an asset. A media:// reference or an
address as a default throws, because a theme cannot know a store's files and must not depend on
another host.
video settings take no default. In the Customizer a merchant replaces the default with a file of
their library; the reference they pick is what the setting stores.
In CSS: url(asset:…)
.hero {
background-image: url(asset:patterns/dots.svg);
}The theme build rewrites url(asset:<path>) (quotes optional, asset:// accepted too) to the
file's address on the store's /media/ path. A path that is not in assets/ fails the build with
the error code THEME_ASSET_MISSING. Write url(asset:…) without the slashes, because that is
the form the check reads.
The theme check: media/* rules
The CLI (poltura theme check), theme install and the code editor run the same rules. The
severity differs only where one of them knows less or where more is at stake:
| Rule | CLI / install / code editor | Reports |
|---|---|---|
media/no-remote-url | warning / error / warning | An http(s) address in a picture value. A shipped theme cannot depend on another host |
media/unsafe-url | error everywhere | javascript:, data: and similar in a picture or link value. An inline SVG data URL of up to 2048 characters is allowed in an <img> src |
media/unresolvable-path | error everywhere | A bare or rooted path nothing serves (/images/x.jpg, hero.jpg) or a malformed media:// / asset:// |
media/unknown-asset | error everywhere | An asset:// or asset('…') path with no file in assets/; suggests the nearest name |
media/unknown-media | warning (install and code editor) | A media:// id that is not in this store's library |
media/ref-in-code | error everywhere | media:// inside src/ |
media/image-alt | warning everywhere | An <img> of the theme's own without alt or decorative |
media/asset-size | warning over the budget, error over the cap | A file over its type's budget or cap, the 50 MB total, or a font that is not WOFF2 |
media/unused-asset | info everywhere | An asset nothing names |
The check's rule against placeholder addresses in text skips picture and link values. The
media/* rules judge an address there instead.
In the code editor
- The folder is always there.
assets/,assets/images/andassets/fonts/show in the Explorer for every theme, including one with no asset yet, and stay when their last file is deleted or moved: they are folders of the workspace, not placeholder files, and nothing about them is stored with the theme. - Assets are files. Drop images, SVG, fonts and icons from your computer into
assets/in the Explorer. Renaming or moving a file updates every reference to it and saves the files it changed. A file the folder cannot hold (bytes outsideassets/, over its cap, of another type) is refused with a notification that says why. - Previews. An image, font or icon under
assets/opens in a preview with its size, bytes and a Used in list. A font shows a specimen with sample text. Preview asset in the Explorer's context menu opens one, and an SVG file has a preview button in its editor title bar. - Media library. The Media library view (its own activity-bar icon) lists the
store's files by kind, with search. Drag a file into a JSON file to insert its
media://reference, or run Pick from the media library there. Upload to library adds a file to the store's library. Upload videos on the admin's Media library page. - Completion and hints. Typing
asset(',useAssetUrl(',useThemeAsset(',"asset://orurl(asset:lists the theme's assets, and"media://lists the store's images. Hovering a reference shows the file, and its link opens the preview. Inlay hints show the pixel size, the library file's name and alt text, or that a reference points at nothing. - Problems and quick fixes. After every save the full theme check runs and fills Problems
(source
poltura-check), with fixes where the rule has one: Use asset://… for a path a file inassets/matches, Did you mean asset://…?, Pick a file from the media library, Upload to the media library for a remote address, Add an image_alt setting and Remove this value.
Next
- Share images (Open Graph): templates for the image a shared link shows.
- media reference:
asset,MediaImage,useAssetUrlanduseThemeAsset.