Plugin SDK > Asset sources

Asset sources

By default, to add new assets to the Media Area through the interface, you can upload files from your computer. But plugins can define custom asset sources to allow contributors to upload assets from external providers.

For example, the Unsplash plugin in our Marketplace allows to upload royalty-free high-resolution images:

Define custom asset sources

Within a plugin you can define the assetSources hook to expose new asset sources. Every source must specify an internal ID, and a name and a representative icon that will be shown in the interface.

import { connect } from 'datocms-plugin-sdk';
connect({
assetSources() {
return [
{
id: 'unsplash',
name: 'Unsplash',
icon: {
type: 'svg',
viewBox: '0 0 448 512',
content:
'<path fill="currentColor" d="M448,230.17V480H0V230.17H141.13V355.09H306.87V230.17ZM306.87,32H141.13V156.91H306.87Z" class=""></path>',
},
modal: {
width: 'm',
},
},
];
},
});

Rendering the custom asset source

When the user selects the custom source, a modal will be opened with the size you specified, and the renderAssetSource hook will be called. Inside of this hook we initialize React and render a custom component called AssetBrowser, passing down as a prop the second ctx argument, which provides a series of information and methods for interacting with the main application:

import { connect } from 'datocms-plugin-sdk';
connect({
assetSources() {
return [{...}];
},
renderAssetSource(sourceId: string, ctx: RenderAssetSourceCtx) {
render(<AssetBrowser ctx={ctx} />);
},
});

As we just saw, a plugin might offer different asset sources, so we can use the sourceId argument to know which one we are requested to render, and write a specific React component for each of them.

import { Canvas, RenderAssetSourceCtx } from 'datocms-react-ui';
type PropTypes = {
ctx: RenderAssetSourceCtx;
};
function AssetBrowser({ ctx }: PropTypes) {
return (
<Canvas ctx={ctx}>
Hello from the sidebar!
</Canvas>
);
}
Always use the canvas!

It is important to wrap the content inside the Canvas component, so that the iframe will continuously auto-adjust its size based on the content we're rendering, and to give our app the look and feel of the DatoCMS web app.

We can use this component to render whatever we want. The important thing is to call the ctx.select method to communicate to the main DatoCMS app the selected asset URL:

import { ButtonLink } from 'datocms-react-ui';
function AssetBrowser({ ctx }: PropTypes) {
const handleSelect = () => {
ctx.select({
resource: {
url: 'https://unsplash.com/photos/yf8qPXQFDJE',
filename: `sky.jpg`,
},
});
}
return (
<Canvas ctx={ctx}>
<Button onClick={handleSelect}>Select</Button>
</Canvas>
);
}

If you're generating your asset on the fly (ie. by rendering on a canvas), instead of a regular URL you can also pass a base64-encoded data URI:

ctx.select({
resource: {
base64: 'data:image/png;base64,PD94bWwgd..',
filename: `generated-image.png`,
},
});

You can also optionally specify some metadata to associate with the newly created upload:

ctx.select({
resource: {
url:
'https://images.unsplash.com/photo-1416339306562-f3d12fefd36f',
filename: 'man-drinking-coffee.jpg',
},
copyright: 'Royalty free (Unsplash)',
author: 'Jeff Sheldon',
notes: 'A man drinking a coffee',
tags: ['man', 'coffee'],
});

Function Reference

renderAssetSource()

Context object

The following properties and methods are available in the ctx argument:

assetSources()

Return value

The function must return AssetSource[] | undefined.

Context object

The following properties and methods are available in the ctx argument: