Cloudinary

Cloudinary is a digital asset management platform with a broad feature set, including support for responsive image generation and url based image transformation. They also provide a powerful media library UI for managing assets, and tools for organizing your assets into a hierarchy.

The Cloudinary media library integration for Netlify CMS uses Cloudinary’s own media library interface within Netlify CMS. To get started, you’ll need a Cloudinary account and Netlify CMS 2.3.0 or greater.

Creating a Cloudinary Account

You can sign up for Cloudinary for free. Once you’re logged in, you’ll need to retrieve your Cloud name and API key from the upper left corner of the Cloudinary console.

Cloudinary console screenshot

Connecting Cloudinary to Netlify CMS

To use the Cloudinary media library within Netlify CMS, you’ll need to update your Netlify CMS configuration file with the information from your Cloudinary account:

media_library:
  name: cloudinary
  config:
    cloud_name: your_cloud_name
    api_key: your_api_key

Note: The user must be logged in to the Cloudinary account connected to the api_key used in your Netlify CMS configuration.

Note: The Netlify CMS media library extensions for Cloudinary are not included in netlify-cms-app. If you’re using netlify-cms-app, you’ll need to register the media libraries yourself.

Security Considerations

Although this setup exposes the cloud_name and api_key publicly via the /admin/config.yml endpoint, this information is not sensitive. Any integration of the Cloudinary media library requires this information to be exposed publicly. To use this library or use the restricted Cloudinary API endpoints, the user must have access to the Cloudinary account login details or the api_secret associated with the cloud_name and api_key.

Netlify CMS configuration options

The following options are specific to the Netlify CMS integration for Cloudinary:

  • output_filename_only: (default: false)
    By default, the value provided for a selected image is a complete URL for the asset on Cloudinary’s CDN. Setting output_filename_only to true will instead produce just the filename (e.g. image.jpg). This should be true if you will be directly embedding cloudinary transformation urls in page templates. Refer to Inserting Cloudinary URL in page templates.
  • use_transformations: (default: true)
    If true, uses derived url when available (the url will have image transformation segments included). Has no effect if output_filename_only is set to true.
  • use_secure_url: (default: true)
    Controls whether an http or https URL is provided. Has no effect if output_filename_only is set to true.

Cloudinary configuration options

The following options are used to configure the media library. All options are listed in Cloudinary’s media library documentation, but only options listed below are available or recommended for the Netlify CMS integration:

Authentication

  • cloud_name
  • api_key

Media library behavior

Image transformations

The Cloudinary integration allows images to be transformed in two ways: directly within Netlify CMS via Cloudinary’s Media Library, and separately from the CMS via Cloudinary’s dynamic URL’s by inserting cloudinary urls.

Transforming images via Media Library

If you transform and insert images from within the Cloudinary media library, the transformed image URL will be output by default. This gives the editor complete freedom to make changes to the image output. There are two ways to configure image transformation via media library – globally and per field. Global options will be overridden by field options.

Global configuration

Global configuration, which is meant to affect the Cloudinary widget at all times, can be provided as seen below, under the primary media_library property. Settings applied here will affect every instance of the Cloudinary widget.

# global
media_library:
  name: cloudinary
  output_filename_only: false
  config:
    default_transformations:
      - - fetch_format: auto
          width: 160
          quality: auto
          crop: scale

Field configuration

Configuration can also be provided for individual fields that use the media library. The structure is very similar to the global configuration, except the settings are added to an individual field. For example:

# field
fields: # The fields each document in this collection have
- label: 'Cover Image'
  name: 'image'
  widget: 'image'
  required: false
  tagname: ''
  media_library:
    config:
      default_transformations:
        - fetch_format: auto
          width: 300    
          quality: auto
          crop: fill
          effect: grayscale

Inserting Cloudinary URL in page templates

If you prefer to provide direction so that images are transformed in a specific way, or dynamically retrieve images based on viewport size, you can do so by providing your own base Cloudinary URL and only storing the asset filenames in your content:

  • Either globally or for specific fields, configure the Cloudinary extension to only output the asset filename
# global
media_library:
  name: cloudinary
  output_filename_only: true
# field
media_library:
  name: cloudinary
  output_filename_only: true
  • Provide a dynamic URL in the site template
{{! handlebars example }}
<img src="https://res.cloudinary.com/<cloud_name>/<resource_type>/<type>/<transformations>/{{image}}"/>

Your dynamic URL can be formed conditionally to provide any desired transformations – please see Cloudinary’s image transformation reference for available transformations.

Bitbucket Backend

For repositories stored on Bitbucket, the bitbucket backend allows CMS users to log in directly with their Bitbucket account. Note that all users must have write access to your content repository for this to work.

To enable it:

  1. Follow the authentication provider setup steps in the Netlify docs.
  2. Add the following lines to your Netlify CMS config.yml file:
    backend:
      name: bitbucket
      repo: owner-name/repo-name # Path to your Bitbucket repository

Client-Side Implicit Grant (Bitbucket)

With Bitbucket’s Implicit Grant, users can authenticate with Bitbucket directly from the client. To do this:

  1. Follow the Atlassian docs to create an OAuth consumer. Make sure you allow Account/Read and Repository/Write permissions. To use the Editorial Workflow, allow PullRequests/Write permissions. For the Callback URL, enter the address where you access Netlify CMS, for example, https://www.mysite.com/admin/.
  2. Bitbucket gives you a Key. Copy this Key and enter it in your Netlify CMS config.yml file, along with the following settings:
    backend:
      name: bitbucket
      repo: owner-name/repo-name
      branch: default
      auth_type: implicit
      app_id: # The Key from your Bitbucket settings

Warning: With Bitbucket implicit grant, the authentication is valid for 1 hour only. After that, the user has to login again, which can lead to data loss if the expiration occurs while content is being edited.

Netlify CMS 2.4.0 brings deploy preview links!

Netlify CMS 2.4.0 brings deploy preview links!

Seeing is believing

The editorial workflow allows editors to create draft content in Netlify CMS, and Netlify can provide deploy previews of draft content, but there hasn’t been a way to access links to these preview builds from within Netlify CMS. The preview pane in the editor is a good tool for seeing how content will look on the site, but in the words of Marvin Gaye, “ain’t nothing like the real thing!” As Mr. Gaye bemoaned the absence of his beloved, so content creators long for the warm embrace of an actual production build. Their words, not ours.

Solution: GitHub Statuses

For sites using the GitHub (or Git Gateway with GitHub) backend, we now have deploy preview links in the CMS using the GitHub Statuses API. Many static sites already have continuous deployment and deploy previews configured on their repo, and they often use statuses to provide a link to a deployment directly from a commit or pull request. To retrieve a commit status that provides a deploy preview URL, we check for a status whose “context” contains one of a list of keywords commonly associated with deploy previews.

If a status is not found, nothing happens in the UI. If a status is found, but the deploy preview isn’t ready, we provide a “Check for Preview” link, allowing the content editor to manually check back until the preview is ready:

When the preview is ready, the “Check for Preview” button is replaced with a link to the content:

Deploy preview links generally direct to the root of a site, but Netlify CMS can also link straight to the piece of content being edited. By providing a string template for each collection, you can get links that go right where editors expect them to. More complex URL’s can be constructed using date information from your content files.

Unpublished vs. published

If you’re not using the editorial workflow, you may not feel you need this very much. Whenever you save content, it’s immediatlely published, so you can navigate to your live site to see the changes. That said, it’s at least convenient to have a link direct to your content from the CMS, so deploy preview links can also work for CMS installs that do not use the editorial workflow. Instead of retrieving a URL from a commit status, this functionality requires setting a site_url in your config, and that URL is used in place of the deploy preview URL.

GitLab and Bitbucket

Support is coming soon for these two awesome backends! Stay tuned.

Try it out!

Deploy preview links are live in Netlify CMS 2.4.0. Please give them a try and let us know if you have any problems by opening an issue or reaching out in our community chat!

Netlify CMS now supports GitLab as a backend

Netlify CMS is releasing support for GitLab as a backend, creating the world’s first completely open source stack for Git-based content editing.

We heard you (and you, and you, and you)! While you want to use Netlify CMS as the headless content management system for your Jamstack projects, all of your code lives in GitLab. Our long-term vision is to be tool-agnostic so you can use whatever tool helps you work best. But while you can already use Netlify CMS with most static site generators, backend support was limited to GitHub.

Immediately after the December release of Netlify CMS 1.0, contributors got to work on improving the API for backend integrations. At the urging of the community, we prioritized support for GitLab. With today’s release of Netlify CMS 1.9.0, you can now use GitLab as the backend for Netlify CMS.

Adding support for GitLab means that millions more developers can now use Netlify CMS with their projects. Seriously — millions. GitLab is used by more than 100,000 organizations like Ticketmaster, Intel, Red Hat, and CERN.

How it works

Netlify CMS is an open source content management system for your Git workflow that enables you to provide editors with a friendly UI and intuitive workflow. You can use it with any static site generator to create faster, more flexible web projects. Content is stored in your GitLab repository alongside your code for easier versioning, multi-channel publishing, and the option to handle content updates directly in Git.

In case you want an even easier way to get started, or just want to poke around in the code, you can use the button below to automatically deploy a starter site that uses the Hugo static site generator along with Netlify CMS.

Lastly, one particularly exciting thing about using GitLab as your backend is that it doesn’t require an authentication server. While the GitHub integration requires a hop to an authentication server (something Netlify provides for most users), GitLab’s implicit auth flow allows you to connect directly from your browser to gitlab.com, or even to your own self-hosted GitLab server!

What’s next

We’re already working toward Bitbucket support and will be releasing it as soon as possible! We’re also focused on the upcoming release of Netlify CMS 2.0, which will bring new image handling features and improvements, and improved APIs for better CMS extensions. We’re also looking for more ideas and helping hands, so if you’re keen to build a smarter, safer, and more scalable CMS, we’d love your contributions. Give us a shout on Twitter or in community chat if you have questions or ideas.

Jekyll

Introduction

This section will help you integrate Netlify CMS with a new or existing Jekyll project.

Jekyll is a blog-aware static site generator built with Ruby. Github Pages are powered by Jekyll, making it a popular choice for developer blogs and project pages.

If you’re starting a new project, the fastest route to publishing on a Jekyll website with Netlify CMS is to deploy a template on Netlify.

Setup

This guide will use the blog you get if you follow the really excellent official Jekyll step by step tutorial as a starting point. If you’re new to Jekyll – I recommended you start by following the tutorial so you know your way around your new blog. Otherwise you can clone this repo and checkout the without-cms branch.

Add Netlify CMS

Add admin/index.html

Create a file admin/index.html in the root of your repo – it should look like this:

<!-- admin/index.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Content Manager</title>
    <!-- Include the identity widget -->
    <script src="https://identity.netlify.com/v1/netlify-identity-widget.js" type="text/javascript"></script>
  </head>
  <body>
    <!-- Include the script that builds the page and powers Netlify CMS -->
    <script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script>
  </body>
</html>

Add admin/config.yml

Create a file admin/config.yml in the root of your repo – it should look like this:

# config.yml

backend:
  name: git-gateway
  branch: main # Branch to update (optional; defaults to master)
media_folder: 'assets/uploads'
collections:
  - name: 'blog'
    label: 'Blog'
    folder: '_posts/'
    fields:
      - { name: Title }

Enable authentication for CMS users

Netlify CMS stores content in your online Git repository. Therefore, to make content changes, users need to authenticate with the corresponding Git provider to prove that they have read and write access to that content.

Follow the directions in the Introduction section to enable Netlify Identity and Git Gateway services for the backend, then add the Identity widget to render a login portal on the frontend.

CMS Configuration

Blog Collection

We’ll start by updating the blog collection. Blogging is baked into Jekyll, and the _posts/ directory uses some special conventions we’ll need to keep in mind as we configure Netlify CMS. Copy and paste the following into your config.yml.

collections:
  - name: 'blog'
    label: 'Blog'
    folder: '_posts/'
    create: true
    slug: '{{year}}-{{month}}-{{day}}-{{slug}}'
    editor:
      preview: false
    fields:
      - { label: 'Layout', name: 'layout', widget: 'hidden', default: 'post' }
      - { label: 'Title', name: 'title', widget: 'string' }
      - { label: 'Publish Date', name: 'date', widget: 'datetime' }
      - { label: 'Body', name: 'body', widget: 'markdown' }

A few things to note.

  • We set the slug to '{{year}}-{{month}}-{{day}}-{{slug}}' because Jekyll requires this format for blog posts. year, month, and day will be extracted from the date field, and slug will be generated from the title field.
  • We added editor configuration with a field preview: false. This will eliminate the preview pane. Because Jekyll uses Liquid templates, there currently isn’t a good way to provide a preview of pages as you update the content.
  • The layout field default is set to post so Jekyll knows to use _layouts/post.html when it renders a post. This field is hidden because we want all posts to use the same layout.
  • The date and title field will be used by the slug – as noted above, Jekyll relies on the filename to determine a post’s publish date, but Netlify CMS does not pull date information from the filename and requires a frontmatter date field. Note Changing the date or title fields in Netlify CMS will not update the filename. This has a few implications:
    • If you change the date or title fields in Netlify CMS, Jekyll won’t notice
    • You don’t necessarily need to change the date and title fields for existing posts, but if you don’t the filenames and frontmatter will disagree in a way that might be confusing
    • If you want to avoid these issues, use a regular Jekyll collection instead of the special _posts directory

Author Collection

In addition to _posts, the Jekyll tutorial blog includes a collection of authors in the _authors directory. Before we can configure Netlify CMS to work with the authors collection, we’ll need to make a couple tweaks to our Jekyll blog. Here’s the front matter for one of the authors.

short_name: jill
name: Jill Smith
position: Chief Editor

name has special meaning as a unique identifier in Netlify CMS, but as set up now our Jekyll blog is using short_name as the unique identifier for authors. For each author, update the frontmatter like so.

name: jill
display_name: Jill Smith
position: Chief Editor

then update _layouts/author.html, _layouts/post.html and staff.html accordingly.

<!-- _layouts/author.html -->
--- layout: default ---

<h1>{{ page.display_name }}</h1>
<h2>{{ page.position }}</h2>

{{ content }}

<h2>Posts</h2>
<ul>
  {% assign filtered_posts = site.posts | where: 'author', page.name %} {% for post in
  filtered_posts %}
  <li>
    <a href="{{ site.baseurl }}{{ post.url }}">{{ post.title }}</a>
  </li>
  {% endfor %}
</ul>
<!-- _layouts/post.html -->
--- layout: default ---

<h1>{{ page.title }}</h1>

<p>
  {{ page.date | date_to_string }} {% assign author = site.authors | where: 'name', page.author |
  first %} {% if author %} - <a href="{{ author.url }}">{{ author.display_name }}</a>
  {% endif %}
</p>

{{ content }}
<!-- staff.html -->
--- layout: default ---

<h1>Staff</h1>

<ul>
  {% for author in site.authors %}
  <li>
    <h2>
      <a href="{{ site.baseurl }}{{ author.url }}">{{ author.display_name }}</a>
    </h2>
    <h3>{{ author.position }}</h3>
    <p>{{ author.content | markdownify }}</p>
  </li>
  {% endfor %}
</ul>

Next, copy and paste the following into the collections array in config.yml below the blog collection.

- name: 'authors'
  label: 'Authors'
  folder: '_authors/'
  create: true
  editor:
    preview: false
  fields:
    - { label: 'Layout', name: 'layout', widget: 'hidden', default: 'author' }
    - { label: 'Short Name', name: 'name', widget: 'string' }
    - { label: 'Display Name', name: 'display_name', widget: 'string' }
    - { label: 'Position', name: 'position', widget: 'string' }
    - { label: 'Body', name: 'body', widget: 'markdown' }

Now that we have the authors collection configured, we can add an author field to the blog collection. We’ll use the relation widget to define the relationship between blog posts and authors.

# updated fields in blog collection configuration
fields:
  - { label: 'Layout', name: 'layout', widget: 'hidden', default: 'post' }
  - { label: 'Title', name: 'title', widget: 'string' }
  - { label: 'Publish Date', name: 'date', widget: 'datetime' }
  - {
      label: 'Author',
      name: 'author',
      widget: 'relation',
      collection: 'authors',
      display_fields: [display_name],
      search_fields: [display_name],
      value_field: 'name',
    }
  - { label: 'Body', name: 'body', widget: 'markdown' }

With that configuration added, you should be able to select the author for a post from a dropdown.

About Page

Our Jekyll blog includes an About page. It would nice to be able to edit that page just like we can edit our blog and author pages. Netlify CMS provides file collections to solve this problem.

Copy and paste the following into the collections array in config.yml

- name: 'pages'
  label: 'Pages'
  editor:
    preview: false
  files:
    - label: 'About Page'
      name: 'about'
      file: 'about.md'
      fields:
        - { label: 'Title', name: 'title', widget: 'hidden', default: 'about' }
        - { label: 'Layout', name: 'layout', widget: 'hidden', default: 'about' }
        - { label: 'Body', name: 'body', widget: 'markdown' }

The last aspect of our Jekyll blog we might want to bring under the control of Netlify CMS is our Navigation menu. Our Jekyll tutorial blog has a file _data/navigation.yml that defines the links rendered by _includes/navigation.html. It looks like this.

# _data/navigation.yml
- name: Home
  link: /
- name: About
  link: /about.html
- name: Blog
  link: /blog.html
- name: Staff
  link: /staff.html

To make this file editable with Netlify CMS, we’ll need to make one minor tweak. The issue is this file contains a yaml array at the top level, but Netlify CMS is designed to work with yaml objects. Update _data/navigation.yml so it looks like so.

# _data/navigation.yml
items:
  - name: Home
    link: /
  - name: About
    link: /about.html
  - name: Blog
    link: /blog.html
  - name: Staff
    link: /staff.html

You’ll need to update _includes/navigation.html accordingly. {% for item in site.data.navigation %} should be changed to {% for item in site.data.navigation.items %}. When you’re done, the nav html should look like this.

<nav>
  {% for item in site.data.navigation.items %}
    <a href="{{ site.baseurl }}{{ item.link }}" {% if page.url == item.link %}style="color: red;"{% endif %}>
      {{ item.name }}
    </a>
  {% endfor %}
</nav>

Finally, add the following to the collections array in config.yml

- name: 'config'
  label: 'Config'
  editor:
    preview: false
  files:
    - label: 'Navigation'
      name: 'navigation'
      file: '_data/navigation.yml'
      fields:
        - label: 'Navigation Items'
          name: 'items'
          widget: 'list'
          fields:
            - { label: Name, name: name, widget: string }
            - { label: Link, name: link, widget: string }

Now you can add, rename, and rearrange the navigation items on your blog.