Apostrophe 4.33.0: Free and improved version history, and AI connectors in core

Published Estimated reading time: 6 min read

Apostrophe 4.33.0 moves version history into open source core, with a clearer view of what changed, who changed it and when. You can also now edit text fields right on the page, and a new shared AI engine gives developers one place to build AI features. Plus JSX, structured logging and security updates.

Apostrophe 4.33.0 brings three major improvements to the editing and development experience. Version history, called Document Versions in Apostrophe, has moved from a Pro extension into the open source core. It's also been improved to show a more detailed view of changes.

String and rich text fields can now be edited directly on the page, wherever your JSX, Nunjucks or Astro templates render them. Core also gains a shared, provider-agnostic AI engine for building AI-powered features across Apostrophe. This release also includes important improvements to JSX, logging, and security, so we recommend updating promptly.

Version history: now open source and part of core

Document version history, previously the Pro @apostrophecms-pro/document-versions extension, is now open source and built into Apostrophe core as @apostrophecms/document-versions. There is nothing extra to install and no license required. It is on for pages and pieces by default, and can be configured per type with the versions option.

It has also been reworked to show a much clearer view of what’s changed. The new interface makes it much easier to see what changed in each version, who made the change, and when. Drafts are now recorded as well as published versions, including whether AI was involved, and images and files have their own version history in the media manager. See the Document Versions guide for a full tour. Accessing this feature will work the same for editors, but experience once they open the Document Versions modal looks quite different.

If your project uses the extension, remove it when you upgrade. If you upgrade both, the extension will print a polite warning and do nothing since the feature is now in core. Your existing history is converted automatically when the site first starts. Some configuration options, REST API routes and methods have changed, so see the migration guide for the full steps, including notes for rolling deployments.

Improved DX for enabling in-context field editing

Areas have always been editable right where they appear on the page. Now ordinary schema fields can be too. This change makes it much easier for developers to deliver a true in-context visual editing experience for schema fields. Instead of opening the editor modal for a hero to change a headline, an editor clicks the headline on the page and types over it. Existing string fields work this way, as do fields of the new richText type, and custom field types can opt in.

This is a template choice, not a schema change. When a template renders a field with the new field tag that becomes editable where it appears. Fields rendered the usual way behave exactly as before, and every field stays in the editor modal and the REST API. The one exception is Astro: because it receives its data before its templates run, each field it edits in place also needs wysiwyg: true in the schema.

For example, take a widget with an ordinary string field:

javascript
// modules/hero-widget/index.js ​ export default { extend: '@apostrophecms/widget-type', fields: { add: { headline: { type: 'string', label: 'Headline' } } } };

Rendering it with Field in the widget's JSX template makes the headline editable right on the page:

javascript
// modules/hero-widget/views/widget.jsx ​ export default function ({ widget }, { Field }) { return ( <section className="hero"> <Field doc={widget} name="headline" with={{ tag: 'h1' }} /> </section> ); }

In edit mode, the editor takes on the page's own typography and takes up no more room than the text it replaces, so editing feels like typing on the page rather than filling in a form. Outside edit mode, only the value is rendered, so the tag is safe to use anywhere. See the inline editing guide for the details.

The new richText schema field type also means rich text no longer has to live in a widget inside an area. It uses the same editor, sanitization rules, and configuration as the rich text widget, so any customizations you've already made apply automatically.

AI connectors in core

Apostrophe now includes apos.ai, a provider-agnostic API for AI text and image generation. Features can be written once against a shared interface, while switching between Anthropic, OpenAI, Google, OpenAI-compatible services, or a local Ollama is handled through configuration rather than feature-specific integrations.

This connector engine is opt-in: no provider or API key is configured by default. It also provides shared infrastructure for tool calling, permissions, background jobs, retries, testing, and content extraction, giving current and future AI features a consistent way to work with Apostrophe content.

Our Pro modules are the first to use it:

  • Automatic TranslationAutomatic Translation can now translate through the AI provider already configured for the project, and now supports richText fields. Automatic translation still supports traditional providers like deepl as well.

  • SEO AssistantSEO Assistant 2.0 (major version bump, edit package.json to get it) now generates through apos.ai and no longer requires Automatic Translation. Existing projects should review the migration notes in the module README.

JSX across our documentation and starter kits

When we introduced JSX templates in Apostrophe 4.31.0, we said we would update our documentation over time to show JSX as the preferred authoring path. The documentation now leads with JSX, and our starter kits use JSX templates as well, so we recommend starting new projects with JSX. Nunjucks remains fully supported, and the two can coexist in the same project, so existing sites can keep their templates as they are or migrate one at a time.

Security fixes

This release fixes 22 responsibly disclosed security vulnerabilities across core and several supporting packages, three of them rated high severity. We recommend all users upgrade promptly. This release addresses:

  • Unauthenticated uploads that could fill the disk, in chunked uploads, the rich text CSV-to-table import and form submissions

  • Authorization gaps in several REST routes, page reordering, notifications and the AI Helper's image routes

  • Session and password hardening, including throttled password confirmation and cryptographically secure login tokens

  • Injection and XSS fixes in the admin UI, sanitize-html, Import/Export, CAPTCHA verification, the SQL database adapters and uploadfs

Full details and reporter credits are in the changelog below and in the published GitHub security advisories.

A few of these fixes change behavior you may be relying on:

  • viewRole now applies to logged-out visitors, as was always intended. In particular, users (viewRole: 'admin') reached through a relationship, such as the author of an article, will no longer load for logged-out visitors in templates or public APIs. Use a separate piece type, such as an "author" type, to represent people publicly. See our public-demo repository for an updated example of this.

  • apos.http.bigUploadMiddleware() now requires a logged-in user by default. A route that genuinely accepts anonymous uploads must pass its own authorize callback or authorize: false.

  • If you ever deployed uploadfs with an Azure SAS token in replicateClusters, revoke or rotate that token due to token exposure. However, it should be noted that this configuration did not actually work prior to this release. So it is unlikely that it was in practical use.

Additional improvements

Faster, more predictable undo and redo: Undo now reverses the edit itself instead of replaying your whole editing session and re-rendering the page. The page no longer flashes or jumps, the change is scrolled into view and briefly outlined, each undo is a small, fast save, and your typing history survives the page being refreshed around it.

Structured logging, everywhere: Apostrophe's structured logger now covers boot messages, warnings, runtime errors, long-running tasks, and diagnostics from modules and supporting libraries such as uploadfs and sanitize-html. Development output remains readable and colorized, while production defaults to one JSON object per line. A new top-level log option in app.js configures logging for the entire process, including multisite projects. Developers using custom loggers should review the changelog below for changes to event metadata.

Node.js 22.12 or newer required

Apostrophe now requires Node.js 22.12 or newer, since it relies on the ability to require() ES modules that arrived in that release. If you are on an earlier Node.js 22 release, upgrade Node.js before you update Apostrophe.

How to update to the latest version of ApostropheCMS

Update your projects with npm update and let us know what you think on our roadmap.