Forms, dynamic data, components, bindings and media
Forms with fields and actions, PHP components for the site, bindings to WordPress data and saving images.
On this page
01Overview
The nc/native-form block describes a form in JSON: fields, steps and actions. The compiler saves the normalized configuration in the nc/native-form slot of the document. On every request the slot writes the nonce, the context post and the outcome. The visitor submits the form to the REST endpoint nucleo/v1/form/<doc>/<node>. The endpoint reads the configuration from the published document, validates the values and runs the actions in order.
Components are PHP classes written in a plugin of the site. They register data sources for nc/collection and actions for nc/native-form with the nucleo/register_components hook.
Bindings connect a property of a node (content.<name> or settings.<name>) to a WordPress field. The compiler writes the fixed values of the page right away. The others become tokens of the nc/bind slot, resolved on every request.
The media part saves images in the library with a check of the real type, and generates AVIF and WebP copies if the site turns them on.
All functions in this chapter are free.
02Native form: definition
Form configuration
What it does: defines a form with fields, steps, actions, texts and options. The configuration is normalized, and invalid entries are silently discarded.
How to use it: nc/native-form node in the document. Minimal example:
{ "id": "m1", "type": "nc/native-form",
"settings": {
"fields": [ { "name": "email", "type": "email", "label": "Email", "required": true } ],
"actions": [ { "type": "save" }, { "type": "email", "to": "admin", "subject": "New contact", "body": "{fields}" } ]
},
"content": { "submitLabel": "Send" } }Parameters (settings):
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
fields | array | field objects (see below) | [] | At most 40. Fields after the 40th are discarded. |
steps | array | { "title": string } | [] | One step per entry. Entries without a string title are discarded. |
actions | array | objects with type among otp, save, email, webhook, create-post, component | [] | Actions with an unknown type are discarded. |
redirect | string | home, page:<slug> or a URL | '' | Destination after a successful submission. See "Outcome and redirect". |
captcha | boolean | true, false | true | false removes the site captcha from this form. |
groupNumbering | string | none, letters, numbers, letters-box, numbers-box | none | Numbers the legends of field groups. Any other value means none. |
Texts (content, translatable):
| Key | Default |
|---|---|
submitLabel | Send |
successMessage | Thank you. |
errorMessage | Something went wrong. Try again. |
codeLabel | Verification code |
nextLabel | Next |
backLabel | Back |
sentMessage | We sent a code to your email. |
sendCodeLabel | Get the code |
verifyLabel | Verify |
otpFailedMessage | We could not send the code by email. Try again later. |
expiredMessage | The code has expired. Request a new code: your answers stay in the form. |
captchaMessage | Complete the anti-spam check and try again. |
requiredMark | none |
optionalMark | none |
The defaults are translatable strings of the nucleo domain. An empty text, or a text with only spaces, keeps the default.
Permissions: who saves the document.
Edition: Free
Known limits: 40 fields. Field name with ^[a-z][a-z0-9_]{0,31}$. The block is not allowed inside a card of nc/query or nc/collection (card_block_not_allowed).
Field types
What it does: each field produces an HTML control and a validation rule on the server.
How to use it: entry of settings.fields with name and type.
Parameters (field attributes):
| Name | Type | Allowed values | Default | Notes | |
|---|---|---|---|---|---|
name | string | ^[a-z][a-z0-9_]{0,31}$, unique | required | A field with an invalid or repeated name is discarded. | |
type | string | text, email, tel, url, textarea, number, date, select, radio, checkboxes, checkbox, consent, hidden, context | required | An unknown type discards the field. | |
label | string | text | '' | Label or legend. | |
required | boolean | true, false | false | Only a literal true makes the field required. | |
help | string | text | '' | Help text linked with aria-describedby. | |
step | integer | >= 0 | 0 | Step index. An index beyond the last step goes to the last one. | |
maxLength | integer | >= 1 | 2000 for textarea, 200 for the others | Applies to text types. | |
min, max | number or string | number, or date Y-m-d | '' | For number and date. | |
decimals | integer | >= 0 | 0 | Decimal places of number. The HTML step attribute is 1 or 10^-decimals (at most 15 digits). | |
placeholder | string | text | '' | For text, email, tel, url, textarea. | |
options | array | `{ "value": string\ | number, "label"?: string }` | [] | For select, radio, checkboxes. Empty value: option discarded. Without label the value is used. |
value | string or number | text | '' | Fixed value of hidden. | |
from | string | post.id, post.title, post.url | required for context | A context field without a valid from is discarded. | |
width | string | full, half | full | Two consecutive half fields sit side by side on wide screens. | |
group | string | text | '' | Consecutive fields with the same group sit in a fieldset with that legend. |
Controls and values:
type | Control | Submitted value |
|---|---|---|
text, email, tel, url | input of the matching type with maxlength | string without HTML tags |
textarea | textarea with maxlength | string without HTML tags |
number | input type="number" with min, max, step | numeric string |
date | input type="date" with min, max | Y-m-d |
select | select with an empty first option | one of the option values |
radio | group of radio buttons in a fieldset | one of the option values |
checkboxes | group of checkboxes, name <name>[] | list of option values |
checkbox, consent | one checkbox with value="1" | 1 |
hidden | input type="hidden" | always the value of the configuration |
context | no control | id, title or URL of the context post, read by the server |
Permissions: as the form configuration.
Edition: Free
Known limits: consent behaves like checkbox. Nucleo does not save the date, text or version of the consent. requiredMark and optionalMark do not appear on checkbox, consent, hidden and context. The form does not accept files.
Steps
What it does: splits the fields into steps. Each step is a fieldset with legend equal to title.
How to use it: settings.steps and step on each field. The view.js script shows one step at a time with the nextLabel and backLabel buttons. Without script all steps stay visible.
Parameters: steps[].title (string).
Permissions: as the form configuration.
Edition: Free
Known limits: the server always validates all fields on the final submission. Without steps there is a single fieldset without legend.
Document validation
What it does: checks the configuration when the document is saved. An error blocks the save.
How to use it: automatic, inside the document validation.
Parameters: None
Permissions: as saving the document.
Edition: Free
Known limits: error codes returned:
| Code | When |
|---|---|
duplicate_field | Repeated field name. |
bad_options | select, radio or checkboxes without options. |
bad_step | step of the field >= number of steps, or > 0 without steps. |
otp_first | otp is not the first action, or its field is not of type email. |
otp_step | step of the otp action outside 0…steps-2, or email field in a step after step. |
unknown_field | field of otp, to/replyTo with field:x, or placeholder {field:x} in subject, body, title, fields, input with an undeclared field. |
unverified_recipient | email action with to: field:x and no valid otp action on the same field. |
unknown_post_type | create-post with a content type outside the model. |
bad_status | create-post with status other than draft and pending. |
unsafe_url | webhook with a url that does not start with https://. |
unknown_component | component action with a name that is not registered. |
03Native form: submission
Submission endpoint
What it does: receives a form submission, applies the checks and returns the outcome.
How to use it: POST /wp-json/nucleo/v1/form/<doc>/<node>, body application/x-www-form-urlencoded with the form fields and the service fields. With the header X-Nucleo-Form: 1 the response is JSON. Without the header the response is a 303 redirect to _nc_back with nc_form=<node>, nc_status=done|error|otp|code|verified and, for otp, nc_ticket.
Parameters (service fields):
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
_nc_nonce | string | form nonce | required | See "Form nonce". |
_nc_hp | string | empty | '' | Honeypot. |
_nc_ctx | integer | id of a post | 0 | Context post. Valid only if published. |
_nc_back | string | URL of the same site | home | Return target for the submission without script. Goes through wp_validate_redirect. |
_nc_ticket | string | OTP ticket | '' | Second OTP submission or verification at an intermediate step. |
_nc_code | string | 6 digits | '' | OTP code. |
_nc_otp | string | send, verify | '' | Code at an intermediate step. |
_nc_proof | string | verified ticket | '' | Final submission after the verification at a step. |
g-recaptcha-response, h-captcha-response, cf-turnstile-response, frc-captcha-response | string | provider token | '' | Only with captcha on. |
Order of the checks: document and node, honeypot, nonce, rate limit, captcha, OTP flow, validation, actions.
| Outcome | HTTP | code |
|---|---|---|
| Document not published, protected by password, or node missing | 404 | nucleo_form_not_found |
| Honeypot filled in | 200 | none: success response, no action |
| Invalid nonce | 403 | bad_nonce |
| Limit exceeded | 429 | rate_limited |
| Captcha not passed | 403 | captcha |
| Invalid fields | 422 | invalid, with errors per field |
| Wrong code | 422 | otp_wrong |
| Ticket or proof expired | 410 | otp_expired |
| Code email not sent | 500 | otp_failed |
| Action failed | 500 | action_failed |
| Successful | 200 | status: done, otp, code or verified |
Permissions: public (permission_callback __return_true). The detail field of action_failed is visible only to users with manage_options, or when the environment is local or development. The filter nucleo/forms/error_detail changes the choice.
Edition: Free
Known limits: 5 submissions per minute per IP and form. 10 code verifications per minute per IP and form, with a separate counter. 3 OTP codes every 15 minutes per normalized address (lowercase, no spaces, no +tag). The IP comes from REMOTE_ADDR, or from X-Forwarded-For if the proxy is listed in the nucleo/trusted_proxies filter.
Form nonce
What it does: returns a fresh nonce. The nonce does not depend on the logged-in user.
How to use it: GET /wp-json/nucleo/v1/form/<doc>/<node>/nonce. Response { "nonce": "…" } with Cache-Control: no-store. The script asks for it before every submission, because the page cache can serve an expired nonce.
Parameters: doc and node in the path.
Permissions: public.
Edition: Free
Known limits: HMAC of wp_nonce_tick() and of the action nucleo_form:<doc>:<node>. Valid for the current tick and the previous one, as wp_verify_nonce. 404 if the form does not exist in the published document.
Value validation
What it does: validates the submitted values against the declared fields. It ignores undeclared fields and context fields.
How to use it: automatic on every submission.
Parameters: None
Permissions: public, as the endpoint.
Edition: Free
Known limits: rules and messages:
| Type | Rule | Message |
|---|---|---|
| all | required and empty | This field is required. |
email | FILTER_VALIDATE_EMAIL | Enter a valid email address. |
url | valid URL with scheme http or https | Enter a valid web address starting with http or https. |
tel | ^[0-9 +().-]{5,30}$ | Enter a valid phone number. |
| text types | length <= maxLength | The text is too long. |
number | ^-?[0-9]+(\.[0-9]+)?$, decimals <= decimals, between min and max | Enter a valid number., Too many decimal places., Enter a value within the allowed range. |
date | real date Y-m-d between min and max | Enter a valid date., Enter a date within the allowed range. |
select, radio | value among the options | Choose one of the options. |
checkboxes | every value among the options | Choose one or more of the options. |
checkbox, consent | value 1 | Invalid value. |
Text types lose HTML tags and the spaces at the edges. hidden always uses the value of the configuration, not the submitted one.
Outcome and redirect
What it does: shows the outcome message. With settings.redirect it sets the destination page after a successful submission.
How to use it: redirect accepts home, page:<slug> and the other internal link references, or a URL. The internal reference resolves like the links of the page. The JSON response done contains redirect if the destination exists.
Parameters: settings.redirect (string).
Permissions: public.
Edition: Free
Known limits: a reference without published content does not produce redirect. An unsafe URL (javascript: etc.) is discarded by esc_url_raw. Without script the 303 redirect always returns to _nc_back: the slot reads nc_status and shows only done, error and otp.
04Native form: actions
Action execution
What it does: runs the actions after validation, in the declared order. otp does not run here. The first error stops the following ones.
How to use it: settings.actions.
Parameters: see the sections of the single actions.
Permissions: public, as the endpoint.
Edition: Free
Known limits: the visitor sees errorMessage. The details go to the PHP log with the prefix [nucleo] form <node>, action <type>:. Actions already run are not rolled back.
Placeholders in texts
What it does: replaces the placeholders in the texts of the email, create-post and component actions.
How to use it: {field:<name>}, {post.id}, {post.title}, {post.url}, {site.name}, {fields}. {fields} writes a line label: value for each field that is not context and has a value. Lists are joined with , .
Parameters: None
Permissions: public.
Edition: Free
Known limits: a single pass: an inserted value is not read again as a placeholder. An unknown placeholder stays as it is. The result is plain text.
save action: storing submissions
What it does: saves the submission as a private post of type nucleo_submission.
How to use it: { "type": "save" }. Title <node> – <Y-m-d H:i:s>. Meta _nc_form (<doc>:<node>), _nc_data (values), _nc_context (id of the context post or 0).
Parameters: None
Permissions: the nucleo_submission type requires manage_options to create, edit, read private posts and delete.
Edition: Free
Known limits: the type has show_ui on but show_in_menu off: no menu item. The interface shows only the title, not the values. Nucleo does not delete submissions over time, nor when the plugin is deactivated. Submissions do not clear the collection caches and do not appear in collections.
email action
What it does: sends a plain text email.
How to use it: { "type": "email", "to": "admin", "subject": "…", "body": "…", "replyTo": "field:email" }.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
to | string | admin, field:<name>, email address | admin | admin is the admin_email option. field:<name> requires an otp action on the same field. |
subject | string | text with placeholders | '' | On one line only. |
body | string | text with placeholders | '' | |
replyTo | string | field:<name> | none | Only if the value is a valid email. |
Permissions: public.
Edition: Free
Known limits: invalid recipient: error invalid recipient. Sending failed: error wp_mail did not send the message. The sending goes through the development mail log: in development the email goes to the log.
webhook action
What it does: sends the submission as a JSON POST to an external URL.
How to use it: { "type": "webhook", "url": "https://…" }. Body: { "form": "<doc>:<node>", "fields": {…}, "context": <id>|null }.
Parameters: url (string, https, required).
Permissions: public.
Edition: Free
Known limits: the URL goes through a safety check: only https, no credentials, no localhost, only public IPs. Timeout 5 seconds. Errors: unsafe webhook URL, network error, HTTP status <code> for responses >= 400. The code does not sign the request and does not retry.
create-post action
What it does: creates a content of a model type and writes its fields.
How to use it: { "type": "create-post", "postType": "iscrizione", "status": "pending", "title": "{field:nome}", "fields": { "email": "{field:email}" } }.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
postType | string | slug of a model type | required | |
status | string | draft, pending | required | |
title | string | text with placeholders | '' | |
fields | object | model key → text with placeholders | {} | String values only. |
Permissions: public.
Edition: Free
Known limits: invalid fields: the created content is deleted and the error reports the details. Errors tipo di contenuto fuori dal modello and status not allowed.
component action
What it does: runs a PHP action registered by a plugin of the site.
How to use it: { "type": "component", "name": "acme/crm", "input": { "email": "{field:email}" } }. Without input the action receives all the field values. With input the strings go through the placeholders and the other values stay as they were. Then the input is validated against inputSchema(), permitted() is checked and run() is called.
Parameters: name (string), input (object, optional).
Permissions: public. The action decides with permitted().
Edition: Free
Known limits: errors component action not registered, component action not permitted, JSON schema errors, component action failed or ActionResult::message. ActionResult::data stays on the server.
OTP code at final submission
What it does: verifies the email address before running the actions.
How to use it: first action { "type": "otp", "field": "email" }. First submission: validation, a 6-digit code for each email, response status: "otp" with ticket. Second submission with _nc_ticket and _nc_code: verification, then the actions with the values saved in the ticket.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
field | string | name of an email field | required | |
subject | string | text | Your verification code | Translatable. |
body | string | text | Your code: {code} | |
ttl | integer | 5–30 (minutes) | 15 | Values out of range are set to the limits. |
step | integer | 0…steps-2 | none | See the next section. |
Permissions: public.
Edition: Free
Known limits: in the text of the OTP email only {code}, {site.name}, {post.title}, {post.url} apply. The other placeholders become empty. The ticket is a transient nucleo_otp_<md5> with the HMAC hash of the code. 5 attempts per ticket: from the sixth the ticket expires. The ticket is used only once, even with parallel requests. In the classic flow an expired ticket returns errorMessage, not expiredMessage.
OTP code at an intermediate step
What it does: asks for and verifies the code when leaving the step step, before the following steps.
How to use it: { "type": "otp", "field": "email", "step": 0 }.
_nc_otp=send: the server validates the fields of the steps up tostep, sends the code and respondsstatus: "code"withticket. It sets the cookienucleo_otp_<doc>_<node>(HttpOnly,SameSite=Strict,Secureon HTTPS, 1 hour)._nc_otp=verifywith_nc_ticketand_nc_code: respondsstatus: "verified". The verified ticket is valid for 30 minutes from the first verification.- Final submission with
_nc_proof=<ticket>: full validation, then the proof is used only once.
Parameters: as the otp action, with step.
Permissions: public.
Edition: Free
Known limits: without the cookie the ticket is not valid. The proof is valid only for the same document, node and address. Invalid proof: 410 otp_expired with expiredMessage. Without script the form uses the classic flow.
Consent for actions with external effects
What it does: the quality rule form.action.consequential (R4.4) flags the forms with actions that leave the site. They are webhook, create-post, component, and email with to other than admin or empty.
How to use it: the warning blocks publication. The agent asks the user for consent and publishes with acknowledge and the consent in reason.
Parameters: None
Permissions: as publication, see nucleo/doc-publish.
Edition: Free
Known limits: the rule concerns the consent of the person who publishes, not the privacy consent of the visitor. For the visitor there is the field type consent.
05Native form: anti-spam
Honeypot
What it does: adds the trap field _nc_hp off screen with CSS. A submission with the field filled receives a fake success and no action.
How to use it: automatic in every form.
Parameters: None
Permissions: public.
Edition: Free
Known limits: None found.
Captcha
What it does: shows a captcha above the buttons of every native form and verifies the token with the provider.
How to use it: one provider per site, in the nucleo_captcha option. Set it in Nucleo AI → Settings, Captcha tab, or with nucleo/settings-set, group captcha. nucleo/settings-get reads provider, site key, secretSet and threshold, never the secret. settings.captcha: false removes it from a form.
Parameters (group captcha):
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
provider | string | '', recaptcha, recaptcha-v3, hcaptcha, turnstile, friendly | '' | '' turns the captcha off. |
siteKey | string | public key | '' | Required with a provider. |
secret | string | secret key | '' | Required with a provider. Write only. |
threshold | number | 0–1 | 0.5 | Minimum score for recaptcha-v3. |
Permissions: manage_options; scope nucleo:admin for the abilities.
Edition: Free
Known limits: the captcha applies to the submission without ticket and to _nc_otp=send, not to the verification and to the final submission with ticket or proof. Provider unreachable or response >= 500: the check passes (fail-open). recaptcha-v3 also requires the action nucleo_form. Unknown key in the group: error Unknown captcha key. The provider scripts come from external CDNs (Google, hCaptcha, Cloudflare, jsDelivr for Friendly Captcha).
06Nucleo emails
Sending and outcome of emails
What it does: sends the Nucleo emails (OTP codes and email actions) with wp_mail. It records the outcome of the last sending in the nucleo_mail_status option.
How to use it: automatic. The hooks wp_mail_failed and wp_mail_succeeded update the outcome. nucleo/site-describe reports in warnings a failure from the last 7 days not followed by a successful sending.
Parameters: None
Permissions: none for sending. The warning is read with nucleo/site-describe.
Edition: Free
Known limits: the hooks are registered in admin, REST, CLI and cron, not in frontend requests. Deactivating the plugin deletes nucleo_mail_status.
Development mail log
What it does: in development it stores the Nucleo emails in the nucleo_dev_mail option instead of sending them. The sending is reported as successful.
How to use it: active in local unless define('NUCLEO_DEV_MAIL', false). In development it requires define('NUCLEO_DEV_MAIL', true). The log is never enabled in staging and production. The filter nucleo/dev_mail (default true) turns it off even where it is allowed. Read it with nucleo/mail-log.
The log is never enabled in staging and production. It stores OTP codes in plain text.
Parameters (nucleo/mail-log):
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
limit | integer | 1–20 | 20 | Entries from the most recent. |
Permissions: manage_options; scope nucleo:admin.
Edition: Free
Known limits: last 20 emails, at most 24 hours. Body cut at 5000 characters. The log contains the OTP codes in plain text. A cron (nucleo_dev_mail_prune) removes the expired entries every day. Deactivation deletes the option. The emails of WordPress and of the other plugins are sent as usual.
07Extensible components
Component registration
What it does: collects the data sources and the actions of the site's plugins in one registry.
How to use it: the plugin hooks into nucleo/register_components. The first call to Components::instance() runs it.
add_action('nucleo/register_components', static function (\Nucleo\Extend\Components $components): void {
$components->add(new \Acme\Components\DataSources\Eventi());
$components->add(new \Acme\Components\Actions\Crm());
});PHP API of Nucleo\Extend\Components:
public static function instance(): selfpublic function add(DataSource|Action $component): voidpublic function dataSource(string $name): ?DataSourcepublic function action(string $name): ?Actionpublic function describe(): array— names, labels and schemas, never the code.
The component blocks use another hook, nucleo/register_blocks. The local command nucleo component new <data-source|action|block> <name> generates the plugin, the classes and the registration.
Parameters: component name with ^[a-z0-9-]{1,40}\/[a-z0-9-]{1,40}$, that is <vendor>/<name>.
Permissions: none at runtime. The plugin is installed and activated like a WordPress plugin.
Edition: Free
Known limits: an invalid or already used name (also across data source and action) is discarded with _doing_it_wrong. The PHP code never goes through REST, MCP or push.
Data source (DataSource)
What it does: provides items to nc/collection with "source": "component".
How to use it: implements Nucleo\Extend\DataSource:
public function name(): stringpublic function label(): stringpublic function schema(): array—params,fields, optionalttlpublic function read(array $params, int $page, int $perPage): DataPage
DataPage has items (list of maps of scalar values or null) and total. In the document: "source": "component", "component": "acme/eventi". The param filters pass the parameters. In the card it is read with the bind { "source": "item", "field": "<field>" }.
Parameters (schema()):
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
params | object | key → JSON Schema (string, integer, number, boolean, enum) | required | read() receives parameters already validated. |
fields | object | key → {type, label} | required | Fields of each item. |
ttl | integer | >= 0 seconds | 300 | 0 = no cache. |
Permissions: public for reading, as the collection.
Edition: Free
Known limits: invalid parameters or unregistered source: empty collection. On saving, an unregistered source gives unknown_component. The collection does not compute counts per option.
Action (Action)
What it does: runs site code when a native form is submitted.
How to use it: implements Nucleo\Extend\Action:
public function name(): stringpublic function label(): stringpublic function inputSchema(): array— JSON Schema of typeobjectpublic function permitted(array $input, ActionContext $context): boolpublic function run(array $input, ActionContext $context): ActionResult
ActionContext has formId (node), documentId, contextPostId, ip. ActionResult has ok, message (for the visitor) and data (stays on the server), with the constructors ActionResult::ok(string $message = '') and ActionResult::fail(string $message). Use in the form: see "component action".
Parameters: None beyond the methods.
Permissions: decided by permitted().
Edition: Free
Known limits: see "component action".
List of components
What it does: returns the registered data sources and actions, with name, label and schema.
How to use it: nucleo/components-list. Response { ok, dataSources: [{name, label, schema}], actions: [{name, label, inputSchema}] }.
Parameters: None
Permissions: edit_pages; scope nucleo:read.
Edition: Free
Known limits: does not list the component blocks: they appear in catalog-get.
Activating a components plugin
What it does: activates a components plugin already on disk. It installs nothing and receives no code.
How to use it: nucleo/component-activate with { "plugin": "nucleo-components" }. The file must be WP_PLUGIN_DIR/<plugin>/<plugin>.php with the header Nucleo Components. The local command nucleo component deploy copies the plugin to a local WordPress.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
plugin | string | ^[a-z0-9][a-z0-9-]{0,60}$ | required | Folder and name of the main file. |
Permissions: activate_plugins; scope nucleo:admin.
Edition: Free
Known limits: errors not_found, not_component, activation_failed. Plugin already active: ok with already: true. Every call goes to the audit log.
08Bindings
Bind syntax
What it does: connects a property of a node to a WordPress field.
How to use it: bind key of the node. The key is content.<name> or settings.<name> declared by the block.
{ "id": "h1", "type": "nc/heading",
"bind": { "content.text": { "source": "post", "field": "title", "fallback": "Untitled" } } }Parameters (bind value):
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
source | string | post, term, author, site, nucleo, acf, metabox, jetengine, woo, user, query, param, item | required | |
field | string | not empty | required | See "Sources and fields". |
fallback | string | text | '' | Value when the field is empty or missing. |
Permissions: who saves the document.
Edition: Free
Known limits: a key not declared by the block gives the error bind key not declared in the block. The sources user and query are not allowed in cards.
Sources and fields
What it does: reads the value of the field from the indicated source.
How to use it: nucleo/bind-fields lists the fields of a content type.
Parameters:
source | field | Value |
|---|---|---|
post | title, excerpt, date, url, image, meta:<key> | Current post. image is the URL of the large size of the featured image. |
site | name, description, url | Site data. |
author | name, bio, url | Author of the current post. |
term | name, description, url, slug, count, or key of a model field on the taxonomy | Term of the card or queried term. Never a post. |
user | name | Logged-in user. Empty for anonymous visitors. |
query | search, found, page | Main query of the request: searched text, total results, current page. Not allowed in cards. |
nucleo | <key> or <repeater>.<index>.<subfield> (index from 0) | Field of the content model. |
acf | field name | get_field(). An array with url returns the URL. Without ACF it reads the meta. |
metabox | field id | rwmb_meta(). Without Meta Box it reads the meta. |
jetengine | meta key | Meta of the post. |
woo | price, regular_price, sale_price, sku, stock_status, rating | WooCommerce product of the post. Prices come from wc_price without HTML. Empty without WooCommerce or if the post is not a product. |
item | item key | Current item of a card (component source or row of nc/repeater). |
param | parameter name | Parameter of a reusable section. It resolves when the section is expanded. |
nucleo fields by type: boolean → 1 or empty; image → URL of the attachment; relation → title of the first linked content if published; select → labels joined with , ; whole repeater → no value.
Permissions: nucleo/bind-fields requires edit_posts; scope nucleo:read.
Edition: Free
Known limits: only strings and numbers become text. Arrays, objects, false and null give the fallback. The filter nucleo/bind_fields adds fields to the bind-fields list, not sources to the resolver.
Static and dynamic values
What it does: decides whether a bind resolves at save time or on every request.
How to use it: automatic. In page documents the sources other than user, query, woo, term and item are read at compile time. The value goes into the node and the page records the dependency bind:<source>:<field>. In the other cases the compiler writes a token __NCB<n>__ and the nc/bind slot replaces it on every request. Layout and sections are always dynamic.
Parameters: None
Permissions: none.
Edition: Free
Known limits: an empty static value uses the fallback. Inside a card the bind reads the current item. Outside, the queried post.
Value escaping
What it does: applies the right escape to each dynamic value.
How to use it: automatic. content.html uses wp_kses_post. The keys ending with src, url, href or poster use esc_url. The others use esc_html.
Parameters: None
Permissions: none.
Edition: Free
Known limits: None found.
Recompilation when meta changes
What it does: recompiles a page when a meta read by one of its static binds changes.
How to use it: automatic on added_post_meta and updated_post_meta. It applies to the dependencies bind:metabox:<key>, bind:acf:<key>, bind:post:meta:<key>.
Parameters: None
Permissions: none.
Edition: Free
Known limits: meta with the _ prefix are ignored. Deleting a meta does not recompile. The watcher is registered in admin, REST and CLI, not in frontend requests.
09Media
Saving images
What it does: saves an image as an attachment of the media library, with alternative text and title.
How to use it: internal, used by nucleo/media-import and nucleo/media-upload. It checks the real type with getimagesizefromstring, not the declared header. The file extension comes from the real type. The save goes through media_handle_sideload, so WordPress generates the intermediate sizes.
Parameters: None for the user.
Permissions: those of the abilities that use it.
Edition: Free
Known limits: formats image/jpeg, image/png, image/webp, image/gif, image/avif. Empty content or >= 10 MB: download_failed. Type not allowed: unsupported_type.
Import from URL
What it does: downloads a public image and saves it in the library.
How to use it: nucleo/media-import. Response { ok, id, url, width, height } or { ok: false, error }.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
url | string | https URL of a public host | required | |
alt | string | text | required | Empty string for decorative images. |
title | string | text | none | Title of the attachment. |
Permissions: upload_files; scope nucleo:write.
Edition: Free
Known limits: UrlGuard with DNS resolution: error invalid_url for private hosts, localhost, credentials or a scheme other than https. Timeout 15 seconds. Response other than 200: download_failed. File name from the URL path. Does not recognize duplicates.
Upload from base64
What it does: saves an image sent in base64. An identical file already uploaded is returned without duplicating it.
How to use it: nucleo/media-upload. Response { ok, id, url, width, height, file, sha1, existing }.
Parameters:
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
file | string | name with extension | required | Gives the name of the saved file. The extension comes from the real type. |
data | string | base64 | required | |
alt | string | text | '' | |
title | string | text | none |
Permissions: upload_files; scope nucleo:write.
Edition: Free
Known limits: invalid base64: invalid_data. A duplicate is recognized with the SHA-1 in the _nucleo_sha1 meta and with the original file name (<name> or <name>-<n>). Images above 2560 px are compared on the original file, not on the -scaled copy.
AVIF and WebP formats
What it does: generates AVIF and WebP copies of the original and of the intermediate sizes. nc/image and nc/post-image offer them in <picture>, with the original as fallback.
How to use it: turned on with the site option imageFormats, for example ["avif", "webp"], through nucleo/site-options-set. Images uploaded later get the formats by themselves. For the ones already present use nucleo/media-formats. In image blocks formats: "off" turns the sources off.
Parameters (nucleo/media-formats):
| Name | Type | Allowed values | Default | Notes |
|---|---|---|---|---|
ids | array of integer | 1–50 ids of image attachments | none | Other ids are skipped. |
missing | boolean | true, false | false | Only the images without any of the formats turned on. |
limit | integer | 1–50 | 20 | Applies without ids. Order by ascending id. |
Response { ok, done: [{id, formats}], enabled, supported, remaining }.
Permissions: nucleo/media-formats requires upload_files; scope nucleo:write. nucleo/site-options-set requires manage_options; scope nucleo:admin.
Edition: Free
Known limits: option imageFormats with duplicates or values other than avif and webp: invalid_input. Empty option: media-formats responds formats_disabled. Only the formats that the server image editor can write (supported) are generated. The format equal to the original is skipped. The files are named <file>.<format> in the same folder and listed in the _nucleo_formats meta. The srcset uses only the sizes with the proportions of the original. Deleting the attachment deletes the copies too. An editor error on one size skips it silently.
Was this page helpful?