Here’s how you can use Uploadcare images with Contentful CMS fields
TL;DR
Go to 📁 prezly/uploadcare-extension-for-contentful and follow the instructions.
The Why
At Prezly (the best PR software on the internet 😉) we use Uploadcare to upload and store all media assets that our users upload to use in their newsrooms.
We love Uploadcare, because they've got so much stuff done right: a great drop-in uploading widget you can easily link to any HTML page or React application, awesome on-the-fly image processing CDN and a very friendly support team. So it was a no-brained to try integrating it with Contentful CMS. We’ve recently started to use Contentful as a content backend for our marketing website.
Don’t get me wrong: Contentful has already a rather good on-the-fly Image Processing API, but the one from Uploadcare is faster, has more features, and also seems to have a wider CDN network. Moreover, we already have a large Uploadcare subscription, hosting 6.4TB of assets for our clients.
Unfortunately, there was no ready-made integration available. But luckily Contentful team has implemented a brilliant Extensions SDK. It allows you to customize Contentful content fields in virtually unlimited ways. Also, they claim their own standard fields are implemented using the Extensions API, which is impressive. “Eat your own dog food” principle in action! Good stuff!
It was surprizingly simple to implement it!
The Process
Input Field Extension
First, I’ve created a field extension to render the “Upload new image” button:
Clicking the button will open another extension, responsible for displaying the dialog. The code
itself is mostly just a wrapper for dialogs.openExtension()
(see Contentful Extension SDK documentation), plus some UI state
management: upload, edit, preview, delete. That’s it.
const DIALOG_EXTENSION_ID = '...'; // The ID of the dialog extension
window.contentfulExtension.init(function (api) {
async function openDialog(file = null) {
return await api.dialogs.openExtension({
id: DIALOG_EXTENSION_ID,
width: 900,
shouldCloseOnEscapePress: true,
shouldCloseOnOverlayClick: true,
parameters: {
file,
},
});
}
api.field.onValueChanged((file) => {
if (file) {
document.getElementById('image').src = `${file.cdnUrl}-/preview/`;
}
});
document.getElementById('upload').addEventListener('click', async function () {
const file = await openDialog();
api.field.setValue(file);
});
});
Sprinkle it with some CSS to mimic Contentful UI style (by just copying over CSS styles into the extension), and it immediately looks great. Like it has always been that way. Very native to Contentful!
File Upload Dialog Extension
Then I've created another Contentful Extension for the uploading dialog. It’s basically a wrapper
around the uploadcare.openDialog()
call. This extension is responsible for displaying the
Uploadcare Widget and communicating image JSON back to the image field.
const UPLOADCARE_PUBLIC_KEY = '...';
window.contentfulExtension.init(function(api) {
const settings = {
publicKey: UPLOADCARE_PUBLIC_KEY,
imagesOnly: true,
previewStep: true,
effects: 'crop,rotate,mirror,flip,enhance,sharp,blur,grayscale',
debugUploads: true,
crop: 'free',
};
function getUploadcareFile(fileInfo) { /* ... */ }
async function openDialog(fileInfo) {
const { file } = await getUploadcareFile(fileInfo);
const dialog = uploadcare.openDialog(file, settings);
dialog.done(function(uploadcareFile) {
uploadcareFile.done(fileInfo => api.close(fileInfo));
});
dialog.fail(function () {
api.close(fileInfo);
});
}
openDialog((api.parameters.invocation || {}).file);
});
The code above just opens a standard Uploadcare Widget like this one:
Configure Field Type
Now, when the extensions are ready, we can use them to change the appearance of a content field.
Just create a new field with JSON Object content type and switch it to using the Uploadcare Image Field extension (Appearance tab).
Packaged Installation
Alright, but is there a way to install it without re-implementing? Sure!
For your convenience, we’ve created a GitHub repository to host the code for these two extensions: 📁 prezly/uploadcare-extension-for-contentful
Luckily, you can skip all the boring steps of setting up extensions and copying and pasting source code. Just use Install from GitHub option with these two links:
-
https://github.com/prezly/uploadcare-extension-for-contentful/blob/master/uploadcare-image-dialog/extension.json To finish the installation of this extension you’ll need to provide your public Uploadcare API Key.
-
https://github.com/prezly/uploadcare-extension-for-contentful/blob/master/uploadcare-image-field/extension.json To finish the installation of this extension you’ll need to paste Extension ID you’ve created on the previous step (you can find it in the extension page URL).
See the detailed step-by-step instructions on GitHub: https://github.com/prezly/uploadcare-extension-for-contentful
The Conclusion
Often the tools you use aren't perfect for what you want to achieve with them.
As a developer I always appreciate when a tool isn't just a beautiful walled garden, but also is open for extending it, and integrating with other tools. This creates the so-called synergy effect, when a combination of multiple things is more than just a sum of their individual values.
Morale:
- don't be afraid to extend and combine the tools you're using
- avoid those, which you cannot extend or integrate with others (assuming you're a developer 😉)
- if you're building one of those tools and you want it to be popular, don't underestimate the power of being open to the ecosystem
Cheers! 🖖