# EmDash 1.1: publishing calendar, richer embeds and faster sites

> Source: <https://emdashcms.com/blog/emdash-1-1>
> Published: 2026-10-02 10:33:35+00:00

[Blog](https://emdashcms.com/blog)

# EmDash 1.1: publishing calendar, richer embeds and faster sites

Plan scheduled content in the new publishing calendar, build richer Portable Text pages, add Microsoft sign-in and make public sites more reliable.

EmDash 1.1 is the first release since [the 1.0 launch](https://emdashcms.com/blog/emdash-1-0), and it’s packed with useful additions for editors. 

It gives editorial teams a publishing calendar, adds safer ways to build rich content with HTML, CSS, JavaScript and embedded pages, and makes images easier to add and edit. It also adds Microsoft Entra ID sign-in and an experimental way for browser-based AI agents to search a public EmDash site.

The release includes a a large number of fixes across core, the admin, Cloudflare support and plugin tooling.

Highlights include:

For a Cloudflare site, update the matching core packages together and rebuild:

```
pnpm up --latest emdash
# or if you are using Cloudflare
pnpm up --latest emdash @emdash-cms/cloudflare
```

Add any EmDash plugin packages used by the site to the same `pnpm up` command. Node.js deployments can leave out `@emdash-cms/cloudflare`. 

As with any EmDash update, it’s a good idea to back up your site before upgrading. See [Update EmDash](https://docs.emdashcms.com/deployment/updating/) for the complete deployment and verification sequence.

## Plan and manage publishing from a calendar

The new [publishing calendar](https://docs.emdashcms.com/guides/working-with-content/#review-the-publishing-calendar) brings published entries, scheduled entries and scheduled updates together across every visible collection and locale. Contributors and higher roles can open **Calendar** from the sidebar or command palette; the dashboard's **Scheduled** count links there too.

**Month** shows a calendar grid, while **Agenda** groups entries by day. Entries use the site's time zone, with browser-local times shown when they differ. Filters narrow the view by collection, locale and state, and the view, month, filters and selected entry stay in the URL so the same calendar can be bookmarked or shared.

Selecting an entry opens a detail panel with its state, publication timeline, collection, locale, translations and bylines. People who can publish the entry can reschedule it, remove its schedule or publish an overdue entry immediately. Narrow screens open in Agenda view and use a date picker for the month view. A month is capped at 1,000 loaded entries; when the cap is reached, the calendar marks the days it could not load.

The calendar was contributed in [#3680](https://github.com/emdash-cms/emdash/pull/3680). Thanks [@khoinguyenpham04](https://github.com/khoinguyenpham04) for building it.

## Build richer stories in the editor

### HTML, CSS and JavaScript in isolated blocks

HTML blocks now have **HTML**, **CSS**, **JS** and **Preview** tabs. New blocks created in the admin or through `/html` in visual editing render in an isolated iframe by default. Their scripts can run, but the frame has an opaque origin: it cannot read the site's cookies, storage or pages, and the site's styles do not enter the frame. Choose **Inline** from the block menu when sanitized HTML should remain part of the page instead.

Existing HTML blocks, and blocks created through imports, REST or MCP, remain inline unless they explicitly set `isolated: true`. Anyone who can edit content can add JavaScript that runs for visitors after the entry is published, so sites should keep normal editorial trust and review controls in place.

Sites using EmDash's `PortableText` component get the new rendering automatically. A site with a custom `htmlBlock` renderer must pass isolated blocks to `HtmlBlock` from `emdash/ui`, or render them in an iframe whose sandbox omits `allow-same-origin`. Astro's built-in content security policy blocks the styles, scripts and automatic height inside isolated blocks; see [Add HTML, CSS and JavaScript](https://docs.emdashcms.com/guides/working-with-content/#add-html-css-and-javascript) before enabling both features together. This work shipped in [#3687](https://github.com/emdash-cms/emdash/pull/3687).

### Built-in iframe blocks

Type `/iframe` to embed a page from another site. Paste an embed code or an HTTPS URL into the **Code** tab; YouTube and Vimeo links are converted to their players, and **Preview** loads the embedded page when asked. On the public site, `Iframe` from `emdash/ui` renders the block as a responsive, lazy-loading, sandboxed iframe with a strict referrer policy.

If a plugin already defines an `iframe` block, the editor and public renderer continue to prefer the plugin's block. Sites using Astro's content security policy need to allow the intended hosts in `frame-src`. The full compatibility notes are in [#3688](https://github.com/emdash-cms/emdash/pull/3688) and the [iframe block documentation](https://docs.emdashcms.com/guides/working-with-content/#embed-a-page-from-another-site).

### Faster image authoring

Images can now be dropped into the Portable Text editor or pasted from the clipboard. They upload through the Media Library and land between the surrounding blocks, with an in-place preview while the upload runs and a useful message if it fails ([#3594](https://github.com/emdash-cms/emdash/pull/3594)).

Selecting an image now opens one toolbar for replacement, alt text, alignment, links, settings and deletion. Captions are edited directly below the image, and the alt-text control makes it clear when a real description is present ([#3657](https://github.com/emdash-cms/emdash/pull/3657)).

## Sign in with Microsoft Entra ID

Editors can now sign in with a Microsoft Entra ID work or school account. Register a web application in Entra, add the callback URL documented in the [authentication guide](https://docs.emdashcms.com/guides/authentication/#microsoft), and configure the provider:

``` js
import { microsoft } from "emdash/auth/providers/microsoft";

emdash({ authProviders: [microsoft()] });
```

Set `EMDASH_OAUTH_MICROSOFT_CLIENT_ID`, `EMDASH_OAUTH_MICROSOFT_CLIENT_SECRET` and `EMDASH_OAUTH_MICROSOFT_TENANT_ID`. EmDash also accepts the unprefixed forms. The provider stays disabled until all three are present.

A directory tenant ID gives EmDash a stronger basis for deciding whether the returned address is verified. With `common`, `organizations` or `consumers`, addresses are not treated as verified by default, so read the verification and account-linking rules before enabling self-signup. The provider was contributed in [#3254](https://github.com/emdash-cms/emdash/pull/3254). Thanks [@danielmlr](https://github.com/danielmlr).

## Let browser agents search published content

The new experimental `WebMcpSearch` component registers a read-only `search_site` tool in browsers that support WebMCP. It uses EmDash's public search API and returns titles, absolute URLs and plain-text excerpts from published, search-enabled collections. Unsupported browsers do nothing, and no search query runs until an agent calls the tool.

``` python
---
import WebMcpSearch from "emdash/ui/webmcp-search";
---

<WebMcpSearch collections={["posts", "pages"]} routeMap={{ posts: "/blog/:slug" }} />
```

WebMCP is still an experimental browser API, so its shape can change. See [Let browser agents search your public site](https://docs.emdashcms.com/guides/ai-tools/#let-browser-agents-search-your-public-site) for the component's options and trust boundary. Thanks [@swissky](https://github.com/swissky) for [#3632](https://github.com/emdash-cms/emdash/pull/3632).

## More reliable content, redirects and requests

EmDash 1.1 includes fixes that are especially useful on larger or longer-running sites:

- Lists sorted by fields that may be empty no longer skip entries between cursor pages. The fix covers the admin, REST API, MCP, plugin API and `getEmDashCollection()` , including taxonomy-filtered and custom-field queries ([#3662](https://github.com/emdash-cms/emdash/pull/3662) ). Cursors issued before the update still work.
- Redirect matching now reads a published representation in one query and checks one small row for changes, instead of repeatedly loading the whole table ([#3694](https://github.com/emdash-cms/emdash/pull/3694) ). Enabling a disabled redirect can no longer close a loop ([#3692](https://github.com/emdash-cms/emdash/pull/3692) ), and overlapping patterns now deterministically prefer the earliest-created rule ([#3693](https://github.com/emdash-cms/emdash/pull/3693) ). Existing loops are left in place so they can still be disabled.
- The image endpoint no longer waits for database setup and full runtime startup on every cold isolate, and D1 session bookmarks no longer prevent configured edge caching of signed-in media thumbnails ([#3652](https://github.com/emdash-cms/emdash/pull/3652) ).
- Menus and their items load in one query, and menu cache invalidation now covers seeding, imports and site transfers ([#3579](https://github.com/emdash-cms/emdash/pull/3579) ). Taxonomy-filtered collection queries also avoid walking the whole collection for small or multi-term result sets on D1 and SQLite ([#3402](https://github.com/emdash-cms/emdash/pull/3402) ).
- Returning visitors no longer receive a stale 304 when a cached page has no content-derived `Last-Modified` value ([#3528](https://github.com/emdash-cms/emdash/pull/3528) ). Rewritten content 404s no longer duplicate the visual editing toolbar or remain in the route cache after the missing entry is published ([#3650](https://github.com/emdash-cms/emdash/pull/3650) ).
- Signed-in image, feed and JSON responses no longer wait for the visual editing toolbar ([#3608](https://github.com/emdash-cms/emdash/pull/3608) ). Request-scoped database adapters now read the preview secret and IP salt once per isolate rather than on each relevant request ([#3651](https://github.com/emdash-cms/emdash/pull/3651) ).

## Upgrade notes

The release has no changelog entry marked as a breaking change, but a few setups need attention:

- If the site replaces EmDash's HTML block or Portable Text renderer, add support for `isolated: true` before editors publish new isolated HTML blocks.
- If Astro's content security policy is enabled, review its interaction with isolated HTML and iframe blocks. Add the intended iframe hosts to `frame-src` ; isolated HTML blocks otherwise lose their CSS, JavaScript and automatic height.
- Comment Turnstile verification now reads `EMDASH_TURNSTILE_SECRET_KEY` or`TURNSTILE_SECRET_KEY` at runtime ([#3622](https://github.com/emdash-cms/emdash/pull/3622) ). Node.js deployments must put the key in the running process's environment, not only in a build-time`.env` file. If a secret was present during a build and that server bundle was shared or stored, rotate the key.
- Byline translations created before 1.1 remain unlinked. Open each affected translation in the admin and link its user to restore the author credit. New translations preserve the source byline's user ([#3526](https://github.com/emdash-cms/emdash/pull/3526) ).
- A Cloudflare site can now complete setup without an explicit site URL by using the request origin. To use a custom domain, run setup on that domain or set `EMDASH_SITE_URL` first. Node.js,`wrangler dev` ,`astro preview` and self-hosted workerd deployments still need an explicit reachable origin ([#3711](https://github.com/emdash-cms/emdash/pull/3711) ).

## Smaller improvements and fixes

- Content save hooks now receive optional `locale` and`translationOf` fields, so trusted and sandboxed plugins can distinguish a new entry from a translation ([#3566](https://github.com/emdash-cms/emdash/pull/3566) ). Thanks[@stephanedemotte](https://github.com/stephanedemotte) .
- Partial `seo` and`social` settings updates now preserve fields that were left out ([#3625](https://github.com/emdash-cms/emdash/pull/3625) ). Publishing an older staged revision also succeeds after one of its fields has been removed from the collection schema ([#3617](https://github.com/emdash-cms/emdash/pull/3617) ); thanks[@enesismail](https://github.com/enesismail) .
- JPEG XL joins the default media upload allowlist, including browsers that report a generic MIME type ([#3580](https://github.com/emdash-cms/emdash/pull/3580) ). Upload placeholders now handle large or browser-unsupported formats consistently ([#3609](https://github.com/emdash-cms/emdash/pull/3609) ), and video uploads report dimensions without truncating the uploaded date ([#3685](https://github.com/emdash-cms/emdash/pull/3685) ).
- Registry and marketplace plugins show their public names on settings pages instead of internal IDs ([#3665](https://github.com/emdash-cms/emdash/pull/3665) ). The AT Protocol plugin's settings page loads its Recent Syncs table again ([#3647](https://github.com/emdash-cms/emdash/pull/3647) ); thanks[@nozamdavid](https://github.com/nozamdavid) .
- Block Kit forms in editor panels submit to their plugin instead of reloading the editor ([#3675](https://github.com/emdash-cms/emdash/pull/3675) ), and`select` elements display the selected option's label instead of its stored value ([#3673](https://github.com/emdash-cms/emdash/pull/3673) ). Thanks[@masonjames](https://github.com/masonjames) .
- Durable Object SQL writes now report changed table rows rather than counting index writes, fixing false stale-write outcomes in indexed tables ([#3633](https://github.com/emdash-cms/emdash/pull/3633) ). Thanks[@koikar](https://github.com/koikar) .
- The admin localizes date pickers for Danish and Georgian ([#3655](https://github.com/emdash-cms/emdash/pull/3655) ), completes more German strings ([#3581](https://github.com/emdash-cms/emdash/pull/3581) , thanks[@danielmlr](https://github.com/danielmlr) ), adds missing Hindi strings ([#3704](https://github.com/emdash-cms/emdash/pull/3704) , thanks[@CacheMeOwside](https://github.com/CacheMeOwside) ) and completes Swedish coverage ([#3624](https://github.com/emdash-cms/emdash/pull/3624) , thanks[@kegren](https://github.com/kegren) ).
- Reading settings update the date preview as you type, localize month names, suggest searchable time zones and reject new unrecognized values ([#3583](https://github.com/emdash-cms/emdash/pull/3583) ). The plugin release setup command also type-checks its interactive trigger selection while preserving cancellation ([#3582](https://github.com/emdash-cms/emdash/pull/3582) ). Thanks[@leostera](https://github.com/leostera) for both.
- Text typed after a newly applied editor link stays outside the link ([#3630](https://github.com/emdash-cms/emdash/pull/3630) ), while Widgets and hierarchical taxonomy screens no longer overflow on narrow displays ([#3676](https://github.com/emdash-cms/emdash/pull/3676) ).
- The MCP `content_list` description now suggests only accepted`orderBy` field names ([#3662](https://github.com/emdash-cms/emdash/pull/3662) ).

The same release commit also updates dependency-only packages `@emdash-cms/auth-atproto`, `@emdash-cms/plugin-embeds`, `@emdash-cms/plugin-test` and `@emdash-cms/sandbox-workerd`. `create-emdash`, `@emdash-cms/gutenberg-to-portable-text` and `@emdash-cms/x402` received matching 1.1.0 tags with no direct changelog entries.

Read the complete [`emdash@1.1.0` release](https://github.com/emdash-cms/emdash/releases/tag/emdash%401.1.0), then follow [Update EmDash](https://docs.emdashcms.com/deployment/updating/) to back up, build, deploy and verify the site.
