Tested by updating a copy of The Weekly Dash from EmDash 1.3.0 to 1.3.1, with Astro 7.3.5 and Node.js 24.
EmDash 1.3.1 came out on 18 October 2026, three days after 1.3.0. It's a bug-fix release: no new features to learn and no changes to how your database is set up, just fixes. 41 changes went into it. EmDash's two bots, emdashbot and emdash-autofix, wrote 23 of them, and a person checked and approved every one. Nine are mine, and seven other people sent in the rest, most of them translators. Thanks to all of them.
Most fixes are small, but a few affect your content and who gets to see it. If one of these sounds like your site, update soon:
- You unpublish posts or other entries in a content type that doesn't keep revisions (older versions). Until now, your next edits could be overwritten.
- Your site has subscribers or other users who shouldn't see drafts. Through the API, or an AI assistant connected over MCP, they could read unpublished content.
- Your site runs on Cloudflare Workers and shows categories or tags. One visitor leaving at the wrong moment could leave those pages stuck for everyone else.
EmDash 1.3.1 at a glance
- Your writing: edits survive unpublishing, a new entry asks before you leave it unsaved, and new links open in the same tab.
- Who sees what: drafts stay hidden from subscribers, and contributors only see buttons they can actually use.
- Cloudflare: a half-finished update shows an error instead of blank pages, category and tag pages no longer get stuck, and the cache no longer holds on to old site settings.
- Command line:
emdash loginfinds the right site, and the CLI stays signed in behind Cloudflare Access. - Languages: the admin now speaks Russian, and Japanese, Indonesian and Hindi are more complete.
Fixes that protect your writing
Edits no longer disappear after unpublishing
This is the fix that matters most. In a content type without revisions, once you unpublished an entry, the editor showed the old, published text again after every save. If you saved again, that old text overwrote your edits. Now your edits stay, also on entries you unpublished before the update (#4207). If you've unpublished entries like this before, take a quick look that your latest text is still there.
A new entry asks before you leave
If you started a new entry and clicked to another page in the admin before saving it for the first time, the entry was simply gone, without a warning. Now the admin asks first, and if you reload or close the tab, your browser asks too (#4206).
Links open in the same tab again
Every text link you added in the editor, or while editing on the page itself, was saved to open in a new tab, whether you wanted that or not. Nobody chose this: it was a default setting in a tool the editor is built on. New links now open in the same tab (#4106). Links you saved before the update still open in a new tab. To change one, add the link again.
Image captions are saved
In image fields, you could type a caption, but it was never saved. Now it is, and it also comes along when you export or import a seed file (#4201). The update can't bring back captions that were lost: pick the image again or edit its caption, then save and publish.
Who sees what
Three of my fixes are about who can see and do what. They build on the fixes for contributors in 1.3:
- Drafts stay private. Subscribers and other users who aren't allowed to read drafts could still use the API to see which categories, tags and translations a draft or scheduled post had. An AI assistant connected over MCP could even read the unpublished changes themselves. Now they get "not found", and over MCP they only see what's published (#4179).
- Only buttons that work. Contributors and authors saw Duplicate, Publish, Unpublish and Schedule on entries where clicking them only got a "no". An entry they can't save now opens read-only, with a note explaining why (#4177).
- User count for admins only. The dashboard showed how many users the site has to people who aren't allowed to see the user list. Now only administrators see that card (#4181).
Fewer surprises on Cloudflare
An error message instead of blank pages
When you update EmDash, your site normally brings its database up to date by itself on the first visit after the deploy. EmDash calls these steps migrations. If they didn't finish, a site on Workers kept serving pages without their content and told everyone that all was well. Tools that check whether your site is up saw nothing wrong. Now the site answers with an error, 503 ("temporarily unavailable"), until the database is up to date (#4069).
Also, a live site no longer starts the really big updates on its own, the kind that touch every entry and every older version, such as the date update from 0.39.0. If you're coming from 0.38 or older, run emdash migrate before you deploy, as the docs explain under Apply large content migrations from the CLI. If your site shows a 503 after an update, look at your Worker's log in the Cloudflare dashboard. It tells you what's wrong: either a database update is still waiting, which emdash migrate applies, or an earlier one got stuck and is blocking the rest. For that case, see Release a stuck migration lock.
Category and tag pages no longer get stuck
On Workers, one visitor could break every page that shows categories, tags or how many posts each one has. If they left at just the wrong moment, while EmDash was loading its list of categories, tags or content types, every later visitor handled by the same copy of your site waited until Cloudflare gave up with a 524 error. Now one visitor leaving early no longer holds up anyone else (#4203).
The cache lets go of old settings
After the cache was cleared, pages could get cached again with old site settings: an outdated title, an old logo, or a missing tag that proves to Google and others that the site is yours. Now EmDash reads the settings fresh when it fills the cache, and it double-checks the settings it remembers once they're 30 seconds old (#4226). How we use the cache on this site is in Edge caching for EmDash on Cloudflare.
Smaller fixes on Cloudflare
- Search is quicker on D1: it asks the database fewer times, even when nothing matches, and an empty search doesn't ask at all (#4220).
- Plugins that store data no longer rewrite the same setup every time the site starts, which saves database writes on D1 (#4229).
- Many at once: changing up to 100 comments at once, or saving a post with more than 100 authors, no longer fails with a database error (#4256).
- Starter content: if several visitors reached a new site at the same moment, its starter menus and widgets could show up twice. On D1 that's fixed (#4225).
- Image quality: if you asked Astro for lighter images with
quality="low"and similar, EmDash on Cloudflare still sent the full-size original. Nowlow,mid,highandmaxmean 25, 50, 80 and 100 (#4221).
Redirects and menus
- Old forwarding addresses: when you change a post's address (its slug), EmDash forwards visitors from the old address to the new one. If you later published a new entry at the old address, visitors never got to it. Now publishing removes the old forwarding (#4074).
- Menus: menu items whose parent was missing, sat in another menu, or formed a loop could vanish from the menu on your site. Such changes are now refused with an error, and menus that already contain broken data stay editable (#4255).
Small fixes in the admin
- The separator between page title and site name, under Settings → SEO, can now be deleted and replaced. The default shows up as a hint in the empty field (#4241).
- Screen readers now read out field names in plugin block dialogs (#4197), and confirmation pop-ups from plugins no longer have their text pressed against the edges (#4219).
- The sign-in page no longer asks you to "Enter your handle" for every sign-in method, only where there's a handle to enter (#4013).
- Images with a blurry loading preview now keep the focal point you set (#4170).
- If you run your site on your own server with Node.js and keep media in R2 or other S3-compatible storage, previews and downloads no longer start timing out after repeated requests (#4043).
- Forms plugin: fields that should only appear under a condition stay hidden until it's met (#4249). A single checkbox now sits next to its label instead of stretching across the form (#4247), and a ticked box is saved as ticked (#4248).
The command line behind Cloudflare Access
Two fixes for problems I described in our article on the API, CLI and MCP:
emdash loginandemdash logoutnow go to the site inEMDASH_URL, like every other command. Before, without--url, they always triedhttp://localhost:4321(#4180).- When the sign-in from
emdash loginneeded renewing, every command behind Cloudflare Access failed: the renewal request went out without the extra headers Access asks for. Now it sends them, just like every other request (#4239).
The admin in more languages
Russian is new and ready to pick in the language menu (#3556). Japanese (#4222, #4230, #4257), Indonesian (#4142, #4211) and Hindi (#4104) are more complete, and Indonesian already covers the new revision history and the AI training switch from 1.3. Italian now has its navigation translated but can't be picked yet (#4264). Thank you to everyone translating EmDash.
For developers
If you build templates, plugins or scripts, these are for you:
- Image captions: read
captiondirectly on the image field value. It's now in the generated types too, and the oldermeta.captionstays in sync where it exists (#4201). - Errors no longer hidden: when a route threw an error, the redirect middleware ran it a second time and hid the original error. Now it reaches Astro (#4161).
- Locales with codes: if your Astro config gives a locale a path and separate codes, like
{ path: "en", codes: ["en-US"] }, passingAstro.currentLocaleto queries now finds entries stored under either one (#4224). - Custom fields during a migration:
getEmDashCollection()returned nothing whenwhereororderByused a custom field while migration086_relations_structuralwas still pending (#4024). - D1 column limit: when a collection hit D1's column limit, a new field stayed in the schema without a column. Once you free a column, you can create it without a
FIELD_EXISTSerror (#4070). <Image>fromemdash/uiaccepts thequalityprop inastro check(#4221).- Wrangler is now optional for
@emdash-cms/cloudflareand only needed if you usesandbox()(#4234). EmDashClientfromemdash/clientnow runs yourinterceptorson its automatic token refresh too (#4239).- Dashboard API:
userCountinGET /_emdash/api/dashboardnow only goes to administrators (#4181).
Before you update: what to check
1.3.1 makes no changes to how your database is set up, and most fixes need nothing from you. Have a quick look at these points first. Most of them only matter if you build templates or scripts:
- Coming from 0.38 or older: on Workers, run
emdash migratebefore you deploy. Otherwise your site shows a 503 until the database is up to date (#4069). - Links in new tabs: new text links open in the same tab, old ones still open a new tab. If your template adds
target="_blank"itself, nothing changes for you (#4106). - Image captions: read
captionin your templates. Captions lost before the update don't come back by themselves (#4201). - AI agents over MCP: for users who can't read drafts,
content_getnow returns the published version. If an agent signs in as such a user and needs drafts, give it a role that may read them (#4179). - Scripts that edit menus: an invalid parent now gets an error instead of being saved (#4255).
- Locales with codes: entries saved under both the path and a code stay separate. EmDash doesn't merge or delete anything, so lists may show both (#4224).
- Signing in with AT Protocol: this sign-in option now needs
@lingui/react(Lingui 5). If your package manager doesn't install it for you, add it yourself (#4013).
How to update to EmDash 1.3.1
As always, an update is a deployment: you install the new version and put your site online again. Your content stays where it is, in the database. The easiest way is upgrade-emdash:
npx upgrade-emdash@latest
npm run deployI tried this on a copy of The Weekly Dash. A test run with --dry-run showed two packages moving from 1.3.0 to 1.3.1, with 25 changelog entries. The real update took 15 seconds, needed no database changes, refreshed the skills for AI agents in .agents/skills, and the site built without errors afterwards. The Weekly Dash itself moved to 1.3.1 the same evening, so the page you're reading now runs on it.
If you'd rather do it by hand, a site from the Cloudflare template needs two commands:
npm install emdash@latest @emdash-cms/cloudflare@latest
npm run deployKeep both packages on the same version, or the build will warn you. If you want a restore point first, and a way back if something goes wrong, Update EmDash walks you through it step by step.
What about you?
Did one of these bugs catch you out, or is something still not working after 1.3.1? Tell us in the comments below. Kevin and I are both EmDash maintainers, and we read the comments: what you tell us here goes straight back into the project.

Comments
First-time comments appear once we've approved them. How we handle your details