# Images and fonts

> Load Fabric.js images and fonts reliably: check every image before loading, load each font family first, upload local images and fix CORS issues.

Source: https://fabricjs-document-engine.jscrate.dev/docs/guides/assets-and-fonts
Last updated: 2026-09-28

Fabric.js images and fonts are the most common reason a saved document looks wrong when it is opened again. An image URL expired, a font was not loaded yet, or a picture only existed in the old tab. The engine checks all of this for you.

## The asset manifest

Every saved document lists the images and fonts it needs, with the ids of the objects that use them:

```ts
const manifest = engine.getAssetManifest();
// { images: [{ url, objectIds }], fonts: [{ family, weight, style, objectIds }] }
```

Images embedded as `data:` URLs are left out, because they need no fetching.

## Configure the checks

```ts
const engine = createDocumentEngine({
  canvas,
  storage,
  assets: {
    resolveUrl: (url) => url.replace("asset://", "https://cdn.example.com/"),
    replaceMissingImage: () => "/placeholder.png",
    upload: async ({ blob }) => uploadToYourBucket(blob),
    loadFont: async ({ family, weight, style }) => {
      const face = new FontFace(
        family,
        `url(/fonts/${family}-${weight}.woff2)`,
        {
          weight,
          style,
        }
      );
      document.fonts.add(await face.load());
    },
    requireFonts: false,
  },
});
```

## When a document is opened

1. `resolveUrl` can rewrite each stored URL, for example to sign it or to map ids to a CDN.
2. `loadFont` runs for each font family and weight. The engine then checks the font really renders, instead of falling back quietly.
3. Every image loads in parallel. For each missing image, `replaceMissingImage` can return a new URL, or `null` to leave it missing.
4. If images are still missing, loading fails with `MISSING_ASSETS`. `error.missingAssets` lists each `{ url, objectIds }`, and the canvas is not touched.

A font that cannot load gives a `FONT_UNAVAILABLE` warning and the text uses a fallback font. Set `requireFonts: true` to fail with `MISSING_FONTS` instead.

## When a document is saved

Images that exist only in this tab (`blob:` URLs) and embedded `data:` images are passed to `upload` once. The document stores the returned URL. Without an `upload` handler, `blob:` images give an `ASSET_NOT_PORTABLE` warning, because another device cannot open them.

## CORS and export

An image from another site, loaded without `crossOrigin: "anonymous"`, taints the canvas, and a PNG export fails. The engine warns with `IMAGE_CROSS_ORIGIN` so you can fix it early. Serve the image with an `Access-Control-Allow-Origin` header and load it with `crossOrigin: "anonymous"`.

## Check and replace at any time

```ts
const report = await engine.checkAssets();
report.missingImages;
report.unavailableFonts;

await engine.replaceImage("/old-logo.png", "/new-logo.png");
```

`replaceImage` swaps every image with that URL. Each keeps its size on the page, and the change is one undo step. That makes it easy to fix Fabric.js images and fonts after a user reports a problem.
