Repository navigation
Nibble 0.22.0
This release is mostly forms and fields, and a plainer Control Plane. Four database migrations are added; they only
add tables and columns, so they can be rolled back, but the snapshot taken before an upgrade is the surest way back.
What's new
- Public forms can be handled, not just stored. Each submission is New or Handled, can be marked unread,
and carries internal notes, and the list takes bulk actions. A person's submissions can be exported or erased by
email address, exports and deletes are recorded in the audit log, and the submissions of a form removed from the
schema are purged after the retention period. - Form notifications need no code.
notifyentries merge{field.x}and{global.set.field}into the subject
and message, take recipients from a field or a global (to: {field.email}), and are routed withif:. Each email
is recorded on the submission, and Send notifications again resends them. - A form can open, close and cap itself.
limits:takesopens_at,closes_at,max_submissionsandunique
(a value accepted once, such as a ticket code), with aclosed_messageshown when it is closed. A form's
submit_labelreplaces the button text. - More ways to catch spam.
spam.min_secondstreats a submission sent too soon after the form was shown as spam,
andspam.max_linkscatches text full of links. The rate limit now counts only accepted submissions, so refused
posts no longer lock a real visitor out, and the refusal says how long to wait. - A form field can be encrypted.
encrypt: truestores the value encrypted, bound to its submission and field.
Staff, exports, emails, deliveries and per-person search still read it. - Multi-step forms, saved forms and calculations.
steps: trueturns sections into checked steps.resume: true
adds Save and finish later, with a link emailed to the visitor. Acalculationfield is worked out on the
server when the form is sent, with a live figure in the theme throughcalculated(). - Forms speak the visitor's language. A multilingual site translates a form's text, Nibble's own form messages and
the visitor's confirmation email. - Hidden and prefilled form fields. A
hiddenfield is filled from a fixedvalueor from the page's query
string withprefill. - Themes get what they need to draw a form. A form field arrives with its fieldtype settings, its resolved default
and its conditions as rules to evaluate.useNibbleFormapplies conditions, leaves out fields hidden by one,
refills typed values after a refused post even without JavaScript, and gives ids,aria-describedby, an error list
and focus targets. Crumbs' contact form draws every public fieldtype accessibly, with steps, calculations and the
closed message. - Rich text can link to a global. Choose a global field in the link dialog, or write
[Apply](global:site.apply_url)through the API, and the link follows the global's address when the text renders. - Content migrations work on globals.
rename_fieldandset_defaulttake aglobalin every locale, and the new
move_fieldandremove_fieldcarry values to another global or drop a field that left the schema, so nothing is
stranded. - New fieldtypes.
decimal,range,rating,time,colorandbutton_groupwork in blueprints and public
forms, with Control Plane controls and crumbs inputs.noteshows Markdown between a form's fields and stores
nothing. Decimal, range and rating can be used in calculations. - Date-times can have a time zone.
time_zone: Europe/London(orsite) reads the time as typed in that zone,
stores the moment in UTC and shows it in that zone. A time the clocks skip is refused, and a repeated one takes its
first occurrence. - Text can be validated by what it holds.
input_type: email,urlortelchecks the value on save, in
blueprints and on public forms. A toggle'sinline_labelcan hold Markdown links, for a consent checkbox. - A field's
requiredandread_onlycan take a condition. The required marker shows only while the condition
passes, and a hidden field keeps its stored value. - Read-only means read-only. A value sent for a
read_onlyfield is kept as stored whoever saves, rows in grids
and replicators by theirid. Entry, term, global and asset writes through the API answer with anignoredlist of
the fields whose value was kept. - Apps see fuller field schemas. The JSON Schema an app writes against describes length, format, range, step,
option labels, read-only state, conditions and when a field is required. list_form_submissionstakessinceandq, searching as the Control Plane listing does.site/types.d.tstypes each form's values, and a view's form prop uses them, sovalues.topicis typed.
useNibbleFormtakes that type; an untyped call is unchanged.computed:todayis a built-in default, the current date in the site's time zone.- Blocks are easier to work with. Undo a removed block or grid row from the notice that appears, move blocks and
rows up and down from their menu, copy a block and paste it into any field with the same set, and use
collapse: accordionto keep one block open at a time. Grids and blocks have a Full screen action. - Rich text options now do what the reference says.
placeholder,character_limit(with a counter),
toolbar_mode,smart_typography, input and paste rules,link_noopener,link_noreferrer,link_collections
(the link dialog's Page tab lists routed collections),always_show_set_button,previewsand
inline_hard_breaks. - Pickers have modes and can create.
entriesandtermsfields takemode: auto | default | select | typeahead | stack;auto, the default, is a dropdown for 25 or fewer choices. People allowed to create the item see
Create a new … in the picker.nibble:checkrefuses an unknown mode. - Duplicate an entry from the editor or the listing. A field's
duplicateoption decides what is copied; slug and
uniquefields are left out by default. - Entry listings sort and filter by field. Field columns sort, and listed choice, toggle and date fields add
filters.sortableandfilterableturn them off or on per field. - Documentation covers more of the site. A theming guide to forms, pages on what a view receives and on styling
and the page shell, a Reference section listing every fieldtype option, validation rule and condition, and the
forms guide split into declaring, delivery, spam and privacy, translation and a key reference. Tests fail when the
code gains an option the pages miss. - Guides for the people who run a site. Webhooks, the Utilities screens, every
nibble:checkmessage, every
environment variable and task, the page cache and CDN, sign-in lockout and recovery, and administering from the
Control Plane without a terminal. bin/rails nibble:dev:setupasks which AI tools to set up — Claude Code, Codex or Cursor, those found on this
computer chosen by default — and writes only into the site's folder.--tools claude,codexanswers without asking.
Codex gets a project.codex/config.tomland the skills, like Claude Code.- The Connected apps screen shows
nibble connect <site>, which sets up Claude Code, Codex and Cursor in the
folder it runs in, with the site's MCP server and skill. It needs thenibblecommand 0.3.0 or later. - Apps are told more about each field. A field's description says when it is shown, required or read-only, and the
bundled schema, theming and extending skills cover the new fieldtypes, forms and reference pages. - Guides for editors, and routes in. Settings, categories and tags, the trash, your account and two-factor
sign-in, and form submissions, with start-here routes by audience and every guide listed on the docs home.
What's fixed
- Crumbs ships a fallback
defaultview, andnibble:checkwarns when a collection's entries resolve to a view
the theme lacks. A set without a view is a warning, since its blocks render nothing. - The 500 page gets the site's shared props, falling back to empty ones if loading them fails.
- Saving changes to a live entry no longer warns that someone published a newer version. The warning now appears
only when the entry really was published after those changes were started. - Publish works on a new entry, creating and publishing it in one click, and a new entry in a collection that
needs review offers Submit for review. - Apps are no longer told a field hidden by its condition isn't saved; it keeps what's sent, and only its rules
are skipped. - The Backups screen links to the restore section of the backups guide.
- The health check asks the page renderer on the configured port.
nibble:generate:formwritesrequired: true.- Form emails show every fieldtype's value again. Only a fieldtype with its own display formats a submitted value.
- A form field's
messagesoverride the step error, and a calculation's posted value is never kept in a saved
form.
Changed
- Plainer wording in the Control Plane. Page-builder sets are blocks, globals are Site settings, pending
edits to a live page are a Draft, a taxonomy shows its own name, and link targets are filtered by Type.
Statuses show their label (In review, not the stored key), error summaries name a field once by its label, and
messages say what to do next in plain words. - History, the audit log and approvals say what happened. They show field labels, readable values, titles and
verbs, and an approval says what it does and changes. Signed-in devices have names. - The Control Plane formats numbers and dates in the site's locale, the default one in
config/nibble.yml. When
that locale names only a language, such asen, the browser's region for it decides the style, so an Australian
browser sees day/month/year and an American one month/day/year; a site that declares no locale follows the
browser. Until now every Control Plane wrote Australian dates. - Default validation messages name the field once: "Your name is required." rather than "The Your name field is
required.". Their keys are unchanged, so a site's ownmessages:and translations still apply. - Date fields are compact unless
full_width: true, or the date-time has atime_zone. - Relationship fields with 25 or fewer choices show a dropdown and offer Create a new ….
nibble:checkreports more: records holding a switched-off required toggle, saved text failing an email, URL or
phone check, a picker mode it doesn't know, and alink_collectionshandle that names no collection.
Security
- CSV exports can't run formulas. A cell that starts like a spreadsheet formula is written as text, in entry, term,
submission and per-person exports. - Rich text links to other sites carry
rel="noopener"by default. - A resume link's token stays out of the request log, and the personal data export of saved forms leaves it out.
Upgrade:
- A required toggle must be switched on, everywhere.
required: trueon atogglenow means it has to be on:
entries holding one switched off can't be published, and terms and globals can't be saved.bin/rails nibble:check
lists them; fix them, or droprequiredif "off" is a valid answer. - CSV exports put
'before cells that look like formulas. A script that parses an export sees'=SUM(A1)
where it saw=SUM(A1); strip a leading'if you read the files. - Writes to a
read_onlyfield are now ignored from the Control Plane, API tokens and MCP, and likewise for
visibility: read_only. An integration that sets such a field must use an import, a content migration or a
scheduled task, which are exempt, or you removeread_onlyfrom the field. - Email, URL and phone
textfields are checked on save. A saved record whose value fails can't be saved until
it is fixed;bin/rails nibble:checklists them. To check a phone number against your own pattern, use
validate: regex:, which replaces the phone check. - A rich text field with
character_limitrefuses longer text on save. Content already over a newly set limit
can't be saved until it is shortened. to: {global…}on a form notification lets whoever edits that global choose where submissions go. Keep such a
global to people you'd trust with the inbox.- A custom theme must post
_nibble_t(a hidden input holdingform.timestamp) when a form sets
spam.min_seconds, or every submission is caught as spam.useNibbleFormand crumbs already do. limits.uniquecovers only submissions accepted after it's added. Duplicates already stored are left alone.- Rich text links to other sites now get
rel="noopener". Setlink_noopener: falseon the field to keep the old
output. - Editors will notice: date fields are compact unless
full_width: trueor zoned; grids and blocks have a
Full screen action; relationship fields with 25 or fewer choices show a dropdown and offer Create a new …
to people allowed to; entry listings gain filters for listed choice, toggle and date fields; and the new names
(blocks, Site settings, Draft, Type). - Four new database migrations add form handling (handled state, notes, retention), encrypted submission fields,
submission keys forlimits.uniqueand saved forms (form_partials).bin/rails nibble:upgraderuns them. They
only add tables and columns, sobin/rails db:rollbackcan undo them, which drops what they hold. site/types.d.tsgains form value types.bin/rails nibble:upgraderegenerates it; commit the new file.- AI apps you connected with
nibble0.2.0 were set up for your whole account, so a site's tools and guide load
in every project. Updatenibbleto 0.3.0, runnibble disconnect <site>once, thennibble connect <site>in
the folder where you work on that site. If you rancodex mcp add nibble-dev, remove it with
codex mcp remove nibble-devand runbin/rails nibble:dev:setupagain to choose your tools.