Overall shape
schema.json declares "what can be edited on this site" and "which forms it has". Both the dashboard's input fields and the shape of the public JSON are built from it.
{
"locales": ["ja", "en"],
"groups": [
{ "key": "hours", "label": "Opening hours", "fields": [
{ "key": "days", "label": "Open days", "type": "text" },
{ "key": "time", "label": "Hours", "type": "text", "translate": false },
{ "key": "notice", "label": "Closure notice", "type": "textarea",
"hint": "Any temporary closures. Leave empty to hide the whole box" }
] }
],
"collections": [
{ "key": "news", "label": "News", "sort": "date desc", "fields": [
{ "key": "title", "label": "Title", "type": "text", "required": true },
{ "key": "date", "label": "Date", "type": "date", "translate": false },
{ "key": "tags", "label": "Tags", "type": "tags" },
{ "key": "body", "label": "Body", "type": "blocks" }
] }
],
"forms": [
{ "key": "contact", "label": "Contact", "fields": [
{ "key": "name", "label": "Name", "type": "text", "required": true },
{ "key": "email", "label": "Email", "type": "email", "required": true },
{ "key": "message", "label": "Message", "type": "textarea" }
] }
],
"tracking": { "gtm_id": "GTM-XXXXXXX" }
}| Key | Required | Contents |
|---|---|---|
locales | Required | List of languages. The first is the primary language |
groups | Sets of single-value fields (opening hours, store details, etc.) | |
collections | Lists that grow over time (news, menu items, etc.) | |
forms | Form definitions | |
tracking | gtm_id only. A GTM ID set under "Settings → Advanced" in the dashboard takes precedence |
Unknown keys are not saved.
Rules for key
The key of groups / collections / forms, and of the fields inside them, all follow the same rules.
- Starts with a lowercase letter and uses only lowercase letters, digits, and
_(/^[a-z][a-z0-9_]*$/) - Up to 40 characters
- Unique within the same list
locales
- In the form
jaorzh-tw(/^[a-z]{2}(-[a-z]{2})?$/). No duplicates. At least one is required - The first is the language editors type in, and it is also shown when a translation is missing
groups
Sets of fields that each hold a single value. label (a non-empty string) and fields are required.
In HTML, refer to them as <group>.<field>.
<dd data-cms="hours.days">Mon–Sat</dd>collections
Lists that grow over time. label (a non-empty string) and fields are required.
sort—"<field>"or"<field> asc|desc". You can't name a field the collection doesn't have. If omitted, items follow the order arranged in the dashboard- Sorting by a
numberfield compares numerically - Order is determined by the primary-language values, so it is the same in every language
In HTML, repeat them with <template data-cms-list="<collection key>"> (Editable areas).
forms
Form definitions. fields is required; label is optional.
| Key | Contents |
|---|---|
key | The value you write in the form's data-sitekit-form="…" |
label | Name shown in the dashboard and notifications |
fields | Fields. Each key matches an input's name |
success_url | Where to go after a submission without JavaScript (application/x-www-form-urlencoded). Must be an http(s) URL within the site's allowed origins |
- Notification destinations (email, Slack) and the auto-reply text are not set in schema.json. The owner can change them under "Settings → Notifications → each form" in the dashboard.
forms[].notify/forms[].mail_templateare ignored with a warning if present - For regular forms sent with JavaScript, set the destination with
data-success-urlin the HTML (Forms)
fields
| Key | Type | Contents |
|---|---|---|
key | string | Required. Follows the key rules above |
label | string | Field name in the dashboard |
type | string | One of the types below. Defaults to text |
required | boolean | Makes the field required |
translate | boolean | false disables translation. If omitted, text types (text / textarea / blocks) are translated |
hint | string | Input help shown in the dashboard |
options | array | Options for select (required for select) |
Types
| Type | Use | Values accepted from forms |
|---|---|---|
text | Single line of text | Up to 200 characters |
textarea | Multiple lines of text | Up to 4,000 characters |
blocks | Article body (blocks such as headings, photos, video) | — |
date | Date | A real date as YYYY-MM-DD |
image | Photo (absolute URL in the public JSON) | — |
select | Choice | One of options |
number | Number | A finite number |
email | Email address (used as the recipient of the form's auto-reply) | Up to 254 characters. Saved in lowercase |
tel | Phone number | Digits, +, -, spaces, parentheses; up to 32 characters |
checkbox | Checkbox | true / "on" / "1" / "true" |
tags | Tags (for collections) | — |
email / tel / checkbox are meant for forms. In groups or collections they are treated as a plain single line of text.
Options for select
Write options as an array of strings or as objects with value / label / color (you can mix both).
{ "key": "category", "label": "Category", "type": "select", "translate": false,
"options": [
{ "value": "Announcement", "color": "gray" },
{ "value": "New product", "label": "New arrival", "color": "red" },
"Other"
] }valueis a non-empty string; no duplicates- If you write
label, it must be a non-empty string. If omitted,valueis displayed as is coloris one ofred/gold/gray/black/green/blue- The public JSON gains
category_labelandcategory_color(only for options with a color) - Categories are classification labels, so set
"translate": false
tags
- Up to 20 per item, each up to 40 characters
/#?are not allowed (they appear in tag page URLs)- Leading and trailing whitespace is trimmed, and duplicates are merged
translateis alwaysfalseeven if you set it (tags are the same in every language)
Validation errors
If schema.json has mistakes, you get a list of what's wrong and nothing is saved. For example:
groups[0].fields[1].key must match /^[a-z][a-z0-9_]*$/ (max 40)
collections[0].sort names a field this collection does not have
forms[0].fields[2] is a select and needs a non-empty options array
forms[0].success_url must be an http(s) URL
tracking.gtm_id must match /^GTM-[A-Z0-9]+$/Matching schema.json and HTML
| schema.json | HTML |
|---|---|
groups[].key and fields[].key | data-cms="<group>.<field>" |
collections[].key | <template data-cms-list="…"> / data-cms-entry / data-cms-empty |
A collection's fields[].key | data-cms="…" inside the template |
forms[].key | <form data-sitekit-form="…"> |
A form's fields[].key | The input's name="…" |
Form inputs whose name isn't in schema.json are ignored without an error (and not saved). When you add a field, add it to schema.json too.