What's new with TinaCMS
Version 3.12.1
Released on 8/24/2026
Patch Changes
- @joshbermanssw-
Bump the final-form family to the TypeScript releases `final-form` 4.20.10 → ^5.0.1, `final-form-arrays` ^3.1.0 → ^4.0.1, `react-final-form` ^6.5.9 → ^7.0.1. All three majors are the same event: a coordinated Flow → TypeScript rewrite published on 2025-06-07 and labelled as carrying no API changes. `react-final-form@7` is where React 19 was added to the peer range, which clears the last unmet peer warning on install outside the GraphiQL chain. They must move together because each peers on the next: `react-final-form@7` requires `final-form@^5`, and `final-form-arrays@3` peers on `final-form@^4`. `final-form-set-field-data` stays put — its peer is `>=1.2.0`.
- @kulesy-
Fix `Button` and `IconButton` not passing `disabled` to the DOM. Both components used the prop only to pick styling (`pointer-events-none`), which blocks the pointer but not the keyboard, so every disabled button in the CMS stayed focusable and could still be activated with Enter or Space. `busy` is now treated as disabled too, closing a double-submit path on in-flight buttons. `disabled` is omitted when `Button` renders as a tag that does not support it (`as='a'`).
- @joshbermanssw-
Drop the deprecated `crypto-js` dependency `@tinacms/cli` used it in one place, to generate the default `NEXTAUTH_SECRET` offered during `tinacms init`. `crypto.lib.WordArray.random(16).toString()` is replaced with `randomBytes(16).toString('hex')` from `node:crypto`, which produces the same 32-character hex string. `tinacms` declared the dependency without ever importing it.
- @joshbermanssw-
Declare the field props that `react-final-form`'s index signature used to cover `FieldRenderProps` carried `[otherProp: string]: any` in v6, so the extras `FieldsBuilder` passes to every field plugin — `tinaForm`, `index`, `children`, `experimental_focusIntent` — type-checked implicitly. v7's TypeScript rewrite dropped that index signature, so they are now declared on `FieldProps` directly. The rich-text plugin's `rawMode`, `setRawMode` and `rawEditor` are declared on its own props rather than the shared type. No runtime change; these props were always being passed.
- @kulesy-
Fix "Save to new branch" failing with "Branch operation failed" when the derived branch name is not a valid Git ref, e.g. when a collection's `path` has a trailing slash, producing `content/articles//foo.mdx` and the invalid ref `tina/articles//foo`. The default branch name derived from the file path, and any user-typed name, are now normalised to a valid ref: repeated and leading/trailing slashes collapse, characters Git forbids in refs (whitespace, control characters, `~ ^ : ? * [ \` and the `@{` sequence) become hyphens, `..` runs collapse, and leading dots and trailing `.` / `.lock` are stripped per path component. Saving is disabled while the name normalises to an empty string. The same normalisation now runs when creating a branch from the branch switcher and from the deleted-branch recovery modal, and the duplicated `formatBranchName` helpers are unified into a single util (the legacy branch switcher previously deleted invalid characters; it now replaces them with hyphens like the main switcher).
- @joshbermanssw-
Add `data-test` hooks to group-list and blocks field controls Mirrors the hooks already on simple list fields, so end-to-end tests can target the add button and field wrapper of an object list or a blocks field without depending on Tailwind classes. Nested fields carry their full path, e.g. `add-item-blocks.0.actions`.
- @kulesy-
Fix two admin regressions that appear once the TinaCloud session check starts failing. Making the collection list settle instead of spinning left the previously fetched data in place, so switching collections rendered the last collection's documents under the new collection's heading; on a fresh mount it left `collection` undefined with no error set, so `GetCollection` ran its auto-open effect against it and threw, which the top-level error boundary caught and replaced the admin with a raw TypeError card. A failed session check now sends the user straight back to the login modal with a "Your session has ended" message, and signing back in returns them to the page they were on. `GetCollection` and `GetDocument` also stop handing `undefined` to their children, showing an "Unable to load" popup for non-auth load failures, and `GetCollection`'s auto-open effect bails out early, which clears the same crash on a failed `fetchCollection`.
- @kulesy-
Skip TinaCloud identity requests when no auth token is stored. Logged-out admin loads no longer produce misleading 401/CORS console errors; a clear console message now points at the login popup console instead. Also fixes an unawaited auth guard in GetDocument, stops the document view from loading forever when that guard rejects the request, and fixes an unhandled promise rejection when the project settings request fails.
- @joshbermanssw-
Add `data-test` hooks to list field controls The add and delete buttons on `list: true` fields had no stable selector, so end-to-end tests had to target Tailwind classes. Adds `data-test="list-<name>"` on the field wrapper, `data-test="add-item-<name>"` on the add button, and `data-test="delete-item-<name>.<index>"` on the delete button shared with group-list and blocks fields. Every hook carries the full field path. The wrapper hook lands on the outer field wrapper, so a nested list's delete buttons are descendants of the outer list's wrapper; a bare id would make `[data-test="list-x"] [data-test="delete-item"]` match the wrong row once lists nest.
- @kulesy-
Fix the collection list and collection search hanging on the loading screen when the session check says the user is not signed in. Both now settle and render instead of spinning until the page is reloaded. - Updated dependencies [[`4f90806`](https://github.com/tinacms/tinacms/commit/4f9080666308063332e16d96d00a75ff7348c011), [`00a8b82`](https://github.com/tinacms/tinacms/commit/00a8b826d0f7bd663f5d9069e487606f71b98cfe), [`00a8b82`](https://github.com/tinacms/tinacms/commit/00a8b826d0f7bd663f5d9069e487606f71b98cfe), [`de5c7d7`](https://github.com/tinacms/tinacms/commit/de5c7d72b67f589f1f5c4bccc5f5677e70cd7e2d)]: - @tinacms/mdx@2.2.1 - @tinacms/search@1.2.24 - @tinacms/bridge@0.3.1 - @tinacms/schema-tools@2.9.0
Version 3.12.0
Released on 8/17/2026
Minor Changes
Patch Changes
- @wicksipedia-
Add a dedicated `@tinacms/mdx/sanitize-url` subpath export containing just the URL-scheme sanitizer, and point `tinacms`'s rich-text renderer (`TinaMarkdown` / `StaticTinaMarkdown`) at it instead of the root `@tinacms/mdx` entry. Previously, importing `sanitizeUrl` pulled in `@tinacms/mdx`'s full remark/mdast/micromark markdown-parsing bundle (~2MB) into every site's client bundle, even though rich-text rendering only needs the ~15-line sanitizer. The root `@tinacms/mdx` export of `sanitizeUrl` is unchanged and still works.
- @joshbermanssw-
The media manager now lists assets from the v2 assets-api endpoint. Uploads and deletes are unchanged and stay on v1. Listing behaviour is identical — this is a transport-only move that sets up media search.
- @wicksipedia-
Give the exported Plate plugin arrays (`plugins`, `viewPlugins`, `createEditorPlugins`) an explicit type, so their emitted declarations no longer carry a `.pnpm/` store path.
Version 3.11.0
Released on 7/16/2026
Minor Changes
- @joshbermanssw-
Editorial-workflow saves (Save draft / Save to a new branch, and the media create-branch flow) now run a single branch-list lookup instead of two sequential ones, roughly halving the delay before the progress modal appears.
Patch Changes
- @kulesy-
`Button` now renders the shared loading-dots indicator automatically when `busy`, so every busy button gets a consistent spinner instead of each call site wiring its own (and some, like the account password form, were missing it entirely). The dots inherit the button text color so they stay visible across variants.
- @joshbermanssw-
Show a clear error when repo-based media is used with a self-hosted site, instead of a misleading "Bad Route" message.
Version 3.10.1
Released on 7/12/2026
Version 3.10.0
Released on 7/6/2026
Minor Changes
- @joshbermanssw-
editorial workflow - add toggle to switch PRs created between draft and ready to review mode
Patch Changes
- @joshbermanssw-
Update `@radix-ui/*` dependencies to their latest patch/minor releases and remove the unused `@radix-ui/react-checkbox` dependency
- @joshbermanssw-
Add a PostHog `editorial-workflow-save` event that records which save option was used in the "Save changes to new branch" modal (draft, ready for review, or publish), whether the save succeeded, and the failure reason when it didn't.
- @joshbermanssw-
Editorial workflow: replace the draft / ready-for-review toggle in the "Save changes to new branch" modal with a save-options dropdown (Save draft, Save (ready for review), Save and publish). The split button's main action reflects the editor's last choice (default Save draft, remembered via localStorage), and Save and publish is disabled with a tooltip on protected branches.
- @joshbermanssw-
refactor: replace hardcoded error-message string checks with shared error-identifier constants in `@tinacms/schema-tools`, so producers and consumers reference one source of truth instead of fragile `error.message.includes('...')` matching (#6777)
- @kulesy-
Unify folder-name validation with the document-filename and backend `relativePath` allowlist. The Create Folder modal now rejects names with disallowed characters (e.g. spaces) inline instead of letting the request fail on the backend, and a project-level `folderNameRegex` is layered on top of that baseline. The allowlist lives in a single shared constant in `@tinacms/schema-tools`.
- @Aibono1225-
Harden message handling in the `useEditState` hook so it validates the sender of incoming `message` events, matching the `isFromAdmin(event, trustedAdminOrigins)` check already used by `useTina`. The hook now also removes its `message` listener on unmount. Legitimate admin→preview behavior is unchanged.
Version 3.9.4
Released on 7/1/2026
Patch Changes
- @isaaclombardssw-
feat(tinacms): add a back-to-collection breadcrumb on the admin editor/create pages and in the visual editor sidebar, switch the breadcrumb separator from a chevron to a slash, show only the filename (not the full folder path) in the root breadcrumb across both editors, and truncate long crumbs so the trail no longer overflows
- @isaaclombardssw-
Improve global collection UX: global collections now appear once in the sidebar "Site" section (globe icon) instead of being duplicated under Collections, open directly in the form instead of a popup modal, and single-document global collections skip the document list and go straight to the form. Global collections with zero or multiple documents fall through to the normal list view.
- @wicksipedia-
Move `moment-timezone` to devDependencies so its timezone database no longer ships in the admin bundle. It was loaded via a non-tree-shakeable side-effect import, but production code never used the `moment.tz` API (only a unit test did). Removes ~39 KB gzip (~732 KB uncompressed) from the first admin load. No behavior change.
- @wicksipedia-
Remove the dead `mdx-field-plugin/plate/plugins/ui/icons.tsx` module (398 lines of unused inline-SVG icons). Its single consumed export (`EllipsisIcon`) now resolves from the shared `plate-ui/icons` module. No behavior change.
- @wicksipedia-
Standardize date handling on date-fns and remove the moment stack. `@tinacms/graphql` moves to date-fns v4 (collapsing the previous v2/v4 split), and `tinacms` drops `moment`, `moment-timezone`, and `react-datetime`. The date-field display label now formats with date-fns via a non-breaking moment→date-fns token converter, so existing `dateFormat`/`timeFormat` schemas (moment token syntax) keep working unchanged. Also removes the orphaned vendored react-datetime views. Net effect: the admin bundle no longer ships moment (~18.6 KB gzip smaller first load).
Version 3.9.3
Released on 6/15/2026
Patch Changes
- @Aibono1225-
Fix crash when reopening Global Configuration after navigating to a collection in the admin
Version 3.9.2
Released on 6/15/2026
Updated Dependencies
@tinacms/search@1.2.18
Version 3.9.1
Released on 6/5/2026
Patch Changes
- @JackDevAU-
Skip the filesystem-backed response cache on edge runtimes (Cloudflare Workers, Vercel Edge) where Node's `fs` API is present but unusable, which could otherwise hang concurrent identical queries. Adds a `cache` option to `createClient` to force-disable the cache.
Version 3.9.0
Released on 6/3/2026
Minor Changes
- @18-th-
Support Tina media uploads and deletes in the editorial workflow on protected branches. Media changes now prompt for a branch, write to that branch, switch the editor to it after the media operation succeeds, and continue through indexing and pull request creation with the same workflow progress UI as content edits.