Reference
Resource metadata
Root settings, system fields, resource rules and schema examples.
.meta file
Defines the structure and behavior of a resource. All fields must be explicitly configured.
{
"fields": {
"title": {
"name": "Title",
"type": "text",
"required": true
},
"title_slug": {
"name": "URL slug",
"type": "slug",
"source": "title"
},
"published": {
"name": "Published",
"type": "boolean"
},
"body": {
"name": "Body",
"type": "html",
"buttons": "h2,h3,h4,bold,italic,orderedlist,unorderedlist,quote,anchor",
"media": true,
"media_sizes": "sm-90,md-70,lg-60,xl-50,xxl-40",
"admin_col": false
},
"sort_order": {
"name": "Sort order",
"type": "text",
"admin_col": false
}
},
"sort": {
"field": "sort_order",
"flags": "numeric",
"order": "asc"
}
}
Root-level .meta configuration
| Key | Description |
|---|---|
sort |
Default sort (field, flags: string/numeric, order: asc/desc) |
validate |
Validation rules (e.g. natural-short-text) |
languages |
Enabled languages for this resource |
ai_prompts |
Per-field AI translation instructions |
name |
Object with optional singular and plural labels used by [#resource-name#], admin headings, and Nimbly-bar resource entries. Labels fall back to names derived from the resource ID. Example: {"singular": "Member", "plural": "Members"}. |
nimblybar |
Boolean controlling whether the resource appears in the Nimbly-bar Resources menu. Regular resources are visible by default; users and roles are hidden by default. Set true to include or false to hide explicitly. The current user still needs view-<resource>. |
actions |
Object with optional view_url and url keys. view_url overrides the generic admin View action (default /nb-admin/{resource}/{uuid}?view=1); url adds the separate “View on site” action. Both support [#record.<field>#] substitutions. Example: {"view_url": "/review/?id=[#record.uuid#]", "url": "[#base-url#]/articles/[#record.title_slug#]"}. |
events |
Resource lifecycle event declarations. Supported keys: create, update, delete. Values are arrays of named events or job:<type> queue entries. See below. |
splitdir |
Boolean. When true, records are stored in a two-level subdirectory tree by UUID prefix for filesystem performance at scale (> ~10,000 records). See §12 API - Scalability. |
index |
Array of field names to index. Creates fast lookup paths for those fields. See §4 Indexes below. |
upsert |
Boolean. When true, data_update() (and therefore PUT /api/v1/{resource}/{uuid}) creates a missing record instead of failing. Use only for key-value-style resources where "record may not exist yet" is the normal, expected state (e.g. core's .config, used for per-page settings) - not for regular content resources, where updating a non-existent record should stay an error. |
self_edit |
users only. Comma-separated fields a user may save on their own record through PUT /api/v1/users/{uuid}. Default: name. Anyone who may edit users (edit-users, manage-users, admin) saves every field. |
hidden |
Comma-separated fields the API never returns: not in a list, a single record, the answer to a create or update, or an export. They are still stored and saved as usual; read them in PHP with data_read(). Fields named in encrypt are always hidden. For users, password, salt, api, password_reset_token and change_email_token are hidden by core, whatever the .meta says. |
keep_shortcodes |
Boolean. By default a shortcode tag in a value that is written to a record is stored as text ([# and #] become HTML entities), whoever writes it: the API, an import, an agent, a form handler or data_create() / data_update() in a library. It then displays as typed and is never run when the value is printed inside another shortcode. Values a record already holds and the .meta itself are not touched. Set true only for a resource that no template prints and that must hold its text exactly as written; core does so for the job queue and the agent's own records. |
history |
Boolean. Whether changes to the resource's records are kept, see Record history below. Default: on for regular resources, off for users and for hidden resources other than .content, .config and .navigation. |
sitemap |
Lazy sitemap declaration. url is a string or language-keyed URL template; optional published names a publication field and optional each names one array field to expand. Rendering exposes record, language, and sitemap_item. |
System fields (auto-managed)
Every record automatically has: uuid, _created, _modified, _created_by, _modified_by. Never define these in .meta.
Resource conventions (required)
These rules are mandatory for all resources unless explicitly stated otherwise.
Always include:
"required": trueon all name/title fieldspublishedboolean field on content resourcessort_orderfield +sortconfig on list resources (partners, logos, cards, team members, etc.)"admin_col": falseon images, html, urls, large text, and technical fields like sort_order
Always consider:
- Does this resource need a
publishedfield? - Does ordering matter? Add
sort_order+sort - Is this linked from a URL? Add a slug field and list it in
index - Does any field need to be unique? Add it to
unique; a unique field is indexed by itself - Does the admin overview need a specific column order? Use
admin_columns, including_modifiedand_createdwhen useful - Does content need to be translated? Add
languagesandi18nper field - Can this be smaller while still fully solving the current requirement?
- Can existing system metadata or a single field index solve this without extra custom fields?
Admin visibility - fields to hide by default:
- images
- html content
- urls
- large text fields
- sort_order and other technical fields
Production-ready .meta examples
Example A: Partners (list with sorting)
{
"fields": {
"title": {
"name": "Partner name",
"type": "text",
"required": true
},
"published": {
"name": "Published",
"type": "boolean"
},
"logo": {
"name": "Logo",
"type": "image",
"admin_col": false
},
"website": {
"name": "Website",
"type": "url",
"admin_col": false
},
"sort_order": {
"name": "Sort order",
"type": "text",
"admin_col": false
}
},
"sort": {
"field": "sort_order",
"flags": "numeric",
"order": "asc"
}
}
Example B: Articles (content with date sorting)
{
"fields": {
"title": {
"name": "Title",
"type": "text",
"required": true
},
"published": {
"name": "Published",
"type": "boolean"
},
"featured": {
"name": "Featured",
"type": "boolean"
},
"date": {
"name": "Date",
"type": "date"
},
"main_img": {
"name": "Image",
"type": "image",
"admin_col": false
},
"intro": {
"name": "Intro",
"type": "html",
"buttons": "bold,italic",
"admin_col": false
},
"main_text": {
"name": "Main text",
"type": "html",
"buttons": "h2,h3,h4,bold,italic,orderedlist,unorderedlist,quote,anchor",
"media": true,
"media_sizes": "sm-90,md-70,lg-60,xl-50,xxl-40",
"admin_col": false
}
},
"sort": {
"field": "date",
"flags": "string",
"order": "desc"
}
}
Example C: Admin overview columns
Use admin_columns to control the admin table column order. This can include built-in system columns _modified and _created.
{
"admin_columns": ["email", "_modified", "_created"],
"sort": {
"field": "_modified",
"flags": "numeric",
"order": "desc"
}
}