Images
How to use images in Format Studio documents.
Referencing assets
There are two ways to load bitmap images, like jpg and png.
As a module import
As you might be used to in your existing React or Vue projects, you can import an asset as an ES Module, using an import statement.
documents
invoice
documents
invoice
From an assets directory
You can put assets in one of two places:
- A special directory called
assetsnested under each document - A user-defined
sharedAssetsDirthat all documents can see
shared-assets
documents
invoice
assets
{
"sharedAssetsDir": "./shared-assets"
}shared-assets
documents
invoice
assets
{
"sharedAssetsDir": "./shared-assets"
}shared-assets
documents
invoice
assets
{
"sharedAssetsDir": "./shared-assets"
}If there is a filename clash between these two, the document's assets directory wins.
You can use any directory structure inside an assets folder to organize assets.
shared-assets
brand
latest
documents
invoice
assets
layout
v1
import { Document, Layout } from '@format.dev/react'
export default function Invoice() {
return (
<Document title="Invoice">
<Layout id="invoice" width={793.71} height={1122.52}>
<img src='./layout/v1/banner.jpg' alt='Banner' />
<img src='./brand/latest/logo.png' alt='Acme logo' />
</Layout>
</Document>
)
}shared-assets
brand
latest
documents
invoice
assets
layout
v1
<script setup lang="ts">
import { Document, Layout } from '@format.dev/vue'
</script>
<template>
<Document title="Invoice">
<Layout id="invoice" :width="793.71" :height="1122.52">
<img src='./layout/v1/banner.jpg' alt='Banner' />
<img src='./brand/latest/logo.png' alt='Acme logo' />
</Layout>
</Document>
</template>shared-assets
brand
latest
documents
invoice
assets
layout
v1
SVGs
Building on the above, you can load SVGs in three ways, each with different trade-offs.
As an image
Reference an SVG from an assets directory using an <img> tag. The SVG is treated as a static image. You cannot style fill, stroke, or other SVG properties via CSS from outside the element. It is still rendered as a scalable vector.
documents
invoice
assets
<img src='./logo.svg' alt='Acme logo' /><img src='./logo.svg' alt='Acme logo' /><img src="./logo.svg" alt="Acme logo" />As a component
Import the .svg file as a module to use it as an inline component. The SVG markup is rendered directly into the HTML output, giving you full access to style fill, stroke, and other SVG properties via CSS.
Studio uses vite-plugin-svgr to transform SVG imports into React components.
Studio uses vite-svg-loader to transform SVG imports into Vue components.
Inline
Paste SVG markup directly into your template. This gives you the same benefits as the component approach, without needing a separate file.
import { Document, Layout } from '@format.dev/react'
export default function Invoice() {
return (
<Document title="Invoice">
<Layout id="invoice" width={793.71} height={1122.52}>
<svg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
<circle cx='12' cy='12' r='10' fill='#FF5A06' />
</svg>
</Layout>
</Document>
)
}<script setup lang="ts">
import { Document, Layout } from '@format.dev/vue'
</script>
<template>
<Document title="Invoice">
<Layout id="invoice" :width="793.71" :height="1122.52">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="10" fill="#FF5A06" />
</svg>
</Layout>
</Document>
</template><template data-type="document" data-title="Invoice">
<template data-type="layout" data-id="invoice" data-width="793.71px" data-height="1122.52px">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="10" fill="#FF5A06" />
</svg>
</template>
</template>Assets based on variable data
When you need to load a different assets based on the dynamic data within your document, you have a few choices:
<img src={data.theme === 'dark' ? 'logo-dark.png' : 'logo-light.png'} />Which is perfectly acceptable, but does assume that assuming that both logo-dark.png and logo-light.png are in one of your document asset directories. Both files would be zipped and be available at render time.
If, for example you were to load a variant where data.theme was set to dark in Studio and you didn't have logo-dark.png available, Studio will show a warning diagnostic, making it hard to miss.
However, in the case that don't have a variant that triggers logo-dark.png to be loaded, and logo-dark.png isn't present (and thus not zipped when you compile for production), you would get an AssetMismatchError at runtime. Still not catastrophic, as you can handle this error appropriately, but it's worth being aware of.
You could also use a module import, which would flag the issue much earlier:
import logoLight from './logo-light.png'
import logoDark from './logo-dark.png'
<img src={data.theme === 'dark' ? {logoDark} : logoLight} />If you need to use assets that are completely dynamic at runtime, for example user uploaded images, you should use Dynamic mode when running compile.