A CMS for static site generators. Give non-technical users a simple way to edit and add content to any site built with a static site generator.
Netlify CMS is released under the MIT License. Please make sure you understand its implications and guarantees.
How it works
Netlify CMS is a single-page app that you pull into the
/admin
part of your site.
It presents a clean UI for editing content stored in a Git repository.
You setup a YAML config to describe the content model of your site, and typically tweak the main layout of the CMS a bit to fit your own site.
When a user navigates to
/admin
she'll be prompted to login, and once authenticated she'll be able to create new content or edit existing content.Installing
Netlify CMS is a React app. To install it in your site, add an
/admin
folder in your public directory and use thisindex.html
as a template:<!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 stylesheets from your site here -->
<link rel="stylesheet" href="//cms.netlify.com/assets/main.css" />
<!-- Include a CMS specific stylesheet here -->
</head>
<body>
<script src="//cms.netlify.com/assets/main.js"></script>
</body>
</html>
Add a
config.yml
file to the /admin
folder and configure your content model:backend:
name: github-api
repo: owner/repo # Path to your Github repository
branch: master # Branch to update (master by default)
media_folder: "img/uploads" # Folder where user uploaded files should go
collections: # A list of collections the CMS should be able to edit
- name: "post" # Used in routes, ie.: /admin/collections/:slug/edit
label: "Post" # Used in the UI, ie.: "New Post"
folder: "_posts" # The path to the folder where the documents are stored
create: true # Allow users to create new documents in this collection
fields: # The fields each document in this collection have
- {label: "Title", name: "title", widget: "string", tagname: "h1"}
- {label: "Body", name: "body", widget: "markdown"}
- {label: "Foo", name: "foo", widget: "foo"}
meta: # Meta data fields. Just like fields, but without any preview element
- {label: "Publish Date", name: "date", widget: "datetime"}
- name: "settings"
label: "Settings"
files:
- name: "general"
label: "General settings"
file: "_settings/general.json"
fields:
- {label: "Main site title", name: "site_title", widget: "string"}
- {label: "Number of fronpage posts", name: "post_count", widget: "number"}
- {label: "Site cover image", name: "cover", widget: "image"}
Netlify CMS works with the concept of collections of documents that a user can edit.
Collections basically comes in three forms:
- A
folder
. Set thefolder
attribute on the collection. Each document will be a file in this folder. Each document will have the same format, fields and meta fields. - A list of
files
. Set thefiles
attribute on the collection. You can set fields that all files in the folder shares directly on the collection, and set specific fields for each file. This is great when you have files with a different structure. - A
file
. Warning, not implemented yet. This is a collection stored in a single file. Typically a YAML file or a CSV with an array of items.
Each collection has a list of fields (or files with their individual fields). Each field has a
label
, a name
and a widget
.
Setting up the right collections is the main part of integrating netlify CMS with your site. It's where you decide exactly what content editors can work with, and what widgets should be used to edit each field of your various files or content types.
GitHub as a Backend
The default Github-based authenticator integrates with Netlify's Authentication Provider feature and the repository backend integrates directly with Github's API.
To get everything hooked up, setup continuous deployment from Github to Netlify and then follow the documentationto setup Github as an authentication provider.
That's it, now you should be able to go to the
/admin
section of your site and log in.Media folder and Public folder
Most static file generators, except from Jekyll, don't keep the files that'll be copied into the build folder when generating in their root folder.
This can create a problem for image and file paths when uploaded through the CMS.
Use the
public_folder
setting in config.yml
to tell the CMS where the public folder is located in the sources. A typical Middleman setup would look like this:media_folder: "source/uploads" # Media files will be stored in the repo under source/uploads
public_folder: "source" # CMS now knows 'source' is the public folder and will strip this from the path
Widgets
Actual content editing happens with a side by side view where each
widget
has a control for editing and a preview to give the content editor an idea of how the content will look in the context of the published site.
Currently these widgets are built-in:
- string A basic text input
- markdown A markdown editor
- datetime A date and time input
- image An uploaded image
Extending Netlify CMS
The Netlify CMS exposes an
window.CMS
global object that you can use to register custom widgets, previews and editor plugins. The available methods are:- registerPreviewStyle Register a custom stylesheet to use on the preview pane.
- regsiterPreviewTemplate Registers a template for a collection.
- registerWidget lets you register a custom widget.
Writing React Components inline
Both regsiterPreviewTemplate and registerWidget requires you to provide a React component. If you have a build process in place for your project, it is possible to integrate webpack and Babel for a complete React build flow.
Although possible, it may be cumbersome or even impractical to add a React build phase. For this reason, Netlify CMS exposes two React constructs globally to allow you to create components inline: ‘createClass’ and ‘h’ (alias for React.createElement).
registerPreviewStyle
Register a custom stylesheet to use on the preview pane.
CMS.registerPreviewStyle(file);
Params:
- file: css file path.
Example:
CMS.registerPreviewStyle("/example.css");
regsiterPreviewTemplate
Registers a template for a collection.
CMS.registerPreviewTemplate(collection, react_component);
Params:
- collection: The name of the collection which this preview component will be used for.
- react_component: A React component that renders the collection data. Three props will be passed to your component during render:
- entry: Immutable collection containing the entry data.
- widgetFor: Returns the appropriate widget preview component for a given field.
- getMedia: Returns the correct filePath or in-memory preview for uploaded images.
Example:
<script>
var PostPreview = createClass({
render: function() {
var entry = this.props.entry;
var image = entry.getIn(['data', 'image']);
var bg = this.props.getMedia(image);
return h('div', {},
h('h1', {}, entry.getIn(['data', 'title'])),
h('img', {src: bg.toString()}),
h('div', {"className": "text"}, this.props.widgetFor('body'))
);
}
});
CMS.registerPreviewTemplate("posts", PostPreview);
</script>
registerWidget
lets you register a custom widget.
CMS.registerWidget(field, control, [preview])
Params:
- field: The field type which this widget will be used for.
- control: A React component that renders the editing interface for this field. Two props will be passed:
- value: The current value for this field.
- onChange: Callback function to update the field value.
- preview (optional): A React component that renders the preview of how the content will look. A
value
prop will be passed to this component.
Example:
<script>
var CategoriesControl = createClass({
handleChange: function(e) {
this.props.onChange(e.target.value.split(',').map((e) => e.trim()));
},
render: function() {
var value = this.props.value;
return h('input', { type: 'text', value: value ? value.join(', ') : '', onChange: this.handleChange });
}
});
CMS.registerWidget('categories', CategoriesControl);
</script>
from https://github.com/netlify/netlify-cms
-----------------
利用NETLIFY CMS为静态站点搭建后台管理界面
- 今天了解到 Netlify CMS 服务,决定给博客弄一个,按照官方文档顺利搭建成功,以下是过程记录。
- 如果没有站点的话可以按照官方模版快速搭建一个带有 CMS 的站点;我的内容记录主要是在已有 Netlify 站点基础上添加 Netlify CMS,英文文档见Add To Your Site。
搭建过程
创建 ADMIN 文件夹
该部分是最关键的内容,认真做完这一步基本就完成了 Netlify CMS 的搭建了。
admin 文件夹用来存储 Netlify CMS 文件,这些文件在站点部署后应该位于根目录下。不同的静态站点生成器存放 admin 文件夹位置可能不同,我是用的Hugo,所以在
/static
下创建 admin 文件夹,且创建index.html
和config.yml
两个文件:admin
├ index.html
└ config.yml
编辑INDEX.HTML
index.html
即为访问your-domain-name/admin
时展示的页面,内容可以如下:<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Content Manager</title>
</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>
编辑CONFIG.YML
config.yml
用于编辑 Netlify CMS 的配置,我的项目仓库在 Bitbucket,和 GitHub/GitLab 在一些配置上有点区别,GitHub/GitLab 仓库的配置可见官方文档。- Backend
对于 Bitbucket 仓库,Bitbucket
backend
可以直接使用 Bitbucket 账号登录 CMS,注意所有人需要仓库内容的读写权限才能登录后台界面。backend:
name: bitbucket
repo: owner-name/repo-name # 仓库路径
除了编写以上内容外,需要在 Bitbucket 注册一个
OAuth application
,以下以 Bitbucket 为例介绍注册过程,其他平台类似:- 进入账户设置界面,点击OAuth,找到OAuth consumers;
- 点击Add consumer;
- 除了Callback URL需填写
https://api.netlify.com/auth/done
,其他可以自定义。
添加步骤如下:
- 打开Netlify 主页进入网站项目;
- 找到Settings -> Access control -> OAuth;
- 在OAuth下添加Key和Secret,如图。
- Media and public folder
media_folder: "static/img/post" # 存放图片的文件夹
public_folder: "/img/post" # 上传图片的src属性会以该路径开头
- Collections
# 以下是我的Collections内容,如需要请根据自己的头文件内容自定义
collections:
- name: "post" # 定义该collection的路径
label: "Blog" # 后台显示的名字
folder: "content/blog/2018" # 文章存放文件夹
create: true # 允许创建新文件
slug: "{{slug}}" # 文件名字模版,{{slug}} 取自title
fields: # 定义front matter的显示与数据类型
- { label: "Title", name: "title", widget: "string" }
- {
label: "Author",
name: "author",
widget: "string",
default: "WithdewHua",
}
- { label: "Type", name: "type", widget: "string", default: "post" }
- { label: "Categories", name: "categories", widget: "list" }
- { label: "Tags", name: "tags", widget: "list" }
- { label: "Series", name: "series", widget: "list", required: false }
- { label: "Publish Date", name: "date", widget: "datetime" }
- {
label: "Lastmod",
name: "lastmod",
widget: "date",
default: "",
required: false,
format: "YYYY-MM-DD",
}
- {
label: "Description",
name: "description",
widget: "text",
required: false,
}
- {
label: "Featured Image",
name: "featured",
widget: "image",
required: false,
}
- {
label: "Featured Alt",
name: "featuredalt",
widget: "string",
required: false,
}
- {
label: "Featured Path",
name: "featuredpath",
widget: "string",
default: "img/post",
required: false,
}
- { label: "Slug", name: "slug", widget: "string", required: false }
- {
label: "Draft",
name: "draft",
widget: "boolean",
default: false,
required: false,
}
- {
label: "Show TOC",
name: "showtoc",
widget: "boolean",
default: true,
required: false,
}
- { label: "Post Content", name: "body", widget: "markdown" }
NETLIFY 设置
允许 IDENTITY 服务
- 进入 Netlify Settings -> Identity, 选择Enable Identity service;
- 剩余选项内容可根据自己需要调整。
添加 NETLIFY IDENTITY 挂件
- 在
admin/index.html
和自己网站页面的<head>
元素间(如我的网站中的layouts/partials/header.html
)添加以下代码;
<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
- 在自己网站页面的
</body>
元素前(如我的网站中的layouts/partials/footer.html
)加入以下代码,用于验证后跳转回自己网站。
<script>
if (window.netlifyIdentity) {
window.netlifyIdentity.on("init", user => {
if (!user) {
window.netlifyIdentity.on("login", () => {
document.location.href = "/admin/";
});
}
});
}
</script>
以上完成之后,将文件上传至 Bitbucket 仓库就全部完成了,可以进入
your-domain-name/admin
登录查看搭建好的后台界面了.