Product Updates

DatoCMS changelog for new features and general improvements
NewUI Improvement
Introducing duplicate asset detection in Media Area
August 2nd, 2021

Another day, another improvement to DatoCMS!

Building up from our recent addition of MD5 metadata to assets, we can now warn the user when there's an asset in the Media Area with the same signature as the file they're trying to upload:

NewUI Improvement
Introducing Quick Search!
July 30th, 2021

Today we're really happy to announce a small, nifty addition that we're sure a lot of people will find useful! We called it Quick Search, and it allows to find all records matching a specific criteria around your whole project.

You can launch Quick Search using the little "magnifying glass" icon that's always present at the top-right or, even faster, using the ⌘+P (or Ctrl+P) keyboard shortcut:

UI Improvement
Navigate through record links!
July 29th, 2021

Small, great addition today. You can now see which records point to the current record via Link fields! Some plugins were already available to perform the same job, but the need is so common that we decided to add it everywhere 😉

UI ImprovementContent Management APIContent Delivery API
Search assets in the Media Area with MD5 hashes!
July 28th, 2021

This is a nice addition to the Media Area: you can now see the MD5 hash of any asset you upload to DatoCMS. You can also search for MD5 in your Media Area, to see if the same asset is already present!

This is especially useful in automated scripts: the same information/query is also available both on our Content Management API and Content Delivery API:

Docs, Guides and Demos
Updated the plugin generator!
July 26th, 2021

This was long overdue, but we finally found some time to update our Yeoman Plugin generator to make use of the latest React version, and improved the default React skeleton with hooks!

npm update -g generator-datocms-plugin
More control for webhooks
July 26th, 2021

We made some improvements to webhooks! You can now "pause" webhooks by temporarly disabling them, and use Mustache templates not only to compose a custom HTTP payload, but also to personalize the URL:

Sort records by field
July 5th, 2021

You can now change the sort order of the records by the field of your choice:

Top streamed assets and optional IP tracking
July 2nd, 2021

You can now see the top videos by streaming time in the "Project usages":

Another change in the tracking area is related to the IP address tracking.

You can now disable the IP tracking in the projects settings:

Content Management APINew
Splitted a couple of permissions to make them more granular
June 7th, 2021

With today's update, we decided to split two permissions in order to give you a more fine grained permission system.

Environment permissions

The Create/edit models, plugins and customize content navigation bar environment permission has been splitted in two separate ones: Create/edit models and plugins and Customize content navigation bar.

That's the before and after:

Assets permissions

The Edit metadata/replace assets permission for assets has received the same treatment, and you can now control the two actions separately:

What happened to existing roles in my project?

This change did not alter what your users were already able to do, or not to do. For instance, if an existing role had the ability to "Create/edit models, plugins and customize content navigation bar", the same role is now be able to "Create/edit models and plugins" and "Customize content navigation bar".

NewUI Improvement
More fine grained controls on publishing/unpublishing of linked records
May 6th, 2021

It's no doubt that having a strongly linked content schema helps you find the information you need, when you need it. But what happens when we attempt to (un)publish or delete interconnected resources?

Most CMSs are terrible at handling this sort of thing. Contentful for example simply leaves a ghost references to a records that no longer exists, and calls it a day. Their philosophy seems to be "users will take care of filtering this garbage somehow on the frontend, not our problem!".

What distinguishes us the most from competition is a greater care in keeping the saved contents coherent and always consistent. It is our problem to ensure that, not yours. You've better things to do.

Today, we're happy to introduce additional settings that allow you to specify exactly what behavior to adopt when such events occur. And since different settings may make sense depending on the specific context, you can specify different behaviours for every Link, Links and Structured Text in your project.

If you have ever worked with databases, you will surely notice a similarity with the DELETE CASCADE settings that you can set on the foreign keys of a table:

With this change, editors won't have to guess the right pattern to solve intricate cases of dependencies between records, since the developers have already taken care of that for them. And scheduled publish/unpublish operations will be much more secure and deterministic than before.

The default settings you'll find in the existing fields are the ones that were in place until now, so don't worry, nothing will change unless you decide to do so.

If you want to massively change these settings, you can conveniently do so via the Content Management API and migrations.

In this example, we're changing settings for every Link, Links and Structured field in a project, so that when a publishing is requested and a field references some unpublished records, the resolution strategy is to also publish the referenced records:

module.exports = async (client) => {
const itemTypes = await client.itemTypes.all();
for (const itemType of itemTypes) {
const fields = await client.fields.all(;
const interestingFields = fields.filter((f) =>
['link', 'links', 'structured_text'].includes(f.fieldType),
for (const field of interestingFields) {
const validatorFor =
field.fieldType === 'link'
? 'itemItemType'
: field.fieldType === 'links'
? 'itemsItemType'
: 'structuredTextLinks';
if (
.onPublishWithUnpublishedReferencesStrategy !== 'publish_references'
) {
await client.fields.update(, {
validators: {
[validatorFor]: {
« PreviousNext »