Hosted images
Upload user images to your own server with a TLAssetStore instead of storing them as data URLs.
import { TLAssetStore, Tldraw, uniqueId } from 'tldraw'
import 'tldraw/tldraw.css'
// [1]
const UPLOAD_URL = '/SOME_ENDPOINT'
// [2]
const myAssetStore: TLAssetStore = {
// [a]
async upload(asset, file) {
const id = uniqueId()
const objectName = `${id}-${file.name}`.replaceAll(/\W/g, '-')
const url = `${UPLOAD_URL}/${objectName}`
await fetch(url, {
method: 'POST',
body: file,
})
return { src: url }
},
// [b]
resolve(asset) {
return asset.props.src
},
}
// [3]
export default function HostedImagesExample() {
return (
<div className="tldraw__editor">
<Tldraw assets={myAssetStore} />
</div>
)
}
/*
By default, images and videos added to the editor are stored as data URLs inside the
document, which is fine for a demo but bloats the document quickly. A `TLAssetStore`
tells the editor to upload files somewhere and store only a URL.
[1]
A placeholder for your server's upload endpoint. This example doesn't actually have one,
so uploads here will fail; the point is the shape of the code.
[2]
The asset store.
[a] `upload` is called once when a file is added. It receives the asset record and the
`File`, and must return the URL (`src`) that will be saved in the asset's props.
[b] `resolve` is called whenever the editor needs to display the asset. Returning
`asset.props.src` is the default behavior, so this method could be omitted. Implement
it to rewrite the URL, for example to add an auth token or pick a resized variant
based on the `ctx` argument (screen scale, whether it's for export, etc).
[3]
Pass the store to the `assets` prop. From then on, drops, pastes, and the "Upload media"
menu item all go through it.
*/
Without an asset store, images and videos added to the canvas are inlined into the document as data URLs. A TLAssetStore passed to the assets prop takes over: its upload method sends each new file to your server and returns the URL to save, and its optional resolve method turns that saved URL into the one actually rendered, which is the place to add auth tokens or pick an optimized size.
The upload endpoint here is a placeholder, so this example won't actually store anything. It shows the code you'd write against your own backend.
Is this page helpful?
Prev
Export canvas as image (with settings)Next
Custom paste behavior