{"slug":"framework","name":"Framework","orgs":[{"slug":"bun","name":"Bun","domain":"bun.com","avatarUrl":"https://media.releases.sh/orgs/bun.png"},{"slug":"deno","name":"Deno","domain":"deno.com","avatarUrl":"https://media.releases.sh/orgs/deno.png"},{"slug":"expo","name":"Expo","domain":"expo.dev","avatarUrl":"https://media.releases.sh/orgs/expo.png"},{"slug":"nuxt","name":"Nuxt","domain":"nuxt.com","avatarUrl":"https://media.releases.sh/orgs/nuxt.png"},{"slug":"svelte","name":"Svelte","domain":"svelte.dev","avatarUrl":"https://media.releases.sh/orgs/svelte.png"},{"slug":"tailwind-css","name":"Tailwind CSS","domain":"tailwindcss.com","avatarUrl":"https://media.releases.sh/orgs/tailwind-css.png"},{"slug":"wordpress","name":"WordPress","domain":"wordpress.org","avatarUrl":"https://media.releases.sh/orgs/wordpress.png"},{"slug":"htmx","name":"htmx","domain":null,"avatarUrl":"https://media.releases.sh/orgs/htmx.png"}],"products":[{"slug":"headless-ui","name":"Headless UI","description":"Unstyled, accessible UI components for React and Vue","orgSlug":"tailwind-css","orgName":"Tailwind CSS"},{"slug":"nextjs","name":"Next.js","description":"React framework for production","orgSlug":"vercel","orgName":"Vercel"},{"slug":"svelte","name":"Svelte","description":"The Svelte compiler — a UI component framework that compiles components to efficient vanilla JavaScript at build time.","orgSlug":"svelte","orgName":"Svelte"},{"slug":"sveltekit","name":"SvelteKit","description":"Full-stack web framework built on Svelte with file-based routing, SSR, and adapter-based deployment.","orgSlug":"svelte","orgName":"Svelte"}],"releases":[{"id":"rel_VKdUhQ4C-fy8vte9Xq1IY","version":"v2.9.0","type":"feature","title":"v2.9.0","summary":"Deno.serve automatic compression is now disabled by default (opt-in via --compress/compress config). This release also ships the `deno desktop` subcommand for building cross-platform desktop apps, plus `deno watch`, `deno link`/`unlink`, `deno list`, CSS module imports, Web Locks API, Happy Eyeballs for TCP/TLS connections, and built-in snapshot testing.","titleGenerated":"Deno v2.9.0 ships desktop subcommand, Deno.serve compression now opt-in","titleShort":"Deno.serve compression now opt-in; desktop apps land","content":"### 2.9.0 / 2026.06.25\r\n\r\nRead more: http://deno.com/blog/v2.9\r\n\r\n- feat(bundle): add --declaration flag to generate rolled-up .d.ts files\r\n  (#33838)\r\n- feat(cli): add `deno link` and `deno unlink` subcommands (#34359)\r\n- feat(cli): add `deno watch` subcommand (#35301)\r\n- feat(cli): add deno list subcommand to list declared dependencies (#34972)\r\n- feat(cli): auto-migrate pnpm-workspace.yaml on resolution failure (#34993)\r\n- feat(cli): provide a `node` on PATH when Node.js is not installed (#34969)\r\n- feat(compile): persist Web Storage/KV in a per-app data directory (#34618)\r\n- feat(coverage): add configurable coverage thresholds (#35056)\r\n- feat(desktop): --compress for self-extracting app bundles (#35420)\r\n- feat(desktop): add Linux .deb and .rpm installer output formats (#35296)\r\n- feat(desktop): add Windows .msi installer output format (#35378)\r\n- feat(desktop): autodetect Vite framework (#35470)\r\n- feat(desktop): default UI backend to webview (#35442)\r\n- feat(ext/crypto): support remaining modern WebCrypto algorithms (#35223)\r\n- feat(ext/http): deprecation warning for legacy request abort (#34397)\r\n- feat(ext/net): implement Happy Eyeballs for `Deno.connect` and\r\n  `Deno.connectTls` (#31726)\r\n- feat(ext/node): implement node:test mock.module (#35329)\r\n- feat(ext/node): implement node:test mock.timers (#33946)\r\n- feat(ext/web): web locks api (#31166)\r\n- feat(fmt): add sortNamedImports and sortNamedExports options (#33313)\r\n- feat(fmt): infer config from .editorconfig (#34071)\r\n- feat(fmt): use lax-css for CSS, SCSS, and Less (#35160)\r\n- feat(fmt): use lax-markup for HTML, XML, SVG, and components (#35174)\r\n- feat(fmt): use lax-sql for SQL formatting (#35161)\r\n- feat(http): allow disabling serve compression (#35253)\r\n- feat(http): disable Deno.serve automatic compression by default (#35486)\r\n- feat(install): create node_modules for workspace members (#34970)\r\n- feat(install): seed deno.lock from bun.lock (#35394)\r\n- feat(install): seed deno.lock from package-lock.json (#35330)\r\n- feat(install): seed deno.lock from pnpm-lock.yaml (#35346)\r\n- feat(install): seed deno.lock from yarn.lock (#35350)\r\n- feat(install): warn on package.json engines mismatch (#34225)\r\n- feat(lockfile): auto-resolve git merge conflicts in deno.lock (#34726)\r\n- feat(lsp): add inferred type request (#35099)\r\n- feat(napi): implement Node-API version 10 (#35270)\r\n- feat(node): bump reported process.version to v26.3.0 (#34747)\r\n- feat(npm): install jsr deps into node_modules via npm-compat registry (#35029)\r\n- feat(npm): publishing-trust ranking and no-downgrade trust policy (#34927)\r\n- feat(runtime): add request_builder_hook for fetch token and cdn-loop headers\r\n  (#35088)\r\n- feat(task): add --if-present flag to deno task (#35315)\r\n- feat(task): add --jobs/--concurrency flag to deno task (#35318)\r\n- feat(task): input-based caching with files/output/env (#34509)\r\n- feat(task): set npm_execpath, npm_node_execpath and npm_command for\r\n  package.json scripts (#35317)\r\n- feat(test): add --changed and --related flags to deno test (#35199)\r\n- feat(test): add --shard flag to split a test run across machines (#35057)\r\n- feat(test): add Deno.test.each for parameterized tests (#34938)\r\n- feat(test): add retry and repeats options to Deno.test (#35053)\r\n- feat(test): built-in snapshot testing via t.assertSnapshot (#35139)\r\n- feat(test): show sub-millisecond test durations (#35200)\r\n- feat(unstable): CSS module imports (with { type: \"css\" }) (#35093)\r\n- feat: `deno desktop` subcommand (#33441)\r\n- feat: `deno remove --global` as alias for `deno uninstall --global` (#35327)\r\n- feat: add \"preferPackageJson\" deno.json setting (#35392)\r\n- feat: add stable --unsafe-proto flag (#34738)\r\n- feat: enable default minimum dependency age (#35458)\r\n- feat: stabilize \"links\" field in deno.json (#34996)\r\n- feat: stabilize bare node built-in resolution (#33316)\r\n- feat: support `ignore` option in `Deno.watchFs` (#31582)\r\n- feat: support navigator.userAgentData (#34743)\r\n- fix(check): treat npm .d.ts as CJS based on package.json (#35166)\r\n- fix(core): always register isolate to prevent silent foreground task drop\r\n  (#35408)\r\n- fix(core): don't cache WebIDL sequence keys in thread-local v8::Eternal\r\n  (#35462)\r\n- fix(core): handle async op promise id wraparound (#35126)\r\n- fix(core): make uv_compat ready queues thread-safe (#35175)\r\n- fix(core): preserve custom .stack getters in error/test formatter (#35246)\r\n- fix(core): unwrap global exports in Wasm ESM integration (#34912)\r\n- fix(coverage): don't panic in summary reporter without a common root (#35211)\r\n- fix(coverage): merge coverage for modules loaded with different hash/search\r\n  params (#35354)\r\n- fix(deploy): use JSR latest for deploy CLI (#35493)\r\n- fix(desktop): Wayland support for CEF and webview backends (#35425)\r\n- fix(desktop): add Bluetooth usage descriptions to macOS Info.plist (#35472)\r\n- fix(desktop): add macOS desktop Info.plist keys (#35484)\r\n- fix(desktop): correct libdenort unpack path with non-executable extension\r\n  (#35267)\r\n- fix(desktop): hide bundled libc++ symbols so the desktop runtime can be\r\n  dlopen'd on Linux (#35424)\r\n- fix(desktop): use native Wayland instead of XWayland on Wayland systems\r\n  (#35485)\r\n- fix(ext/crypto): allow deriving AES-OCB keys (#35426)\r\n- fix(ext/crypto): clamp X448 scalar per RFC 7748 (#35157)\r\n- fix(ext/crypto): pad JWK to multiple of 8 bytes for AES-KW wrap (#35475)\r\n- fix(ext/fetch): keep content-encoding and content-length on decompressed\r\n  responses (#35124)\r\n- fix(ext/fetch): require --allow-net for Unix proxy in createHttpClient\r\n  (#35231)\r\n- fix(ext/fs): truncate should not follow a terminal symlink (#35239)\r\n- fix(ext/http): apply automatic compression for zero-arg serve handlers\r\n  (#35490)\r\n- fix(ext/http): close active WebSockets on Deno.serve shutdown (#35105)\r\n- fix(ext/kv): validate remote KV URL when opening the connection (#35106)\r\n- fix(ext/napi): restore Explicit microtask policy in napi_resolve_deferred\r\n  (#35212)\r\n- fix(ext/net): cancel in-flight reads when closing TCP/Unix/Vsock streams\r\n  (#35294)\r\n- fix(ext/net): set transport on address for TlsListener (#35258)\r\n- fix(ext/node): allow registerHooks with no resolve or load hook (#35235)\r\n- fix(ext/node): avoid panic deserializing empty buffers over child_process IPC\r\n  (#35340)\r\n- fix(ext/node): avoid panic when vm.SourceTextModule uses import.meta (#35375)\r\n- fix(ext/node): check --allow-net for proxied request target in node:http(s)\r\n  (#35241)\r\n- fix(ext/node): don't apply requestTimeout to active streaming responses\r\n  (#35291)\r\n- fix(ext/node): fail node:test on unhandled rejection and enforce timeout\r\n  (#35297)\r\n- fix(ext/node): fix `node:test` hook ordering and error handling (#35393)\r\n- fix(ext/node): forward permissions when spawning deno with subcommand args\r\n  (#35443)\r\n- fix(ext/node): implement process.resourceUsage() (#35468)\r\n- fix(ext/node): implement t.assert.fileSnapshot for node:test (#35478)\r\n- fix(ext/node): implement test.TestContext.runOnly (#35158)\r\n- fix(ext/node): implement worker_threads.isInternalThread (#35234)\r\n- fix(ext/node): import attributes and custom module types in registerHooks ESM\r\n  hooks (#35028)\r\n- fix(ext/node): initialize named stdio exports lazily (#35428)\r\n- fix(ext/node): keep dns.lookup permission token internal (#35224)\r\n- fix(ext/node): make registerHooks resolve hook work for nested imports\r\n  (#35169)\r\n- fix(ext/node): preserve AsyncLocalStorage context across node:net callbacks\r\n  (#35237)\r\n- fix(ext/node): restore Node binding signature for zlib write/writeSync\r\n  (#35238)\r\n- fix(ext/node): single source of truth for emulated Node version (#35273)\r\n- fix(ext/node): stop coloring non-TTY streams in `util.styleText` (#35236)\r\n- fix(ext/node): support AbortSignal.timeout in node:test mock.timers (#35474)\r\n- fix(ext/node): support HTTP/2 on the DENO_SERVE_ADDRESS override listener\r\n  (#35089)\r\n- fix(ext/node): trace v8 serializer delegate (#35132)\r\n- fix(ext/signals): build windows-sys only on Windows (#35283)\r\n- fix(install): remove stale root node_modules symlink on deno remove (#35137)\r\n- fix(install): resolve package.json dependencies in global install (#35135)\r\n- fix(install): seed pnpm workspace members and catalog deps (#35376)\r\n- fix(jupyter): report cell errors instead of failing silently (#35328)\r\n- fix(lsp): honor --env-file from deno.json `test` task in test runner (#34905)\r\n- fix(lsp): include tsconfig roots in script names (#34136)\r\n- fix(lsp): make requests work for files opened from node_modules (#35176)\r\n- fix(lsp): report TS2307 for unresolved imports in .d.ts entrypoints (#35469)\r\n- fix(node): expose lazy console stdio streams (`console._stdout`/`_stderr`)\r\n  (#35488)\r\n- fix(node): propagate source thread id to `process` `workerMessage` event\r\n  (#35374)\r\n- fix(node/test): route nested top-level test() to a subtest (#35406)\r\n- fix(npm): avoid spurious npm re-resolution that fails under --cached-only\r\n  (#35051)\r\n- fix(npm): don't apply import map to npm bin main module (#35097)\r\n- fix(npm): make peer dependency warning actionable and show importers (#35242)\r\n- fix(npm): slim cached full packument when minimumDependencyAge is set (#35285)\r\n- fix(npm): support `catalog:` protocol in deno.json imports (#35168)\r\n- fix(npm): symlink workspace npm members into root node_modules by name\r\n  (#35383)\r\n- fix(pack): include assets matched by publish.include in the tarball (#35331)\r\n- fix(pack): surface slow type diagnostics (#35379)\r\n- fix(permissions): don't require --allow-run for process.kill on self (#34382)\r\n- fix(permissions): require --allow-net for Unix domain socket ops (#34395)\r\n- fix(permissions): treat Windows `\\\\?\\` verbatim paths as equivalent (#35096)\r\n- fix(publish): continue publishing workspace after a package fails (#35133)\r\n- fix(publish): skip already-published versions before type checking (#35134)\r\n- fix(repl): highlight regex literals correctly (#35103)\r\n- fix(resolver): better hint when importing a linked package by the wrong name\r\n  (#35319)\r\n- fix(resolver): resolve linked packages by bare specifier (#35228)\r\n- fix(runtime): capture blob worker roots before revocation (#35128)\r\n- fix(runtime): don't silently lose Deno.watchFs events (#35122)\r\n- fix(runtime): make Deno.test.* sub-methods no-op under `deno run` (#35344)\r\n- fix(runtime): suggest --unstable-unsafe-proto after **proto** access (#35192)\r\n- fix(serve): exit cleanly on SIGTERM/SIGINT in deno serve (#32862)\r\n- fix(serve): shut down old workers on watcher restart (#35136)\r\n- fix(serve): update request_signal_streaming spec for legacy abort warning\r\n  (#35193)\r\n- fix(task): set npm lifecycle env vars when running package.json scripts\r\n  (#35252)\r\n- fix(test): ignorelist leaks from sanitizer-ignoring tests (#35005)\r\n- fix(test): skip invalid doctest import bindings (#35382)\r\n- fix(test/node): mark test-worker-fshandles-open-close-on-termination as flaky\r\n  (#35387)\r\n- fix(tests): skip npm/playwright_compat on windows-aarch64 (#35358)\r\n- fix(update): refetch npm metadata so stale cache doesn't hide newer versions\r\n  (#35380)\r\n- fix(upgrade): stream zstd delta patch to avoid 2GiB OOM (#35284)\r\n- fix: Headers inspect for duplicate Set-Cookie values (#35461)\r\n- fix: accept U+30FB KATAKANA MIDDLE DOT in identifiers (#35147)\r\n- fix: cache 404 responses for remote modules (#35138)\r\n- perf(core): reduce snapshotted cppgc op member templates (#35298)\r\n- perf(core): skip source ASCII checks in release runtime setup (#35186)\r\n- perf(ext/crypto): port WebCrypto from JS to Rust (#34966)\r\n- perf(ext/web): port console/inspect to Rust (cppgc object wrap) (#35087)\r\n- perf(macos): enable chained fixups to cut pre-main startup (~0.8ms) (#35409)\r\n- perf(runtime): lazy-load node:buffer and node:timers globals (#35373)\r\n- perf(snapshot): guard against lazy modules leaking into eager snapshot\r\n  (#35332)\r\n- perf(snapshot): minify snapshot sources (#35183)\r\n- perf(workers): incremental message-passing cleanups (#35108)\r\n- perf: V8 code cache for residual lazy-loaded ESM modules (#35338)\r\n- perf: gate eager node bootstrap to node workers (#35337)\r\n- perf: lazy-load OSX frameworks with `lzld` (#35341)\r\n- perf: startup profiling instrumentation + clap fast-path (#35263)\r\n- perf: startup time (22ms -> 15ms) (#34450)","publishedAt":"2026-06-25T15:00:40.000Z","url":"https://github.com/denoland/deno/releases/tag/v2.9.0","media":[],"prerelease":false,"source":{"slug":"deno","name":"Deno","type":"github"},"org":{"slug":"deno","name":"Deno"},"product":null,"groupSlug":"deno","groupName":"Deno","coverageCount":0,"composition":{"bugs":1,"features":5,"enhancements":3}},{"id":"rel_6kNiPfaX3_xVG-lQ5o6yf","version":"2.9","type":"feature","title":"Deno 2.9","summary":"Deno 2.9 introduces `deno desktop`, a new command that builds native desktop applications from web framework projects with no extra toolchain, producing a single distributable binary with built-in Deno.* desktop APIs. Performance gains include 2x faster cold startup (17ms), up to 3x less RSS memory, and 27% higher realworld Deno.serve throughput. Also adds direct npm, pnpm, yarn, and Bun lockfile reading in `deno install`, CSS module imports, and a stronger test runner.","titleGenerated":"Deno 2.9 introduces deno desktop for native desktop apps and cuts startup time in half","titleShort":"Deno desktop ships; startup 2x faster, memory 3x less","content":"# Deno 2.9\n\nJune 25, 2026\n\nDeno 2.9 is here, headlined by `deno desktop`, a new way to build native desktop applications from the web stack you already know, with no Electron boilerplate and a single binary at the end. It's also the easiest release yet to bring an existing Node project over: `deno install` now reads npm, pnpm, yarn, and Bun lockfiles directly, so switching your package manager to Deno takes a couple of commands, not a migration. There's plenty more below, from CSS module imports and a much stronger test runner to faster startup and Node.js 26 compatibility.\n\nTo upgrade to Deno 2.9, run the following in your terminal:\n\n```\ndeno upgrade\n```\n\nIf Deno is not yet installed, run one of the following commands to install or [learn how to install it here](https://docs.deno.com/runtime/manual/getting_started/installation).\n\n```\n# Using Shell (macOS and Linux):\ncurl -fsSL https://deno.land/install.sh | sh\n\n# Using PowerShell (Windows):\niwr https://deno.land/install.ps1 -useb | iex\n```\n\n## `deno desktop`\n\nBuilding a desktop app has usually meant pulling in Electron or Tauri, wiring up a separate toolchain, and shipping a bundle that bears little resemblance to the rest of your project.\n\nDeno 2.9 introduces `deno desktop`. Point it at a script (or a web framework project) and it produces a native, self-contained desktop application where the UI runs in a webview, your logic runs in Deno, and the whole thing compiles down to a single distributable binary ([#33441](https://github.com/denoland/deno/pull/33441)).\n\n> `deno desktop` is **experimental** in 2.9. The surface described here is stabilizing and some platform features are still landing.\n\nThe simplest app is an entrypoint that serves your UI. `Deno.serve()` inside a desktop entrypoint automatically binds to the port the webview opens, so there's no port wiring to do:\n\nmain.ts\n\n```\nDeno.serve(() =>\n  new Response(\n    \"<!DOCTYPE html><h1>Hello from Deno desktop 👋</h1>\",\n    { headers: { \"content-type\": \"text/html\" } },\n  )\n);\n```\n\n```\n$ deno desktop main.ts\n```\n\nThat opens a native window rendering your page. `deno desktop` shares the same framework detection as [`deno compile`](https://deno.com/blog/v2.8#framework-detection): run it with no entrypoint (or `deno desktop .`) and it auto-detects the web framework in the current directory (Next.js, Astro, Fresh, Remix, Nuxt, SvelteKit, SolidStart, TanStack Start, and Vite SSR are all supported), builds it, and wraps the result:\n\n```\n$ deno desktop          # auto-detect the framework in the current directory\n$ deno desktop --hmr    # run with Hot Module Replacement during development\n```\n\n### Native desktop APIs\n\nRicher apps get a full set of native desktop APIs built right into the runtime under `Deno.*`, available immediately with no extra dependencies. `Deno.BrowserWindow` gives you programmatic control over window size, position, visibility, menus, and DevTools, and lets you bridge between the webview and Deno: bind a function in the entrypoint with `window.bind()` and call it from page JavaScript via the `bindings` namespace. There's also `Deno.Tray` for system-tray icons and panels, and `Deno.Dock` on macOS:\n\ntray.ts\n\n```\nconst tray = new Deno.Tray();\ntray.setIcon(iconBytes);\nconst panel = tray.attachPanel({ url: \"https://localhost:8000/panel\" });\npanel.window.bind(\"doThing\", async () => {/* ... */});\n```\n\n`prompt()`, `alert()`, and `confirm()` render as native dialogs, and `Deno.autoUpdate()` wires up a polling auto-updater that applies binary patches in the background.\n\n### Webview or CEF\n\nEvery desktop app needs a browser engine to draw its UI, and `deno desktop` ships two, selected with `--backend`:\n\n- **`webview`** (the default) renders with the operating system's built-in engine: WebView2 on Windows, WebKit on macOS and Linux. Nothing extra is bundled, so binaries stay small and launch fast. The tradeoff is that rendering follows whatever engine the host ships.\n- **`cef`** bundles Chromium through the Chromium Embedded Framework, so every user gets the same modern engine on every platform. That adds tens of megabytes and a download at build time, but guarantees identical rendering and the latest web-platform features everywhere.\n\n```\n$ deno desktop main.ts                  # native webview (default)\n$ deno desktop --backend cef main.ts    # bundled Chromium\n```\n\nMost apps are happiest on the default `webview`; reach for `cef` when you need a guaranteed-identical engine on every platform.\n\n### Distribution\n\nBecause `deno desktop` is built on the same machinery as `deno compile`, the output is a standalone binary with your code and assets embedded. The format follows the extension you pass to `--output`: `.app` and `.dmg` on macOS, `.exe` or an `.msi` installer on Windows, and `.AppImage`, `.deb`, or `.rpm` on Linux.\n\nYou don't need a fleet of machines to ship cross-platform, though. `--target` cross-compiles the app to any supported platform and `--all-targets` builds them all in one command, so a single Linux CI runner (or your laptop) can turn out binaries for Windows, macOS, and Linux together. The Windows `.msi` and Linux `.deb` / `.rpm` installers are authored in pure Rust, so they're produced from any host with no platform-specific packaging toolchain:\n\n```\n$ deno desktop --output MyApp.dmg main.ts                 # build for the host\n$ deno desktop --target x86_64-pc-windows-msvc main.ts    # cross-compile to Windows\n$ deno desktop --all-targets main.ts                      # build every supported target\n```\n\nThe five supported targets match `deno compile`: Linux x64/arm64, Windows x64, and macOS x64/arm64. For smaller artifacts, `--compress` ships the runtime and UI backend as a self-extracting bundle that unpacks on first launch.\n\nFor the full guides, see the [`deno desktop` documentation](https://docs.deno.com/runtime/desktop/). And for a complete, real-world example, [denidian](https://github.com/bartlomieju/denidian) is a note-taking app built with `deno desktop`:\n\n![The denidian note-taking app, built with deno desktop, running as a native macOS window](/blog/v2.9/denidian.png)\n\n## Performance\n\nDeno 2.9 ships broad performance gains in startup time, memory use, and HTTP throughput. The `Deno.serve` benchmarks below run three workloads at concurrency 100: a plaintext `Hello, World!`, a 1 MiB response body, and a **realworld** request that POSTs a JSON payload with a Bearer-auth header and echoes it back as JSON. All measured on a dedicated x86\\_64 Linux box against Deno 2.8.0:\n\nDeno 2.8 (gray) vs 2.9 (blue)\n\nCold start  \nlower is better\n\nv2.8  \n34.2 ms\n\n**v2.9**  \n17.3 ms\n\n1.98x faster\n\n`Deno.serve` realworld  \nhigher is better\n\nv2.8  \n56.8k req/s\n\n**v2.9**  \n72.4k req/s\n\n1.27x faster\n\n`Deno.serve` plaintext  \nhigher is better\n\nv2.8  \n77.0k req/s\n\n**v2.9**  \n85.6k req/s\n\n1.11x faster\n\n`Deno.serve` 1 MiB body  \nhigher is better\n\nv2.8  \n1,617 req/s\n\n**v2.9**  \n1,907 req/s\n\n1.18x faster\n\nRSS, realworld  \nlower is better\n\nv2.8  \n142 MB\n\n**v2.9**  \n64 MB\n\n2.2x less memory\n\nRSS, 1 MiB body  \nlower is better\n\nv2.8  \n197 MB\n\n**v2.9**  \n63 MB\n\n3.1x less memory\n\n`Deno.serve` throughput and peak RSS at concurrency 100; cold start is mean of 150 `hyperfine` runs. Dedicated x86\\_64 Linux box, server and load generator pinned to disjoint cores, `oha` median of 3 runs.\n\n**Startup.** A hello-world program now cold-starts in about half the time it took in 2.8 (`34ms` down to `17ms`). The win comes from lazy-loading `node:` globals out of the snapshot, gating the eager Node bootstrap to Node workers, a V8 code cache for residual lazy-loaded ESM modules, and a minified snapshot ([#34450](https://github.com/denoland/deno/pull/34450), [#35373](https://github.com/denoland/deno/pull/35373), [#35338](https://github.com/denoland/deno/pull/35338), [#35183](https://github.com/denoland/deno/pull/35183)); on macOS, chained fixups trim additional pre-main time ([#35409](https://github.com/denoland/deno/pull/35409)).\n\n**Memory.** The standout this cycle is memory under load. In 2.8, resident set size grew with the workload, from roughly `94 MB` serving plaintext up to `197 MB` streaming 1 MiB bodies. In 2.9 it stays essentially flat, holding around `62 MB` no matter what the server is doing. That works out to `2.2x` less peak RSS on the realworld workload (`142 MB` down to `64 MB`) and `3.1x` less on 1 MiB bodies (`197 MB` down to `63 MB`), so the same machine can run far more concurrent `Deno.serve` instances before it runs out of headroom.\n\n**HTTP throughput.** `Deno.serve` is faster across the board too: the realworld workload gains `1.27x`, plaintext `1.11x`, and 1 MiB bodies `1.18x`, helped by a new Deno-owned HTTP/1.1 serving path ([#34446](https://github.com/denoland/deno/pull/34446)).\n\nSeveral hot paths also moved from JavaScript into Rust this release: `crypto.subtle` ([#34966](https://github.com/denoland/deno/pull/34966)) and `console` / `Deno.inspect` ([#35087](https://github.com/denoland/deno/pull/35087)).\n\n## CSS module imports\n\nDeno 2.9 supports importing CSS files as [constructable stylesheets](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet) using import attributes, matching the [CSS module scripts](https://web.dev/articles/css-module-scripts) web standard ([#35093](https://github.com/denoland/deno/pull/35093)):\n\nmain.ts\n\n```\nimport sheet from \"./styles.css\" with { type: \"css\" };\n\ndocument.adoptedStyleSheets = [sheet];\n```\n\nThe import evaluates to a `CSSStyleSheet` instance, so the same code runs in Deno and in the browser without a bundler step. It's gated behind the `--unstable-raw-imports` flag in 2.9. A lone CSS import isn't much on its own, but it's the difference between front-end code that runs under Deno and code that trips the module loader: components and modules that import their own stylesheets now load and type-check directly, which makes testing front-end code in Deno considerably easier. [Learn more about modules](https://docs.deno.com/runtime/fundamentals/modules/).\n\n## Migrating from npm, pnpm, yarn, and Bun\n\nMoving an existing Node project to Deno is about as smooth as it gets: in most cases it's a couple of commands. Run `deno install` to pull your dependencies and `deno task dev` to start your app, and you're running on Deno. There's nothing to port and nothing to rewrite. Deno reads the `package.json`, lockfile, and workspace layout you already have, and 2.9 closes the last rough edges so that even pnpm workspaces and tools that shell out to `node` work without intervention.\n\n**Your lockfile comes with you.** The biggest friction in switching package managers is losing a carefully-pinned dependency graph. In 2.9 you don't. Run `deno install` in a project that has a `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, or `bun.lock` but no `deno.lock`, and Deno seeds a fresh `deno.lock` straight from it, carrying over the exact resolved versions and integrity hashes on that first install ([#34296](https://github.com/denoland/deno/pull/34296), [#35394](https://github.com/denoland/deno/pull/35394)):\n\n```\n$ deno install\nSeeded deno.lock from package-lock.json\n```\n\nThere's no re-resolution and no surprise upgrades: the versions you were running under npm are the versions you run under Deno. From there `deno install` writes a `node_modules` directory Deno can run against, and `deno task` runs the `package.json` scripts you already have, so the rest of your team can keep working the way they do.\n\n**Workspaces carry over, pnpm's included.** Deno already understands the `workspaces` field that npm, yarn, and Bun keep in `package.json`, so those monorepos work as-is. pnpm is the odd one out: it stores its workspace configuration in a separate `pnpm-workspace.yaml` that Deno doesn't read, which used to surface as a confusing resolution error. Now Deno spots that file and migrates its `packages`, `catalog`, and `catalogs` into your `package.json` (or `deno.json`) without disturbing your comments or existing fields, then asks you to re-run ([#34993](https://github.com/denoland/deno/pull/34993)). Combined with the [`catalog:` protocol](https://deno.com/blog/v2.8#catalog-protocol) Deno adopted in 2.8, your centralized, shared dependency versions keep working after the move.\n\n**Tools that expect `node` keep working.** Plenty of build tooling shells out to a `node` binary directly, like Next.js's Turbopack worker pool. When no real `node` is installed, Deno now puts a stand-in on `PATH` that forwards to itself and translates Node's CLI arguments, so those tools run unmodified. A real `node` is never shadowed, and `DENO_DISABLE_NODE_SHIM=1` opts out ([#34969](https://github.com/denoland/deno/pull/34969)).\n\nPut together, you can drop Deno into a Node project, run your existing scripts against it, and decide how much further to take it on your own schedule. [Read the guide to switching your package manager to Deno](https://docs.deno.com/runtime/migrate/switch_package_manager/).\n\n## Dependency management\n\n### `deno link` and `deno unlink`\n\n`deno link` and `deno unlink` manage local package links from the CLI instead of hand-editing config, in the spirit of `npm link` ([#34359](https://github.com/denoland/deno/pull/34359)). Point `deno link` at a local directory containing a `deno.json` with a `name` field, and it's added to the `links` array and importable by its name everywhere in your project:\n\n```\n$ deno link ../my-lib\nLink ../my-lib (my-lib)\n\n$ deno unlink my-lib   # by name, or `deno unlink ../my-lib` by path\n```\n\ndeno.json\n\n```\n{\n  \"imports\": {},\n  \"links\": [\"../my-lib\"]\n}\n```\n\nThe `links` field itself is now stable in 2.9: it shipped under that name back in 2.3 and was never gated behind a runtime flag, so 2.9 simply drops the remaining \"unstable\" labeling ([#34996](https://github.com/denoland/deno/pull/34996)). [Learn more about `deno link`](https://docs.deno.com/runtime/reference/cli/link/).\n\n### `deno list`\n\nThe new `deno list` subcommand prints the dependencies your project declares in `deno.json` and `package.json` and resolves their versions, the equivalent of `npm ls` / `pnpm list`, answering \"what do I depend on\" rather than walking the full module graph the way `deno info` does ([#34972](https://github.com/denoland/deno/pull/34972)):\n\n```\n$ deno list\n┌───────────────────────┬──────────┬──────────┐\n│ Package               │ Required │ Resolved │\n├───────────────────────┼──────────┼──────────┤\n│ jsr:@hono/hono (hono) │ ^4       │ 4.12.23  │\n├───────────────────────┼──────────┼──────────┤\n│ jsr:@std/assert       │ ^1       │ 1.0.19   │\n├───────────────────────┼──────────┼──────────┤\n│ npm:express           │ ^5       │ 5.2.1    │\n└───────────────────────┴──────────┴──────────┘\n```\n\nFlags narrow or widen the view:\n\n```\n$ deno list --depth 2        # show the tree two levels deep\n$ deno list --prod           # production dependencies only\n$ deno list -r               # include all workspace members\n$ deno list \"*eslint*\"       # filter by name (wildcards supported)\n```\n\n[Learn more about `deno list`](https://docs.deno.com/runtime/reference/cli/list/).\n\n### Prefer `package.json`\n\nFor projects that keep `package.json` as their source of truth, the new `preferPackageJson` setting makes `deno add`, `deno install`, and `deno remove` manage dependencies in `package.json` instead of `deno.json` (creating one if it doesn't exist), the equivalent of passing the `--package-json` flag added in 2.8 on every command ([#35392](https://github.com/denoland/deno/pull/35392)):\n\ndeno.json\n\n```\n{\n  \"preferPackageJson\": true\n}\n```\n\n`deno install` also reads the `engines` field in `package.json` and warns (never errors, matching npm) when the current Node or Deno version doesn't satisfy a declared constraint ([#34225](https://github.com/denoland/deno/pull/34225)). [Learn more about `preferPackageJson`](https://docs.deno.com/runtime/reference/deno_json/#prefer-packagejson-for-dependencies).\n\n### JSR dependencies in `node_modules`\n\nWhen a `node_modules` directory is in use, the new `jsrDepsInNodeModules` option installs `jsr:` dependencies into it through JSR's npm compatibility registry (`jsr:@david/dax` becomes `npm:@jsr/david__dax`, served from `npm.jsr.io`). This matches the native JSR support package managers like pnpm and npm already provide, which install JSR packages through the same npm-compat registry ([#35029](https://github.com/denoland/deno/pull/35029)):\n\ndeno.json\n\n```\n{\n  \"jsrDepsInNodeModules\": true\n}\n```\n\nWith it on, JSR packages behave like npm dependencies on disk: the full tarball is materialized (so a package can read its own bundled assets and `import.meta.dirname` is defined), and each one is symlinked under its original `@scope/name` so external type checkers and bundlers resolve it like any other npm install. It's opt-in and off by default; left off, `jsr:` specifiers keep resolving over HTTPS exactly as before. [Learn more about `jsrDepsInNodeModules`](https://docs.deno.com/runtime/reference/deno_json/#jsr-dependencies-in-node_modules).\n\n### Workspace `node_modules`\n\nIn a workspace, `deno install` now creates a `node_modules` directory inside each member and populates its `.bin`, so Node tooling run from within a member (eslint, svelte-check, astro, and so on) finds the local dependencies it expects ([#34970](https://github.com/denoland/deno/pull/34970)).\n\n### Lockfile merge conflicts\n\nA `deno.lock` containing git merge conflict markers used to be a hard error. Deno 2.9 resolves them automatically, unioning the additive sections and taking the higher version on genuine specifier conflicts, so a rebase no longer means hand-editing the lockfile ([#34726](https://github.com/denoland/deno/pull/34726)).\n\n## Supply chain security\n\n### Minimum dependency age, enabled by default\n\nA large class of npm supply-chain attacks is caught simply by waiting: a malicious version is usually detected and unpublished within a day or two of being released. Deno's [`min-release-age`](https://deno.com/blog/v2.6#controlling-dependency-stability), introduced in 2.6, refuses to install any npm package version younger than a configured age. In 2.9 it is enabled by default with a 24-hour window, so a freshly-published, potentially compromised version never lands in your dependency tree the moment it appears ([#35458](https://github.com/denoland/deno/pull/35458)).\n\nThe default sits at the bottom of the `min-release-age` precedence chain, so anything you set explicitly wins. Tune or disable it in `.npmrc`:\n\n.npmrc\n\n```\nmin-release-age=72h    # wait three days instead of the 24-hour default\nmin-release-age=0      # opt out entirely\n```\n\nIt also fetches the richer npm metadata that the `no-downgrade` trust policy below relies on, so the two supply-chain guards work well together. [Learn more about `.npmrc` configuration](https://docs.deno.com/runtime/fundamentals/node/#npmrc-configuration).\n\n### `no-downgrade` trust policy\n\nDeno 2.9 adds an opt-in npm trust policy that defends against stolen-maintainer-token attacks ([#34927](https://github.com/denoland/deno/pull/34927)). Following pnpm's design, Deno ranks how each package version was published: staged publishing (a maintainer approving with a live 2FA challenge) is the strongest signal, then trusted publishing backed by a provenance attestation, then a provenance attestation on its own.\n\nEnable the policy with `trust-policy=no-downgrade` in `.npmrc`:\n\n.npmrc\n\n```\ntrust-policy=no-downgrade\n```\n\nWith it on, Deno refuses to resolve a version whose trust evidence is weaker than the strongest evidence on any earlier-published version of the same package (compared by publish date). If a package has consistently shipped through trusted publishing or with provenance and a later version suddenly appears as a plain token publish (the hallmark of a compromised maintainer token, as in the August 2025 s1ngularity incident), the install becomes a hard error instead of a silent downgrade. Two escape hatches mirror pnpm: `trust-policy-ignore-after` (in minutes) skips the check for older, genuinely pre-provenance releases, and `trust-policy-exclude[]=<package>` exempts named packages.\n\nThe policy is off by default, since provenance and trusted publishing are still unevenly adopted across the registry. It builds on the `min-release-age` guard above, which already fetches the metadata the trust check needs. [Learn more about `.npmrc` configuration](https://docs.deno.com/runtime/fundamentals/node/#npmrc-configuration).\n\n## Testing and coverage\n\nDeno's built-in test runner picks up features you used to reach for Vitest or Jest to get.\n\n### Snapshot testing\n\nThe test context now has a built-in `t.assertSnapshot()`, using the same format and serializer as `@std/testing/snapshot`, no import required ([#35139](https://github.com/denoland/deno/pull/35139)):\n\nrender\\_test.ts\n\n```\nDeno.test(\"renders the header\", async (t) => {\n  await t.assertSnapshot(renderHeader({ title: \"Deno 2.9\" }));\n});\n```\n\nSnapshots are written to `__snapshots__/<test file>.snap` next to the test. On a mismatch the runner prints a diff and tells you how to update:\n\n```\nerror: AssertionError: Snapshot does not match:\n\n    [Diff] Actual / Expected\n\n    {\n+   value: 2,\n-   value: 1,\n    }\n\nTo update snapshots, run\n    deno test --update-snapshots [files]...\n```\n\nDefault-location snapshots need no read/write permissions (the runner manages them), and stale entries are pruned automatically when a full run updates them. Pass `--update-snapshots` (or `-u`) to regenerate. Snapshot testing also works through `node:test`, via `t.assert.fileSnapshot()` ([#35478](https://github.com/denoland/deno/pull/35478)). [Learn more about snapshot testing](https://docs.deno.com/runtime/fundamentals/testing/).\n\n### Change-aware test selection\n\nFor fast local iteration, `deno test` can run only the tests affected by your changes ([#35199](https://github.com/denoland/deno/pull/35199)):\n\n```\n$ deno test --changed              # tests affected by uncommitted changes\n$ deno test --changed=origin/main  # tests affected since branching off main\n$ deno test --related=src/util.ts  # tests that depend on a specific file\n```\n\nSelection is dependency-aware (it walks the module graph, across workspace members) and conservative: changing your config, lockfile, import map, or `package.json` disables filtering and runs everything. It pairs naturally with a file watcher for a tight edit-test loop, or with `--changed=origin/main` in CI to run only the tests a pull request could have affected. [Learn more about `deno test`](https://docs.deno.com/runtime/reference/cli/test/).\n\n### Retries and repeats\n\nFlaky tests can now be retried, and stability-sensitive tests can be repeated, either per-test or across the whole run ([#35053](https://github.com/denoland/deno/pull/35053)):\n\nflaky\\_test.ts\n\n```\nDeno.test({\n  name: \"eventually consistent\",\n  retry: 2,\n  fn: async () => {\n    // re-run up to 2 more times on failure; passes if any attempt passes\n  },\n});\n```\n\n```\n$ deno test --retry=2     # retry every failing test up to 2 times\n$ deno test --repeats=5   # run each test 5 extra times; all must pass\n```\n\nA test that only passes after a retry is reported as `flaky` in the summary, so the signal isn't silently lost. Per-test options take precedence over the CLI flags (including an explicit `0` to opt a test out). [Learn more about `deno test`](https://docs.deno.com/runtime/reference/cli/test/).\n\n### Coverage thresholds\n\nCoverage can now fail a run when it drops below a target, either via a flag or configured per-metric in `deno.json` ([#35056](https://github.com/denoland/deno/pull/35056)):\n\n```\n$ deno coverage --threshold=90 coverage/\n$ deno test --coverage --coverage-threshold=90\n```\n\ndeno.json\n\n```\n{\n  \"coverage\": {\n    \"thresholds\": { \"lines\": 90, \"branches\": 80, \"functions\": 90 }\n  }\n}\n```\n\nWhen the aggregate falls short, the command exits non-zero and tells you which metric missed:\n\n```\nCoverage threshold not met:\n  - Line coverage 85.00% is below the threshold of 90.00%\n```\n\n[Learn more about `deno coverage`](https://docs.deno.com/runtime/reference/cli/coverage/).\n\n### Sharding with `--shard`\n\n`deno test --shard=<index>/<count>` splits the discovered test files into balanced groups and runs only one group, so you can fan a suite out across CI machines ([#35057](https://github.com/denoland/deno/pull/35057)). It drops straight into a GitHub Actions matrix:\n\n.github/workflows/test.yml\n\n```\njobs:\n  test:\n    strategy:\n      matrix:\n        shard: [1, 2, 3]\n    steps:\n      - uses: denoland/setup-deno@v2\n      - run: deno test --shard=${{ matrix.shard }}/3\n```\n\nThe index is 1-based, sharding happens before `--shuffle`, and over-sharding (more shards than files) simply leaves some shards empty and exits cleanly. [Learn more about `deno test`](https://docs.deno.com/runtime/reference/cli/test/).\n\n### Parameterized tests with `Deno.test.each`\n\n`Deno.test.each` registers one real, independently-filterable test per case from a table of inputs ([#34938](https://github.com/denoland/deno/pull/34938)):\n\nadd\\_test.ts\n\n```\nimport { assertEquals } from \"jsr:@std/assert\";\n\nDeno.test.each([\n  [1, 1, 2],\n  [1, 2, 3],\n  [2, 1, 3],\n])(\"add(%i, %i) = %i\", (a, b, expected) => {\n  assertEquals(a + b, expected);\n});\n```\n\nArray cases are spread as positional arguments; object cases are passed as a single argument and can be interpolated into the test name with `$key`:\n\n```\nDeno.test.each([\n  { a: 1, b: 1, sum: 2 },\n  { a: 2, b: 3, sum: 5 },\n])(\"$a + $b = $sum\", ({ a, b, sum }) => {\n  assertEquals(a + b, sum);\n});\n```\n\nName templates support printf-style tokens (`%s`, `%i`/`%d`, `%f`, `%j`, `%o`), `%#` for the case index, and `$key.nested` for nested object access. `Deno.test.only.each` and `Deno.test.ignore.each` compose as you'd expect. [Learn more about `Deno.test`](https://docs.deno.com/runtime/fundamentals/testing/).\n\n## `deno compile`\n\n`deno compile` gains `--include-as-is`, which embeds a file or directory into the executable's virtual filesystem without any module resolution or transpilation ([#32417](https://github.com/denoland/deno/pull/32417)). Where `--include` runs files through the module graph, `--include-as-is` is for assets and pre-built bundles you just want available via filesystem APIs at runtime:\n\n```\n$ deno compile --include-as-is dist/ --allow-read server.ts\n```\n\n```\nconst html = Deno.readTextFileSync(import.meta.dirname + \"/dist/index.html\");\n```\n\nThe two flags combine, so you can resolve some modules and embed others verbatim in the same build.\n\nCompiled binaries also get real persistent storage. A default `Deno.openKv()`, `localStorage`, and the `caches` API now persist to a per-app directory under the platform's app-data location instead of falling back to in-memory storage ([#34618](https://github.com/denoland/deno/pull/34618)). The storage identity is the new `--app-name` flag, which defaults to the output file name, so two binaries built with the same `--app-name` share a store, and renaming a binary no longer loses its data:\n\n```\n$ deno compile --unstable-kv --app-name notes --output notes main.ts\n```\n\n**Smaller binaries with `--bundle`.** By default `deno compile` embeds your entire resolved `node_modules` tree into the binary. The new experimental `--bundle` flag instead runs your entrypoint through Deno's bundler first (tree-shaking and emitting a single module), and embeds that, which can dramatically shrink binaries for npm-heavy projects (in the project's own measurements, a lodash hello-world dropped from 11.6","publishedAt":"2026-06-25T09:00:00.000Z","url":"https://deno.com/blog/v2.9","media":[],"prerelease":false,"source":{"slug":"deno-changelog","name":"Deno Changelog","type":"feed"},"org":{"slug":"deno","name":"Deno"},"product":null,"groupSlug":"deno-changelog","groupName":"Deno Changelog","coverageCount":0,"composition":{"bugs":0,"features":9,"enhancements":6}},{"id":"rel_ox07uaKiz8O3mIJ73X_tI","version":"expo-orbit-v2.8.0","type":"feature","title":"v2.8.0","summary":"### 🎉 New features\r\n\r\n- Add support for physical iPhones on Windows and Linux. ([#347](https://github.com/expo/orbit/pull/347) by [@gabrieldonadel](h...","titleGenerated":null,"titleShort":null,"content":"### 🎉 New features\r\n\r\n- Add support for physical iPhones on Windows and Linux. ([#347](https://github.com/expo/orbit/pull/347) by [@gabrieldonadel](https://github.com/gabrieldonadel))\r\n- Add Wi-Fi pairing support for Android devices. ([#350](https://github.com/expo/orbit/pull/350) by [@gabrieldonadel](https://github.com/gabrieldonadel))\r\n\r\n### 🐛 Bug fixes\r\n\r\n- Fix error message when launching updates on iOS physical devices. ([#348](https://github.com/expo/orbit/pull/348) by [@patrickwehbe](https://github.com/patrickwehbe))\r\n\r\n### 💡 Others\r\n\r\n- Add cross-platform E2E testing with WebdriverIO for Electron and Appium mac2 for macOS. ([#334](https://github.com/expo/orbit/pull/334) by [@gabrieldonadel](https://github.com/gabrieldonadel))\r\n- Fix flaky onboarding E2E test by switching off the closed onboarding window instead of querying it. ([#349](https://github.com/expo/orbit/pull/349) by [@gabrieldonadel](https://github.com/gabrieldonadel))\r\n- Speed up the macOS E2E workflow by caching CocoaPods. ([#349](https://github.com/expo/orbit/pull/349) by [@gabrieldonadel](https://github.com/gabrieldonadel))\r\n- Speed up CLI commands by lazy-loading command modules and listing devices in parallel. ([#351](https://github.com/expo/orbit/pull/351) by [@gabrieldonadel](https://github.com/gabrieldonadel))\r\n- Upgrade menu-bar app to Expo SDK 56. ([#346](https://github.com/expo/orbit/pull/346) by [@gabrieldonadel](https://github.com/gabrieldonadel))\r\n- Replaced @react-native-clipboard/clipboard with expo-clipboard. ([#346](https://github.com/expo/orbit/pull/346) by [@gabrieldonadel](https://github.com/gabrieldonadel))\r\n- Replaced SystemIconView local module with expo-symbols. ([#346](https://github.com/expo/orbit/pull/346) by [@gabrieldonadel](https://github.com/gabrieldonadel))\r\n- Drop aapt requirement for installing apps to Android devices. ([#352](https://github.com/expo/orbit/pull/352) by [@gabrieldonadel](https://github.com/gabrieldonadel))\r\n- Hide the `tar` console window on Windows when extracting builds, skip probing `devicectl` on non-macOS, and detect locked iOS 17+ devices correctly. ([#352](https://github.com/expo/orbit/pull/352) by [@gabrieldonadel](https://github.com/gabrieldonadel))\r\n\r\n","publishedAt":"2026-06-24T20:11:47.000Z","url":"https://github.com/expo/orbit/releases/tag/expo-orbit-v2.8.0","media":[],"prerelease":false,"source":{"slug":"expo-orbit","name":"Expo Orbit","type":"github"},"org":{"slug":"expo","name":"Expo"},"product":null,"groupSlug":"expo-orbit","groupName":"Expo Orbit","coverageCount":0,"composition":null},{"id":"rel_0-6uyysLGio2wz-YQSz7z","version":null,"type":"feature","title":"Maestro testing: insights, clearer results, and faster retries","summary":"Introducing a new insights dashboard, showing you how every Maestro end-to-end test run performed over time, across your whole team. Identify flakey t...","titleGenerated":null,"titleShort":null,"content":"Introducing a new insights dashboard, showing you how every Maestro end-to-end test run performed over time, across your whole team. Identify flakey tests, see when regressions were introduced, and stop scrolling through endless logs.\n\nYour end-to-end tests pass, until they don't. When a Maestro end-to-end (E2E) test fails, acting on it usually means digging through logs to find out what broke, re-running your whole suite to retry one flaky test, and guessing whether things are getting better over time.\n\n## Maestro insights\n\n[Maestro insights](https://docs.expo.dev/eas-insights/maestro/) collects and visualizes how your [Maestro](https://maestro.dev/) tests perform over time, right in your project's **Insights** tab. It surfaces:\n\n- **Trends:** Maestro runs and pass rate across all your flows over time\n- **Flaky flows identification:** flows that pass only after a retry, so you can find and fix the unreliable ones\n- **Failure patterns:** failures grouped by error message, surfacing common causes behind failures\n- **Filter by test:** open a specific test flow to see its recent runs, durations, and error patterns\n\n![screenshot: Maestro insights — overview, runs-over-time chart, and the All Maestro flows table](https://cdn.sanity.io/images/9r24npb8/production/8eb0243a2892897c5c06183d5344ab4b04800800-1748x1306.png?auto=format&fit=max&q=75&w=800)\n\nWith our insights, you can also filter by workflow, Git branch, tag, or status, and sort the flow list by runs, failures, flake rate, or P90 duration to find issues fast.\n\n## A clearer view of every run\n\nEvery Maestro job now opens with a Test Results summary that lists each flow along with its status (passed, failed, or flaky) and duration. Failed and flaky flows also surface their error messages at the top of the page, so you can immediately see what went wrong without digging through logs. Open the screenshot captured at the moment of failure or jump directly to the failure timestamp in the recording to quickly understand what happened.\n\nTogether with improved flaky test detection, these updates make it easier to identify issues, understand failures, and take action faster.\n\n![screenshot: the Test Results summary on a Maestro job](https://cdn.sanity.io/images/9r24npb8/production/947eb277cfed2f4853b491f8a38adeecb0ddb94e-2590x1822.png?auto=format&fit=max&q=75&w=800)\n\n## Retries that re-run only failed flows\n\nWhen a Maestro job retries, it now re-runs only the flows that failed on the previous attempt instead of your whole suite. You'll get faster feedback and fewer wasted CI minutes. This is the default behavior (`retry_failed_only`); to re-run every flow on each retry instead, set `retry_failed_only: false`. See the [`maestro`](https://docs.expo.dev/eas/workflows/pre-packaged-jobs/#maestro) [job reference](https://docs.expo.dev/eas/workflows/pre-packaged-jobs/#maestro) for details.\n\n## Built on JUnit output\n\nMaestro insights, the Test Results summary, and failed-flow-only retries all build on the JUnit report the Maestro job produces by default (`output_format: junit`). If you've overridden `output_format` to another value, switch back to `junit` to use these features.\n\n## Get started\n\nMaestro insights is currently available to Production (up to 30 days of history) and Enterprise plan (update to 1 year of history) subscribers. To see your project's Maestro insights, open the Maestro tab in your project's Insights through the left sidebar. New to E2E testing on EAS? Follow our [guide to running Maestro tests in EAS Workflows](https://docs.expo.dev/eas/workflows/examples/e2e-tests/).","publishedAt":"2026-06-24T14:00:00.000Z","url":"https://expo.dev/changelog/maestro-testing-improvements","media":[{"type":"image","url":"https://cdn.sanity.io/images/9r24npb8/production/8eb0243a2892897c5c06183d5344ab4b04800800-1748x1306.png?auto=format&fit=max&q=75&w=800","alt":"screenshot: Maestro insights — overview, runs-over-time chart, and the All Maestro flows table","r2Key":"releases/e9d585de08ff88f8824a03187b40621991e8d314b774a8066ef1251089fbef5e.png","r2Url":"https://media.releases.sh/releases/e9d585de08ff88f8824a03187b40621991e8d314b774a8066ef1251089fbef5e.png"},{"type":"image","url":"https://cdn.sanity.io/images/9r24npb8/production/947eb277cfed2f4853b491f8a38adeecb0ddb94e-2590x1822.png?auto=format&fit=max&q=75&w=800","alt":"screenshot: the Test Results summary on a Maestro job","r2Key":"releases/163840f5e0a8cd939cc499e57de3676a00f84a003f3f341f1c2ca489b3633dad.png","r2Url":"https://media.releases.sh/releases/163840f5e0a8cd939cc499e57de3676a00f84a003f3f341f1c2ca489b3633dad.png"}],"prerelease":false,"source":{"slug":"expo-changelog","name":"Expo Changelog","type":"feed"},"org":{"slug":"expo","name":"Expo"},"product":null,"groupSlug":"expo-changelog","groupName":"Expo Changelog","coverageCount":0,"composition":null},{"id":"rel_EugXj6OmjCKq9qE5dNKOI","version":null,"type":"feature","title":"Dev Chat Agenda – June 24, 2026","summary":"WordPress 7.1 will hide the Classic block from the inserter by default, and a merge proposal for a new custom post type is under discussion. The dev chat agenda also covers the 7.0.1 release schedule and a recap of restoring removed version history.","titleGenerated":"WordPress 7.1 hides Classic block from inserter by default","titleShort":"Classic block hidden from inserter in 7.1","content":"The next WordPress Developers Chat will take place on [Wednesday, June 24, 2026, at 15:00 UTC](https://www.timeanddate.com/worldclock/fixedtime.html?iso=20260624T1500) in the [core](https://wordpress.slack.com/messages/core/) channel on [Make WordPress Slack](https://make.wordpress.org/chat/).\n\nThe live meeting will focus on the discussion for upcoming releases, and have an open floor section.\n\nThe various curated agenda sections below refer to additional items. If you have ticket requests for help, please continue to post details in the comments section at the end of this agenda or bring them up during the dev chat.\n\n## Announcements ![📢](https://s.w.org/images/core/emoji/17.0.2/72x72/1f4e2.png)\n\n### 7.1\n\n- [Announcing the 7.1 Release squad](https://make.wordpress.org/core/2026/06/17/announcing-the-wordpress-7-1-release-squad/)\n- [Roadmap for 7.1](https://make.wordpress.org/core/2026/06/19/roadmap-to-7-1/)\n- [Merge Proposal for new custom post type in 7.1](https://make.wordpress.org/core/2026/06/22/merge-proposal-guidelines-built-on-knowledge/)\n- [Classic block hidden from inserter by default in 7.1](https://make.wordpress.org/core/2026/06/23/hiding-the-classic-block-from-the-inserter-in-wordpress-7-1/)\n\n### General\n\n- [7.0.1 release schedule](https://make.wordpress.org/core/2026/06/18/wordpress-7-0-1-release-schedule/)\n- [WP 7.0 Release retrospective](https://make.wordpress.org/core/2026/06/22/wordpress-7-0-release-retrospective/)\n- [Recap: Restoring removed version history](https://make.wordpress.org/core/2026/06/17/recap-restoring-removed-version-history/)\n- [Whats new in Gutenberg 23.4](https://make.wordpress.org/core/2026/06/17/whats-new-in-gutenberg-23-3-03-jun-2/)\n\n## Discussions ![💬](https://s.w.org/images/core/emoji/17.0.2/72x72/1f4ac.png)\n\n*The discussion section of the agenda is for discussing important topics affecting the upcoming release or larger initiatives that impact the Core Team. To nominate a topic for discussion, please leave a comment on this agenda with a summary of the topic, any relevant links that will help people get context for the discussion, and what kind of feedback you are looking for from others participating in the discussion*.\n\n## Open floor  ![🎙](https://s.w.org/images/core/emoji/17.0.2/72x72/1f399.png)\n\nAny topic can be raised for discussion in the comments, as well as requests for assistance on tickets. Tickets in the milestone for the next major or maintenance release will be prioritized.  \n  \nPlease include details of tickets / PRs and the links in the comments, and indicate whether you intend to be available during the meeting for discussion or will be async.\n\n[#7-1](https://make.wordpress.org/core/tag/7-1/), [#agenda](https://make.wordpress.org/core/tag/agenda/), [#core](https://make.wordpress.org/core/tag/core/), [#dev-chat](https://make.wordpress.org/core/tag/dev-chat/)","publishedAt":"2026-06-24T03:52:21.000Z","url":"https://make.wordpress.org/core/2026/06/24/dev-chat-agenda-june-24-2026/","media":[{"type":"image","url":"https://s.w.org/images/core/emoji/17.0.2/72x72/1f4e2.png","alt":"📢"},{"type":"image","url":"https://s.w.org/images/core/emoji/17.0.2/72x72/1f4ac.png","alt":"💬"},{"type":"image","url":"https://s.w.org/images/core/emoji/17.0.2/72x72/1f399.png","alt":"🎙"}],"prerelease":false,"source":{"slug":"wordpress-core-dev-notes","name":"WordPress Core Dev Notes","type":"feed"},"org":{"slug":"wordpress","name":"WordPress"},"product":null,"groupSlug":"wordpress-core-dev-notes","groupName":"WordPress Core Dev Notes","coverageCount":0,"composition":null},{"id":"rel_luYsH4CMBmjFbpva90JjF","version":"svelte@5.56.4","type":"feature","title":"svelte@5.56.4","summary":"### Patch Changes\n\n-   fix: include wrapping parentheses in `{@const}` declarator `end` position ([#18436](https://github.com/sveltejs/svelte/pull/184...","titleGenerated":null,"titleShort":null,"content":"### Patch Changes\n\n-   fix: include wrapping parentheses in `{@const}` declarator `end` position ([#18436](https://github.com/sveltejs/svelte/pull/18436))\n\n-   fix: always unset reactivity context after restoring it ([#18453](https://github.com/sveltejs/svelte/pull/18453))\n\n-   fix: don't notify `searchParams` subscribers when the URL changes without affecting the search string ([#18425](https://github.com/sveltejs/svelte/pull/18425))\n\n-   fix: strip `?` from optional parameters in `<script lang=\"ts\">` so generated JavaScript is valid ([#18448](https://github.com/sveltejs/svelte/pull/18448))\n","publishedAt":"2026-06-23T18:48:43.000Z","url":"https://github.com/sveltejs/svelte/releases/tag/svelte%405.56.4","media":[],"prerelease":false,"source":{"slug":"svelte","name":"svelte","type":"github"},"org":{"slug":"svelte","name":"Svelte"},"product":{"slug":"svelte","name":"Svelte"},"groupSlug":"svelte","groupName":"Svelte","coverageCount":0,"composition":null},{"id":"rel_F0cgQ7oVtDYT6Eg0l7-H6","version":"7.1","type":"feature","title":"Hiding the Classic block from the inserter in WordPress 7.1","summary":"WordPress 7.1 hides the Classic block from the block inserter by default; existing Classic blocks continue to work and remain editable. A `wp_classic_block_supports_inserter` filter allows restoring the block to the inserter.","titleGenerated":"WordPress 7.1 hides Classic block from inserter; filter lets you bring it back","titleShort":"Classic block hidden from inserter; opted back in via filter","content":"We’ve just merged [a change](https://core.trac.wordpress.org/changeset/62546) that will be part of WordPress 7.1 that hides the Classic block from the block inserter by default. The Classic block stays registered, every existing Classic block keeps working and remains editable, and a new filter lets anyone bring it back into the inserter. This post explains what changes, why, and how to opt back in if needed.\n\n## What’s changing\n\nStarting in WordPress 7.1, the Classic block (`core/freeform`) no longer appears in the block inserter ([#11712](https://github.com/WordPress/wordpress-develop/pull/11712), [Trac #65166](https://core.trac.wordpress.org/ticket/65166), originally [#77911](https://github.com/WordPress/gutenberg/pull/77911) in Gutenberg). In practice, this means you can’t add a *new* Classic block from the inserter, the block library, or slash commands.\n\nNothing else about the block changes:\n\n- The Classic block remains registered.\n- All existing Classic blocks (including any `<!-- wp:freeform -->` content) continue to render and stay fully editable, exactly as before.\n- The Classic editor and the underlying TinyMCE experience are untouched. If a post type doesn’t use the block editor, nothing here applies to it.\n\nThis is purely about steering *new* content away from the legacy Classic block, not about removing anything you already have.\n\nTo be clear: the Classic *editor* is not affected at all by this change. This is strictly about the Classic *block* inside the block editor. If you use the Classic editor (for example, via the Classic Editor plugin or on post types that don’t use the block editor), your experience stays exactly the same.\n\n## Why we’re doing this\n\nThe Classic block has been the bridge from the pre-block era into the block editor, and it has served that role well. But it’s also the one block in Core that doesn’t behave like a block:\n\n- **Architectural consistency.** Every other Core block is a node in the block tree. The Classic block is the lone exception, opaque HTML rendered through a separate editor embedded inside the block editor. Keeping it as a default inserter option works against the block-first model on which the editor is built.\n- **Reducing the inflow.** The migration path away from Classic content (Convert to Blocks) has existed for years, and Classic usage keeps shrinking. Hiding the block from the inserter stops new Classic content from being created, so that set keeps getting smaller rather than growing.\n- **Maintenance leverage.** Many block-library improvements have to special-case the Classic block. Each special handling may be small on its own, but cumulatively, this may slow down work that benefits every other block.\n\nThe broader, longer-term goal, which will be covered separately as it matures, is to make the Classic block fully opt-in and eventually to lay the groundwork for loading TinyMCE only when it’s actually needed. WordPress 7.1 is just the first user-facing step on that path. None of the later steps are happening in 7.1, and each will get its own discussion and dev note.\n\n## Opting back in\n\nIf you (or your users) still want the Classic block available in the inserter, there’s a dedicated filter: `wp_classic_block_supports_inserter`.\n\nReturn `true` to show it everywhere:\n\n```\nadd_filter( 'wp_classic_block_supports_inserter', '__return_true' );\n```\n\nThe filter also receives the post being edited, so you can make the decision conditional, for example, per post type:\n\n```\nadd_filter(\n\t'wp_classic_block_supports_inserter',\n\tfunction ( $supports_inserter, $post ) {\n\t\treturn 'page' === $post->post_type ? true : $supports_inserter;\n\t},\n\t10,\n\t2\n);\n```\n\nIf you’d rather not write code, there’s a small plugin that does exactly this, [Enable Classic Block](https://github.com/tyxla/enable-classic-block), which flips the filter on for you. The plugin has already been submitted for approval to the WordPress Plugin Directory.\n\n## Backward compatibility\n\nThis change is opt-out by design and doesn’t break anything:\n\n- No content is modified or migrated. Existing Classic blocks are left exactly as they are.\n- The block, its edit behavior, and the Convert to Blocks action all continue to work.\n- The `core/freeform` block remains registered, so any code that relies on it being present keeps functioning.\n- Restoring the previous behavior is a one-line filter (or one tiny plugin) away.\n\n## What’s next\n\nAlongside this change, we’re investing in the surrounding experience so that moving away from the Classic block is smoother for everyone:\n\n- **A deprecation/migration notice (experimental).** There’s an [experiment in Gutenberg](https://github.com/WordPress/gutenberg/pull/78090) that surfaces a notice inside existing Classic blocks, with one-click actions to convert the content to blocks or to a Custom HTML block. We’re exploring this as a gentle way to highlight that the Classic block is being phased out and to make the migration path more discoverable. It’s behind an experiment flag for now while we refine it for a WordPress release.\n- **Improving everything around it.** In parallel, we’re improving and fixing the pieces that live by the Classic block: the Custom HTML block, the Convert to Blocks path, freeform handling and conversion, and related compatibility layers. The goal is that by the time Classic content needs to move, the tools to move it are solid.\n\nThese, alongside other planned next steps, can be tracked in the dedicated [tracking issue](https://github.com/WordPress/gutenberg/issues/78067).\n\n## We’d love your feedback\n\nThis is an early step in a longer effort, and we want to get it right. If you maintain plugins or custom integrations, run large sites, or have workflows that depend on the Classic block, we’d really like to hear from you, especially around migration and bulk-conversion needs.\n\n---\n\n*Props to [@desrosj](https://profiles.wordpress.org/desrosj/), [@mamaduka](https://profiles.wordpress.org/mamaduka/), [@mukesh27](https://profiles.wordpress.org/mukesh27/), [@westonruter](https://profiles.wordpress.org/westonruter/), [@wildworks](https://profiles.wordpress.org/wildworks/), and [@yuliyan](https://profiles.wordpress.org/yuliyan/) for the contributions, feedback, and code reviews.*\n\n*Props to [@mamaduka](https://profiles.wordpress.org/mamaduka/) and [@yuliyan](https://profiles.wordpress.org/yuliyan/) for reviewing this post.*\n\n[#7-1](https://make.wordpress.org/core/tag/7-1/), [#dev-notes](https://make.wordpress.org/core/tag/dev-notes/), [#dev-notes-7-1](https://make.wordpress.org/core/tag/dev-notes-7-1/)","publishedAt":"2026-06-23T08:34:13.000Z","url":"https://make.wordpress.org/core/2026/06/23/hiding-the-classic-block-from-the-inserter-in-wordpress-7-1/","media":[],"prerelease":false,"source":{"slug":"wordpress-core-dev-notes","name":"WordPress Core Dev Notes","type":"feed"},"org":{"slug":"wordpress","name":"WordPress"},"product":null,"groupSlug":"wordpress-core-dev-notes","groupName":"WordPress Core Dev Notes","coverageCount":0,"composition":{"bugs":0,"features":1,"enhancements":2}},{"id":"rel_f8iQYDMnqhnpNj3UnzQNn","version":"@sveltejs/kit@2.67.0","type":"feature","title":"@sveltejs/kit@2.67.0","summary":"### Minor Changes\n\n\n- feat: add `prerender.handleInvalidUrl` option for invalid URLs discovered while crawling ([#16088](https://github.com/sveltejs/k...","titleGenerated":null,"titleShort":null,"content":"### Minor Changes\n\n\n- feat: add `prerender.handleInvalidUrl` option for invalid URLs discovered while crawling ([#16088](https://github.com/sveltejs/kit/pull/16088))\n\n\n### Patch Changes\n\n\n- fix: support `exactOptionalPropertyTypes` for optional form schema fields ([#15866](https://github.com/sveltejs/kit/pull/15866))\n\n\n- fix: avoid unnecessarily overriding a user's Vite 8 `codeSplitting` setting ([#16118](https://github.com/sveltejs/kit/pull/16118))","publishedAt":"2026-06-22T22:33:00.000Z","url":"https://github.com/sveltejs/kit/releases/tag/%40sveltejs/kit%402.67.0","media":[],"prerelease":false,"source":{"slug":"kit","name":"kit","type":"github"},"org":{"slug":"svelte","name":"Svelte"},"product":{"slug":"sveltekit","name":"SvelteKit"},"groupSlug":"sveltekit","groupName":"SvelteKit","coverageCount":0,"composition":null},{"id":"rel_d7ZIz3LngIr-pWKsDtI8L","version":"@sveltejs/adapter-node@5.5.6","type":"feature","title":"@sveltejs/adapter-node@5.5.6","summary":"### Patch Changes\n\n\n- fix: avoid circular dependency between server initialisation and hook retrieval that causes the app to crash on start ([#16115](...","titleGenerated":null,"titleShort":null,"content":"### Patch Changes\n\n\n- fix: avoid circular dependency between server initialisation and hook retrieval that causes the app to crash on start ([#16115](https://github.com/sveltejs/kit/pull/16115))\n\n\n- fix: correctly resolve root directory on the server ([#16114](https://github.com/sveltejs/kit/pull/16114))\n\n\n- fix: ensure `ENV_PREFIX` is defined ([#16106](https://github.com/sveltejs/kit/pull/16106))\n\n- Updated dependencies [[`cf15fa0`](https://github.com/sveltejs/kit/commit/cf15fa0f695f6059214bd3fa2c9b18a1f49efb20), [`5c76121`](https://github.com/sveltejs/kit/commit/5c76121be6e4bd7265d31b5821decebb372c3b75), [`2992e17`](https://github.com/sveltejs/kit/commit/2992e172bccd57bc137667c57e98e6710512d844)]:\n  - @sveltejs/kit@2.67.0","publishedAt":"2026-06-22T22:32:57.000Z","url":"https://github.com/sveltejs/kit/releases/tag/%40sveltejs/adapter-node%405.5.6","media":[],"prerelease":false,"source":{"slug":"kit","name":"kit","type":"github"},"org":{"slug":"svelte","name":"Svelte"},"product":{"slug":"sveltekit","name":"SvelteKit"},"groupSlug":"sveltekit","groupName":"SvelteKit","coverageCount":0,"composition":null},{"id":"rel_AMZ6lrQAK5SZyVcQPXiVI","version":"7.0","type":"feature","title":"WordPress 7.0 Release Retrospective","summary":"WordPress Core team posts a retrospective on the 7.0 development cycle and invites contributors and observers to share feedback on processes, squads, and the release in general via a form or comments through July 20, 2026.","titleGenerated":"WordPress 7.0 post-release retrospective invites community feedback","titleShort":"Community feedback invited on 7.0 release cycle","content":"A huge congratulations, and a giant thank you to everyone who helped make WordPress 7.0 happen! The release was only made possible by your dedication and hard work. You all are heroes!\n\nNow that the development cycle is over, it’s time for a retro. You’re invited to share your thoughts on the 7.0 cycle, on processes, squad, or anything else about the release cycle. I *know* you all have :a lot: to say after that whirlwind, so please do! Feedback loops help uncover what is and is not working so that the release process can be improved. \n\nPlease [share your feedback using this form](https://docs.google.com/forms/d/e/1FAIpQLSe77yRymCzkbrOmIhYAGsTvoQ9WWHZUWP3EL8Njj2gEyEA8sA/viewform) or by dropping a comment below. Even contributors who did not contribute directly to the release are welcome.\n\nSomeone who was simply watching the release will have thoughts and opinions that vary from someone who was more heavily involved. It’s important for diverse perspectives to be represented in feedback for big picture clarity. So no matter who you are, please speak up!\n\nThe survey is not anonymous, but submissions will be anonymized in the follow up summary. Your wordpress.org username is only needed for any additional questions.\n\nThe form and comments will be open until July 20, 2026, and a summary of feedback will be published soon after.\n\nThank you for taking the time to give your valuable feedback, and thank you again for your amazing investments in 7.0 “Armstrong”. Together, future release cycles will be even better!\n\n*Props to [@4thhubbard](https://profiles.wordpress.org/4thhubbard/) and [@jeffpaul](https://profiles.wordpress.org/jeffpaul/)* *for the pre-publish review.*\n\n[#7-0](https://make.wordpress.org/core/tag/7-0/), [#release](https://make.wordpress.org/core/tag/release/), [#release-process](https://make.wordpress.org/core/tag/release-process/)","publishedAt":"2026-06-22T19:04:40.000Z","url":"https://make.wordpress.org/core/2026/06/22/wordpress-7-0-release-retrospective/","media":[],"prerelease":false,"source":{"slug":"wordpress-core-dev-notes","name":"WordPress Core Dev Notes","type":"feed"},"org":{"slug":"wordpress","name":"WordPress"},"product":null,"groupSlug":"wordpress-core-dev-notes","groupName":"WordPress Core Dev Notes","coverageCount":0,"composition":null},{"id":"rel_63iQK1FZS3zJYDGFBX09m","version":null,"type":"feature","title":"Merge Proposal: Guidelines built on Knowledge","summary":"WordPress 7.1 would merge the wp_knowledge custom post type, a shared storage primitive for author-facing and agent-facing site knowledge, with Guidelines as the first feature built on it. Guidelines gives site owners a canonical place to capture content standards such as voice, tone, image preferences, and per-block rules. Also ships the built-in types guideline, memory, and note, plus a Guidelines Settings page with per-scope records.","titleGenerated":"WordPress 7.1 proposes Knowledge post type with built-in Guidelines feature","titleShort":null,"content":"We propose merging Knowledge, a new `wp_knowledge` custom post type, into WordPress core for the 7.1 release, with Guidelines as the first feature built on it.\n\nKnowledge is a general primitive for storing author-facing and agent-facing site knowledge as standard WordPress content: a post type with a type taxonomy, the existing roles and capabilities, native revisions, and REST access. Guidelines uses it to give site owners a first-class place to capture the standards that shape how content is written and edited, such as voice, tone, image preferences, and per-block rules.\n\nThe implementation is operational in the Gutenberg plugin and has been exercised by production integrations. It builds on the Guidelines experiment, [proposed](https://make.wordpress.org/ai/2026/02/03/content-guidelines-a-gutenberg-experiment/) in February and [landed in Gutenberg 22.7](https://make.wordpress.org/ai/2026/03/23/guidelines-lands-in-gutenberg-22-7/) in March, then shaped through community feedback into [a consolidated design](https://github.com/WordPress/gutenberg/issues/77230) and stabilized for core.\n\n## Purpose & goals\n\nMost sites already have content standards, but they live outside WordPress in documents, wikis, and institutional knowledge. Guidelines gives them a canonical home inside WordPress, available where they matter: during writing and editing.\n\nA single store of standards serves everyone who works on a site: writers and editors applying them by hand, plugins reading them, and AI assistants drawing on them too. Each of these needs the same thing, persistent and structured knowledge about the site, and today there is no shared place to keep it. Without a common primitive, every plugin ships its own storage, its own permissions model, and its own REST surface. That is exactly the kind of fragmentation WordPress core has historically prevented, the same way `wp_template`, `wp_block`, and `nav_menu_item` prevented parallel solutions in their domains. Core owns the primitive. The community decides what to build on it.\n\nThe name follows that intent. “Guideline” describes prescriptive records well but fits memories and working notes much less naturally, while “Knowledge” covers both procedural content (how work should be done) and declarative content (what is known). Knowledge names the namespace. Individual records are referred to by their concrete type, a guideline, a memory, a note. The user-facing feature in WP Admin remains Guidelines, the same way the `attachment` post type surfaces as Media at `/wp/v2/media`.\n\nThe goals, concretely:\n\n- Provide a canonical storage primitive for author-facing and agent-facing site knowledge\n- Ship Guidelines as the first feature built on it, demonstrating the primitive in core\n- Replace fragmented plugin-specific storage, capability, and REST models with one shared foundation\n\n## Non-goals\n\nThis merge ships storage and access, not intelligence: no AI provider, no model, no retrieval algorithm, and no autonomous memory system. The specifics below are intentionally out of scope. They remain open topics, just not blockers:\n\n- No decay, consolidation, or retrieval mechanism in core. Consuming tools accommodate staleness above the primitive.\n- Further built-in types are deferred and can be registered by plugins in the meantime:\n    -   `skill` – a procedure that can load and apply a guideline, is planned for 7.2 pending settled loading and discovery semantics ([ai#430](https://github.com/WordPress/ai/issues/430))\n    -   `plan` – task-scoped working state for a multi-step task, pending a side-effect and lifecycle model\n    -   `artifact` – a reference to a versioned work product distinct from the freeform text covered by `note`, explored separately\n- Load applicability of scopes (when a scope’s guidance applies beyond the universal `site` scope) is left for its own discussion.\n- Session state and cross-site user preferences live above the primitive.\n- Encryption at rest is orthogonal hardening that can land later without changing the data model.\n\n## What we propose to merge in 7.1\n\n- The `wp_knowledge` custom post type with native revision support\n- The `wp_knowledge_type` taxonomy and the `wp_knowledge_types` registration filter\n- The built-in types `guideline`, `memory`, and `note` (defined below)\n- The `*_knowledge_item` capability namespace and the access model described below\n- The generic `/wp/v2/knowledge` REST routes for working with knowledge records like other post types\n- The Guidelines Settings page: per-scope `guideline` records, a filterable scope registry as the source of truth for the UI, and a read-only registry route at `/wp/v2/knowledge/guideline-scopes`\n\nThe knowledge management ability, registered through the Abilities API, is expected to follow in a later release.\n\n## Built-in types\n\nEach type is defined by what the record represents and how it is applied:\n\n- **`guideline`** – a standard, pure text that is the source of truth, such as voice, tone, image guidance, or per-block rules. A guideline does nothing on its own. It is there to be applied, either directly by an ability that pulls the text in or through a skill that loads it. The site-wide standards managed on the Settings page carry this type.\n- **`memory`** – durable context explicitly saved or approved for future use, such as user preferences, stable facts, and profile context. Records are private and author-owned. The explicit save-or-approve rule is deliberate: core ships a storage primitive, not a memory architecture. Decay, consolidation, and retrieval remain things to build on top.\n- **`note`** – private freeform working text, such as sticky notes, drafts, and notes synced from external tools. A record saved without a type falls back to `note`.\n\nPlugins register their own types through the same filter. A plugin might add a `glossary` type to keep domain terminology consistent across writers, editors, and any agent that reads it:\n\n```\nfunction my_plugin_register_knowledge_types( array $types ): array {\n\t$types['glossary'] = array(\n\t\t'title' => __( 'Glossary', 'my-plugin' ),\n\t);\n\n\treturn $types;\n}\nadd_filter( 'wp_knowledge_types', 'my_plugin_register_knowledge_types' );\n```\n\nCore relies only on the semantics of the built-in slugs it ships. Plugin types are free to define their own behavior.\n\n## Guideline scopes\n\nGuideline scopes define the sections shown in *Settings → Guidelines* and the reserved slugs used to address the corresponding `guideline` records. Core ships scopes such as Site, Copy, Images, and Blocks, each one a `guideline` record at a reserved slug like `guideline-copy`. Plugins register additional scopes through a filter, and the Settings page reads the registry through a read-only REST route at `/wp/v2/knowledge/guideline-scopes`.\n\nScopes are not knowledge types. The `wp_knowledge_type` taxonomy answers what kind of record this is (`guideline`, `memory`, `note`). The scope registry answers where a guideline applies in the Guidelines UI. A scope is addressed by its reserved slug, not a taxonomy term, since a term per scope would attach to exactly one record and duplicate identity into a second system.\n\n## Privacy, security, and access model\n\nKnowledge records are not exposed as a public index. The post type is registered as an internal storage primitive, not a front-end content type: it is not publicly queryable, and management flows through the Guidelines UI, REST, and registered programmatic surfaces rather than a native public post-type UI. Collection reads require authentication, per-item reads are capability-checked through `read_post`, and non-publishers can only create `private` records. New records default to private on creation.\n\n**Actor**\n\n**Site-wide guideline records**\n\n**Own private records**\n\n**Others’ private records**\n\n**Publish / manage global records**\n\nSubscriber\n\nNo\n\nNo\n\nNo\n\nNo\n\nContributor\n\nRead where capabilities allow\n\nCreate, read, edit, delete\n\nNo\n\nNo\n\nAuthor / Editor\n\nRead where capabilities allow\n\nCreate, read, edit, delete\n\nNo\n\nNo\n\nAdministrator\n\nManage\n\nYes\n\nYes\n\nYes\n\nThis matrix reflects the access policy from [gutenberg#78296](https://github.com/WordPress/gutenberg/pull/78296) and will be aligned exactly with the final core patch. The built-in type set is defined in code through a filter, while the underlying taxonomy terms are created lazily when a record is first saved with a given type, so authoring a record can create its term. Revisions are retained, and autosave is disabled, since knowledge records have no editor session.\n\n## Testing\n\nEnable the Guidelines experiment in Gutenberg and verify:\n\n- *Settings → Guidelines* renders its sections from the scope registry, and each scope can be edited, revised, and restored through the REST API\n- The scope registry route returns core scopes and plugin-registered scopes\n- A Contributor can create and read only their own private records, and a Subscriber cannot access the post type through REST\n- REST collection reads require authentication, and non-publishers cannot create published records\n- No knowledge records are exposed through front-end public queries\n\nAutomated coverage for the controller, capability mapping, and type registry ships with the implementation and will be part of the core patch.\n\n## FAQ\n\n**Is this an AI-only feature?** No. The storage primitive is already used for plain note-taking and draft syncing with no AI involved, and the Guidelines experience serves any multi-author site that wants consistent standards. AI tools are one consumer among several.\n\n**Does WordPress now have a “memory system”?** No. Core ships storage with a clear access policy. A `memory` record is a durable context a user explicitly saved, comparable to a private post. Anything resembling a memory architecture, including relevance ranking, decay, or consolidation, is left to plugins and integration layers by design.\n\n**What about existing plugins that store AI context their own way?** Nothing breaks. Plugins can keep their own storage or adopt the shared primitive to gain interoperability, revisions, and the capability model for free.\n\n## Timeline\n\nThe core patch is open for review as [wordpress-develop#12201](https://github.com/WordPress/wordpress-develop/pull/12201), tracked in [Trac #65476](https://core.trac.wordpress.org/ticket/65476). It is backed by the Gutenberg work the feature grew from: the [rename to the wp\\_knowledge namespace](https://github.com/WordPress/gutenberg/pull/79149) and the [follow-up](https://github.com/WordPress/gutenberg/pull/79263) that migrates Guidelines to use the improved structure.\n\nThe naming and scope model are settled, so this proposal moves forward on that basis unless a blocker surfaces. The open question is narrower: is the API ready to stabilize for core? The names freeze at WordPress 7.1 Beta 1 on **July 15**, when the post type, taxonomy, REST routes, capabilities, and type slugs become long-term compatibility commitments. Feedback that would block stabilizing for core is most useful in the next three weeks, while there is still room to act on it.\n\n## Call for feedback\n\nThe questions below are where input matters most before these decisions become core commitments:\n\n- Is `wp_knowledge` the right long-term name for the primitive, and are `guideline`, `memory`, and `note` the right built-in type slugs?\n- Are the capability boundaries in the access model correct?\n- Is anything missing that should be settled before these names become core compatibility commitments?\n\nThe best places to respond are the comments below, the [tracking issue](https://github.com/WordPress/gutenberg/issues/75171), and the [#core-ai](https://wordpress.slack.com/archives/C08TJ8BPULS) channel in WordPress Slack.\n\n*Props to [@aagam94](https://profiles.wordpress.org/aagam94/), [@artpi](https://profiles.wordpress.org/artpi/), [@jason\\_the\\_adams](https://profiles.wordpress.org/jason_the_adams/), and [@jorgefilipecosta](https://profiles.wordpress.org/jorgefilipecosta/) for review and feedback on this merge proposal.*\n\n[#7-1](https://make.wordpress.org/core/tag/7-1/), [#guidelines](https://make.wordpress.org/core/tag/guidelines/), [#knowledge](https://make.wordpress.org/core/tag/knowledge/), [#merge-proposals](https://make.wordpress.org/core/tag/merge-proposals/)","publishedAt":"2026-06-22T07:46:17.000Z","url":"https://make.wordpress.org/core/2026/06/22/merge-proposal-guidelines-built-on-knowledge/","media":[],"prerelease":false,"source":{"slug":"wordpress-core-dev-notes","name":"WordPress Core Dev Notes","type":"feed"},"org":{"slug":"wordpress","name":"WordPress"},"product":null,"groupSlug":"wordpress-core-dev-notes","groupName":"WordPress Core Dev Notes","coverageCount":0,"composition":{"bugs":0,"features":6,"enhancements":0}},{"id":"rel_Q1h9k6kEzJjGmlJms-0yd","version":"7.1","type":"feature","title":"Roadmap to 7.1","summary":"WordPress 7.1 introduces a persistent Guidelines feature for encoding editorial rules and brand voice into AI tooling, adds AI Client generation streaming and embedding support, and reorganizes the command palette with recent and suggested sections. Other planned work includes a dedicated Identity screen, responsive and pseudo-state styling in the Site Editor, admin color scheme support in the Site Editor, and a new On This Day dashboard widget.","titleGenerated":"WordPress 7.1 roadmap: Guidelines feature, AI streaming, and command palette overhaul","titleShort":"Guidelines feature, AI streaming, command palette overhaul","content":"WordPress 7.1 is set to be released on August 19th, 2026. This release advances how people work together in WordPress, with collaboration as a throughline: new Notes features like suggestion mode and emoji reactions make asynchronous feedback richer, while real-time collaboration remains an exciting focus area, with strategic questions still to answer around exactly how it’ll show up in the WordPress experience. Closely tied to this is a new Guidelines feature, a persistent, structured way to encode editorial rules into WordPress so you can keep your voice and preferences when collaborating with AI. Longstanding styling gaps are being tackled too, with responsive styling and pseudo-state styling underway, expanding what you can do directly in the Site Editor without touching CSS. Several new options make it easier to find your way around: see when a block inherits its styling from a global setting, set key details about your site in a new Identity section in the Site Editor, jump to what you need faster with recently used commands and suggestions in the command palette, and enjoy the familiarity and functionality of the admin bar inside any of the editors. The experience of uploading and using media gets numerous updates, including a new free-form image cropper for getting your images just right and client-side media improvements that support more image formats and add resiliency throughout. Numerous APIs are slated for iteration, and expanded Unicode support is in the works so email addresses, usernames, and slugs can better reflect WordPress’ global audience. Throughout, smaller delights like a new “On This Day” dashboard widget, new blocks, and various writing flow improvements round out the release.\n\n**As always, what’s shared here is being actively pursued, but doesn’t necessarily mean each will make it into the final release of WordPress 7.1.**\n\nFor those who want to be involved in the release in a different, more hands on way, there’s a new dedicated outreach effort for WordPress 7.1 to ensure collaborative editing gets the collaborative testing it needs. [Learn more here](https://make.wordpress.org/core/2026/06/03/announcing-a-collaborative-editing-outreach-effort-for-7-1/). \n\n## **AI**\n\n**AI Client iteration**\n\nThe AI Client is the foundational piece for running AI programmatically inside WordPress, and for 7.1 the focus stays on empowering plugin authors. Two notable capabilities are planned: generation streaming, introduced first in the [PHP AI Client](https://github.com/wordpress/php-ai-client/) as an initial effort to unlock full usage in a future release, and [embeddings](https://github.com/WordPress/ai/pull/683), which represent content as vectors to enable meaning-based search across a site. These arrive alongside minor fixes that keep improving the reliability of the AI Client.\n\n**Connectors iteration**\n\nAfter landing a new framework for registering and managing connections to external services in 7.0, work is underway for connectors to gain more ways to authenticate beyond API keys: the plan is to start simple with adding username/application password support similar to the existing API key flow and then explore more general, declaratively-defined connection forms (URLs, a default-models dropdown, and more) in PHP, advancing the DataForm API in the process. \n\n*Follow* [*this iteration issue*](https://github.com/WordPress/gutenberg/issues/78647) *and* [*this Trac ticket*](https://core.trac.wordpress.org/ticket/64850) *for more details, along with the related DataForm issues* [*#76544*](https://github.com/WordPress/gutenberg/issues/76544) *and* [*#74865*](https://github.com/WordPress/gutenberg/issues/74865)*.*\n\n**Guidelines**\n\n[![View of the Guidelines section in the WordPress admin against a blue background.](https://make.wordpress.org/core/files/2026/06/7-1-roadmap-guidelines-scaled.png)](https://make.wordpress.org/core/files/2026/06/7-1-roadmap-guidelines-scaled.png)\n\nAfter shipping early as an experiment in Gutenberg to gather feedback, a new Guidelines feature lets you define writing and content guidelines that tie into AI tooling, with the ability to import/export guidelines between sites. This brings a persistent, structured system for encoding editorial rules, brand voice, and content standards directly into WordPress. As more collaboration happens directly in WordPress, this brings consistency and personalization to that collaboration when AI is involved. \n\n*Follow* [*this GitHub issue*](https://github.com/WordPress/gutenberg/issues/75171) *for more details.*\n\n## **Admin**\n\n**A more organized command palette**\n\nThe command palette, the Cmd/Ctrl+K overlay for jumping around the editor and running actions, is becoming smarter to navigate with. Results are now grouped into clear sections for recent, suggested, and matching commands, and a “Recently used” list keeps the commands you reach for most within easy reach, saved to your preferences so they persist across sessions. The palette also gets a roomier layout, making the whole list easier to scan.\n\n*Review* [*this pull request*](https://github.com/WordPress/gutenberg/pull/75691) *for more details.*\n\n**Admin color scheme reflected in the Site Editor**\n\nThe Site Editor sidebar and overall shell now follow the set WordPress admin color scheme instead of always using a fixed dark background. This ensures broader consistency across all parts of the WordPress experience when choosing to personalize the admin.\n\n*Review* [*this pull request*](https://github.com/WordPress/gutenberg/pull/78397) *for more details.* \n\n**DataViews and DataForms iterations**\n\nWork is underway to migrate DataViews onto the new Design System primitives for a more consistent look and feel, and to consolidate Quick Edit with the editor inspector so editing a post’s details feels the same wherever you do it. The DataForm API itself is growing more capable, including support for disabling individual controls. The Site Editor’s Pages, Templates, and Patterns screens are also becoming more extensible, with a new server-side REST endpoint that lets plugin authors register their own view and form configuration.\n\n*Follow* [*this iteration issue*](https://github.com/WordPress/gutenberg/issues/76045) *for more details.*\n\n**Dedicated Identity section**\n\nA dedicated Design → Identity screen brings the essentials of your site’s identity into one place, with an inline media editor for your logo and favicon and live editing of your site title and tagline against the site’s root entity. The aim is to make these foundational settings quick to find and simple to update without digging into templates or needing to go searching in your wider site’s Settings. \n\n*Review* [*this pull request*](https://github.com/WordPress/gutenberg/pull/76264) *for more details.* \n\n**Design System**\n\nWork continues on the shared component library in wordpress/ui and the underlying theming system that powers it. A highlight of this cycle is graduating ThemeProvider from experimental to a stable, public API, alongside finalizing the public token names (background, foreground, and stroke renames) before they lock in, and adding new theme-customization tokens for corner radius and element sizing. In parallel, key parts of the editor UI begin adopting improved components, with flyout menus extending to transforms, style variations, and the block ellipsis and transform menus.\n\n*Follow* [*this tracking issue*](https://github.com/WordPress/gutenberg/issues/76941) *for more details.*\n\n**New “On This Day” widget**\n\n[![WordPress dashboard focused on an \"On This Day\" widget showing a post from 10 years ago. ](https://make.wordpress.org/core/files/2026/06/7-1-roadmap-onthisday-scaled.png)](https://make.wordpress.org/core/files/2026/06/7-1-roadmap-onthisday-scaled.png)\n\nThe dashboard is getting a new “On This Day” widget that resurfaces past content, a popular feature across many different platforms. Get motivated by looking back on what you’ve written and write more content today for future reminders.\n\n*Follow* [*this pull request*](https://github.com/WordPress/wordpress-develop/pull/11630) *introducing the “On This Day” widget for more information.*\n\n**Persistent admin bar across editors (aka omnibar)**\n\n[![](https://make.wordpress.org/core/files/2026/06/7-1-roadmap-omnibar-scaled.png)](https://make.wordpress.org/core/files/2026/06/7-1-roadmap-omnibar-scaled.png)\n\nThe admin bar is getting some nice polish ahead of being easily accessible in the Site Editor and Block Editor. Having landed as an experiment in Gutenberg, the work brings the toolbar into the editing experience while polishing long-standing rough edges: removing the “Howdy” greeting, replacing the home icon with the set site icon, making the profile avatar a circle rather than a square, and replacing the legacy Dashicons icon font with wordpress/icons SVGs throughout the admin bar.\n\n*Follow* [*this iteration issue*](https://github.com/WordPress/gutenberg/issues/79036) *for more details.*\n\n**Revisions iterations**\n\nRevisions are becoming easier to read and navigate. Planned improvements include a spark line view in the scrubbing toolbar to visualize the shape of a document’s history, better representation of edits across authors, and the ability to jump to revisions from a specific author. This work dovetails nicely with real-time collaboration.\n\n*Follow* [*this iteration issue*](https://github.com/WordPress/gutenberg/issues/79120) *for more details.*\n\n## **APIs**\n\n**Abilities API iteration**\n\nThe Abilities API gives developers and AI tooling a structured, queryable way to expose what a WordPress site can do. This cycle advances querying and filtering of abilities and implements a curated set of core abilities (including site settings, current-user info management, and general site awareness).\n\n*Review* [*this trac query*](https://core.trac.wordpress.org/query?status=accepted&status=assigned&status=closed&status=new&status=reopened&status=reviewing&component=Abilities+API&milestone=7.1&group=resolution&col=id&col=summary&col=owner&col=type&col=priority&col=version&col=severity&order=priority) *for more details.*\n\n**Block Bindings iterations**\n\nBlock Bindings gain more reach, with new support for binding list-item blocks and inner blocks, letting more of your content connect to dynamic data sources.\n\n*Follow* [*this pull request*](https://github.com/WordPress/wordpress-develop/pull/12113) *adding list-item support for more information.*\n\n**Enforced iframed editor**\n\nThe post editor has been moving toward always running inside an iframe, which isolates the editing canvas from the admin’s styles and lets viewport-relative units and media queries work against the canvas instead of the browser window. Today the editor still drops back to a non-iframed mode whenever a block using Block API version 2 or lower is present. To make the rollout gradual, the current plan is to enforce iframing for block-based themes in this release, then extend it to all themes in a future release. In both cases, blocks need to be on Block API version 3 to work in the iframed editor, and a migration guide is available to help extenders get there.\n\n*Read the* [*dev note on the 7.0 changes*](https://make.wordpress.org/core/2026/02/24/iframed-editor-changes-in-wordpress-7-0/) *and the* [*block migration guide*](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-api-versions/block-migration-for-iframe-editor-compatibility/) *for more details.*\n\n**Extended Unicode support in email addresses, usernames, and slugs**\n\nThis release is looking to broaden Unicode support so email addresses, usernames, and slugs better reflect WordPress’ global audience. This work centers around allowing storing Unicode email addresses ([Core-31992](https://core.trac.wordpress.org/ticket/31992)) so functions like `is_email()`, `sanitize_email()` and `antispambot()` can be extended to support non-ASCII addresses. \n\n*Read* [*this Make Core post*](https://make.wordpress.org/core/2026/05/22/extending-unicode-support-in-email-addresses-usernames-and-slugs/) *and follow* [*this Trac ticket*](https://core.trac.wordpress.org/ticket/31992) *for more details.*\n\n**React 19 Upgrade**\n\nWordPress is upgrading from React 18 to React 19. This update will first be merged into the Gutenberg plugin ahead of an eventual pathway to Core. In this upgrade, there are several new APIs, major updates to TypeScript types, changed behaviors and more. Plugin and theme developers, [please help test](https://make.wordpress.org/core/2026/05/27/react-19-upgrade-in-wordpress/) and [review what’s coming](https://react.dev/blog/2024/04/25/react-19-upgrade-guide) as early and as much as possible. To help with testing, install and activate the latest version of Gutenberg, head to the experiments page, and turn on the “React 19” experiment.\n\n*Follow* [*this tracking issue*](https://github.com/WordPress/gutenberg/issues/71336) *and read* [*this Make Core post*](https://make.wordpress.org/core/2026/05/27/react-19-upgrade-in-wordpress/) *for more details.*\n\n## **Blocks**\n\n**Icon API expansion**\n\nAfter WordPress 7.0 introduced the foundations of the SVG Icon API ( the icon registry, a REST endpoint, and the core Icon block), 7.1’s iteration centers on opening the API up to third parties: new public functions like register\\_icon() and unregister\\_icon(), core-icons theme support, SVG sanitization and namespace validation, and collection support (similar to the Font Library) so agencies and product makers can ship their own branded icon sets. The work also explores a reusable icon picker modal for any block, Icon block enhancements like flip and rotate, and making the hard-coded icons in blocks such as Navigation, Breadcrumbs, and Details selectable through the Icon API. Alongside the API work, the core icon set itself is getting a visual refresh, with prominent icons [redrawn as stroke-based designs](https://github.com/WordPress/gutenberg/pull/78808) for a more consistent, modern look.\n\n*Follow* [*this iteration issue*](https://github.com/WordPress/gutenberg/issues/75715#issuecomment-4679395256) *for more details.*\n\n**Lazy loading the Classic block**\n\nTo improve performance, the Classic block is planned for deprecation in 7.1, with TinyMCE no longer loaded by default when it isn’t needed. This work improves migration and conversion paths and moves the freeform block into its own package, so sites that don’t rely on the classic experience get a lighter, faster editor. To help with testing, install and activate the latest version of Gutenberg, head to the experiments page, and turn on the “Classic block deprecation” experiment.\n\n*Follow* [*this tracking issue*](https://github.com/WordPress/gutenberg/issues/78067) *for more details.*\n\n**More Core blocks and block improvements** \n\n[![The editor opened with a playlist block visible, listing out three songs.](https://make.wordpress.org/core/files/2026/06/7-1-roadmap-playlist-scaled.png)](https://make.wordpress.org/core/files/2026/06/7-1-roadmap-playlist-scaled.png)\n\nEvery new block added to Core means new possibilities for all, without needing to rely on third party blocks. 7.1 has a few new Core blocks slated for inclusion:\n\n- [Playlist block](https://github.com/WordPress/gutenberg/issues/77421), with additional waveform audio visualization.\n- [Table of Contents block](https://github.com/WordPress/gutenberg/issues/42229), automatically generating navigable links to the headings in your content.\n- [Tabs block](https://github.com/WordPress/gutenberg/issues/73230), organizes content into tabbed panels.\n\nAlongside these new blocks are a set of upgrades to current block functionality to help you do more with what’s already there:\n\n- [Gallery block lightbox refinements](https://github.com/WordPress/gutenberg/issues/56587), including swipe indication and opt-in captions on mobile.\n- [New block support for the HTML block](https://github.com/WordPress/gutenberg/pull/79115), making it possible to have editable blocks inside of a custom HTML block. This is especially useful with AI generated sites, since LLMs often create custom HTML. \n- [“Mark as decorative” toggle](https://github.com/WordPress/gutenberg/pull/78064#top) for the Image block to hide decorative images from screen readers for an improved experience. \n- [An shortcode transform was added to the Embed block](https://github.com/WordPress/gutenberg/pull/77937), so converting or pasting shortcodes now creates a proper Embed block instead of leaving raw shortcode text behind.\n- [Block specific transforms were added to the Shortcode block](https://github.com/WordPress/gutenberg/pull/77944) when text matches a registered shortcode. This makes it much easier to convert a shortcode into a comparable block.\n- [The Group block added support for background gradients through a new background.gradient block support](https://github.com/WordPress/gutenberg/pull/75859), allowing gradients and background images to work together without conflicts. \n\nThis is a great area to contribute to the release. If interested, please help with the [Dialog block](https://github.com/WordPress/gutenberg/issues/61297) for transcripts and conversations and the [Marquee block](https://github.com/WordPress/gutenberg/issues/41730) for scrolling, animated content as these both are on the list of blocks to add but don’t have a champion. \n\n**Writing flow and drag-and-drop improvements**\n\nWriting and arranging content keeps getting smoother. The goal is to improve drag-and-drop enough to remove the toolbar drag handle entirely, make multi-selection work on touch devices, and refine inline insertion and inline images.\n\n*Follow* [*this tracking issue*](https://github.com/WordPress/gutenberg/issues/63255) *for more details.*\n\n## **Collaboration**\n\n**New Notes features**\n\n[![A Note in the editor with emojis listed to react with. ](https://make.wordpress.org/core/files/2026/06/Frame-2147226206.png)](https://make.wordpress.org/core/files/2026/06/Frame-2147226206.png)\n\nNotes have a range of planned improvements that include notes on specific content within a block and across multiple blocks, rich text in notes, notifications for replies and follows, emoji reactions, a minified notes experience, and an “apply suggestions” feature that works from note replies so assistants can act on them in a thread. All of these help provide a richer, more interactive experience of collaborating with others directly in the editor.\n\n*Follow* [*this iteration issue*](https://github.com/WordPress/gutenberg/issues/76316) *for more details.*\n\n**Real-time collaboration**\n\nImagine a world with no post lock screen and with collaborators of all kinds (human and AI) working together to share content with the world through WordPress. After a monumental effort ahead of the last release, real-time collaboration marches ahead with that vision in mind and with big, open strategy questions around:\n\n- What to land in this release (full feature vs the underlying architecture)? [This came up in a Core Committer meeting at WCEU](https://make.wordpress.org/core/2026/06/15/core-committers-meeting-wordcamp-europe-2026/) and is important to directly call out.\n- [What storage mechanism to use](https://make.wordpress.org/core/2026/05/08/results-real-time-collaboration-performance-testing-analysis/)? There’s a clear winner that still needs to be decided upon.\n\nThese decisions, along with the readiness of the feature, are the key aspects to get right for all of WordPress and to align with project leadership on. They impact who gets access to the feature and what the experience will be like. To help aid the decision making and reliability of the feature, there’s a new dedicated outreach effort for WordPress 7.1 to ensure collaborative editing gets the collaborative testing it needs. Please consider getting involved and [learn more here](https://make.wordpress.org/core/2026/06/03/announcing-a-collaborative-editing-outreach-effort-for-7-1/). \n\n*Follow* [*this iteration issue*](https://github.com/WordPress/gutenberg/issues/76377) *for more details.*\n\n## **Customization**\n\n**Display inherited styles**\n\nWhen you’re styling a block, it isn’t always clear which styles are coming from the theme, a parent, or global styles. This work explores surfacing inherited styles clearly in the sidebar so you can understand where a block’s styles are coming from and edit at the right layer of styling, whether that’s a global or local change.\n\n*Follow* [*this tracking issue*](https://github.com/WordPress/gutenberg/issues/77595) *for more details.*\n\n**Interactive states styling**\n\n[![A button block with viewport and pseudo state options visible. ](https://make.wordpress.org/core/files/2026/06/7-1-roadmap-states.png)](https://make.wordpress.org/core/files/2026/06/7-1-roadmap-states.png)\n\nA standardized way to style interactive states is taking shape. Support for pseudo-state styling such as hover, focus, and active has landed for both Global Styles and individual block instances, building on the broader “states” effort. Further work, including custom states like styling the current menu item, continues beyond 7.1. All of this work means you can begin to style how blocks respond to interaction, like buttons changing color on hover, all without writing a line of CSS.\n\n*Follow* [*this tracking issue*](https://github.com/WordPress/gutenberg/issues/38277) *for more details.* \n\n**Pattern editing iterations**\n\nWith WordPress 7.0, the experience of using patterns shifted to be more like editing a single block with a focus on content changes than exposing every tool available for every block in a pattern. For this cycle, work will focus on UX improvements based on feedback around this change, bug fixes, and general maintenance. \n\n*Follow* [*this iteration issue*](https://github.com/WordPress/gutenberg/issues/75717) *for more details.*\n\n**Responsive styling** \n\n[![View of the option to switch into a responsive editing mode.](https://make.wordpress.org/core/files/2026/06/7-1-roadmap-responsive-styling.png)](https://make.wordpress.org/core/files/2026/06/7-1-roadmap-responsive-styling.png)\n\nResponsive styling for blocks has been a long requested feature and 7.1 aims to be a big step towards more support. Building on the same style states mechanism that powers the interactive states styling for blocks, this work lets you define how a block looks at different screen sizes. This means you can apply responsive styles, like a font size at a certain viewport, directly in the editor without writing custom CSS. The feature will be available both for global styles that apply across every instance of a block, and for individual block instances. The aim is to make responsive design a built-in, first-class part of the editing experience.\n\n*Follow* [*this iteration issue*](https://github.com/WordPress/gutenberg/issues/77817) *for more details.*\n\n**Viewport breakpoint customization**\n\nAfter adding the ability to hide or show blocks based on viewport, theme-configurable breakpoints defined in theme.json are being added to provide more flexible, customizable responsive styling.\n\n*Follow* [*this iteration issue*](https://github.com/WordPress/gutenberg/issues/75707) *for more details.*\n\n## **Media**\n\n**Client-side media iterations**\n\nAfter being punted from 7.0, client-side media processing keeps getting more capable and resilient ahead of this release. The work spans HEIC image support, Ultra HDR support, GIF-to-video conversion, more resilient uploads that retry on failure and resume after a crash or going offline, video transcoding to web-safe formats, optimization of previously uploaded media, and local poster generation during video upload so pages can render before a video finishes loading.\n\n*Follow* [*this iteration issue*](https://github.com/WordPress/gutenberg/issues/76756) *for more details.*\n\n**Media editor modal**\n\nThe Media editor modal replaces the existing inline cropping tool in the Block Editor. The modal pattern keeps the familiar Crop button entry point, and brings freeform and aspect-ratio cropping, flip, fine-grained and snap rotation, and metadata editing into one dedicated workflow.\n\n*Follow* [*this tracking issue*](https://github.com/WordPress/gutenberg/issues/73771) *for more details.*\n\n**Media gallery improvements**\n\nGalleries are becoming more dynamic and easier to build, with better handling of the legacy gallery shortcode on conversion, dynamic galleries that can sort or pull media attached to a post, and a quicker path in the inserter’s media tab to images attached to the current post  with thumbnails shown directly. \n\n*Follow* [*this tracking issue*](https://github.com/WordPress/gutenberg/issues/77117) *for more details.*\n\n## **Performance improvements**\n\nThe core performance change planned for 7.1 is an update to speculative loading: when both object caching and page caching are detected, the default eagerness would move from conservative to moderate, prefetching and prerendering more readily on sites equipped to handle it so navigation feels faster.\n\n*Follow* [*this Trac ticket*](https://core.trac.wordpress.org/ticket/64066) *for more details.*\n\nTwo further efforts are being iterated on within feature plugins you can install and benefit from today. Work in the [View Transitions plugin](https://wordpress.org/plugins/view-transitions/) centers around bringing smooth, animated transitions between pages on the front end. Work in the [Enhanced Responsive Images plugin](https://wordpress.org/plugins/auto-sizes/) computes more accurate sizes values in block themes so browsers download appropriately sized images. Both are in active development, and interested contributors are welcome to help move them forward.\n\n*Follow the* [*View Transitions*](https://github.com/WordPress/performance/issues?q=is%3Aopen+label%3A%22%5BPlugin%5D+View+Transitions%22) *and* [*Enhanced Responsive Images*](https://github.com/WordPress/performance/issues?q=is%3Aopen+label%3A%22%5BPlugin%5D+Enhanced+Responsive+Images%22) *issues for more details.*\n\n## **Find something missing? Want to help?**\n\nIf you have something you’re working on that you don’t see reflected in this post, please share a comment below so we can all be aware! If you’re reading this and want to help, start with the above items and/or ping me ([@annezazu](https://profiles.wordpress.org/annezazu/)) in the [7.1 release leads channel](https://wordpress.slack.com/archives/C0B4Q0RJVAT). I have a list of projects that were punted from this release that I’m happy to talk to people about taking on. \n\n*Thank you to [@ramonopoly](https://profiles.wordpress.org/ramonopoly/) [@isabel\\_brison](https://profiles.wordpress.org/isabel_brison/) [@ellatrix](https://profiles.wordpress.org/ellatrix/) [@gziolo](https://profiles.wordpress.org/gziolo/) [@jason\\_the\\_adams](https://profiles.wordpress.org/jason_the_adams/) [@ntsekouras](https://profiles.wordpress.org/ntsekouras/) (and many others I might be forgetting) for reviews.*\n\n[#7-1](https://make.wordpress.org/core/tag/7-1/) [#release-roadmap](https://make.wordpress.org/core/tag/release-roadmap/)","publishedAt":"2026-06-19T00:04:09.000Z","url":"https://make.wordpress.org/core/2026/06/19/roadmap-to-7-1/","media":[{"type":"image","url":"https://make.wordpress.org/core/files/2026/06/7-1-roadmap-guidelines-scaled.png","alt":"View of the Guidelines section in the WordPress admin against a blue background.","r2Key":"releases/de0fec59a013443d0d449a988531cbfee12ec192554da82c96762941e5708b7f.png","r2Url":"https://media.releases.sh/releases/de0fec59a013443d0d449a988531cbfee12ec192554da82c96762941e5708b7f.png"},{"type":"image","url":"https://make.wordpress.org/core/files/2026/06/7-1-roadmap-onthisday-scaled.png","alt":"WordPress dashboard focused on an ","r2Key":"releases/21ed950ff93ec17db70a9add16ae665443a55cdcf54de10b6d704bf037725b26.png","r2Url":"https://media.releases.sh/releases/21ed950ff93ec17db70a9add16ae665443a55cdcf54de10b6d704bf037725b26.png"},{"type":"image","url":"https://make.wordpress.org/core/files/2026/06/7-1-roadmap-omnibar-scaled.png","r2Key":"releases/293386286d3d6ce5a1f63ad8f9e459913eee227ade72fe781f58761199df0a79.png","r2Url":"https://media.releases.sh/releases/293386286d3d6ce5a1f63ad8f9e459913eee227ade72fe781f58761199df0a79.png"},{"type":"image","url":"https://make.wordpress.org/core/files/2026/06/7-1-roadmap-playlist-scaled.png","alt":"The editor opened with a playlist block visible, listing out three songs.","r2Key":"releases/a45417a417018c5a58408ae9fb390477428a92256b8671a460310a0ef705b568.png","r2Url":"https://media.releases.sh/releases/a45417a417018c5a58408ae9fb390477428a92256b8671a460310a0ef705b568.png"},{"type":"image","url":"https://make.wordpress.org/core/files/2026/06/Frame-2147226206.png","alt":"A Note in the editor with emojis listed to react with. ","r2Key":"releases/07053d50a686b452706e349c72a18b3462df3e78951f75f203f337233a021cfe.png","r2Url":"https://media.releases.sh/releases/07053d50a686b452706e349c72a18b3462df3e78951f75f203f337233a021cfe.png"},{"type":"image","url":"https://make.wordpress.org/core/files/2026/06/7-1-roadmap-states.png","alt":"A button block with viewport and pseudo state options visible. ","r2Key":"releases/2dc7d706541de6fe5f5e3822aea138d38f82e4fcd49c6eee9d3ce2800e2b95b7.png","r2Url":"https://media.releases.sh/releases/2dc7d706541de6fe5f5e3822aea138d38f82e4fcd49c6eee9d3ce2800e2b95b7.png"},{"type":"image","url":"https://make.wordpress.org/core/files/2026/06/7-1-roadmap-responsive-styling.png","alt":"View of the option to switch into a responsive editing mode.","r2Key":"releases/435a8bc4874d25332e4048828d609ebdcde9da49183173327e30959130ed51cb.png","r2Url":"https://media.releases.sh/releases/435a8bc4874d25332e4048828d609ebdcde9da49183173327e30959130ed51cb.png"}],"prerelease":false,"source":{"slug":"wordpress-core-dev-notes","name":"WordPress Core Dev Notes","type":"feed"},"org":{"slug":"wordpress","name":"WordPress"},"product":null,"groupSlug":"wordpress-core-dev-notes","groupName":"WordPress Core Dev Notes","coverageCount":0,"composition":{"bugs":0,"features":8,"enhancements":5}},{"id":"rel_fwfXQmrpV95xrVj8lV_Th","version":"@sveltejs/kit@2.66.0","type":"feature","title":"@sveltejs/kit@2.66.0","summary":"### Minor Changes\n\n\n- feat: precompress prerendered `.md` and `.mdx` files ([#15893](https://github.com/sveltejs/kit/pull/15893))\n\n\n- feat: warn the u...","titleGenerated":null,"titleShort":null,"content":"### Minor Changes\n\n\n- feat: precompress prerendered `.md` and `.mdx` files ([#15893](https://github.com/sveltejs/kit/pull/15893))\n\n\n- feat: warn the user when they forget to make boolean inputs optional in their form schemas ([#15804](https://github.com/sveltejs/kit/pull/15804))\n\n\n### Patch Changes\n\n\n- fix: blur active element before component update during navigation so that blur/focusout handlers fire while old component data is still valid ([#15452](https://github.com/sveltejs/kit/pull/15452))\n\n\n- fix: ensure `base` is available from `$service-worker` during development ([#15882](https://github.com/sveltejs/kit/pull/15882))\n\n\n- fix: use correct relative asset paths when rendering an error page for a missing `__data.json` request ([#15884](https://github.com/sveltejs/kit/pull/15884))\n\n\n- fix: preserve active `for await` consumers across `query.live` reconnects ([#16022](https://github.com/sveltejs/kit/pull/16022))\n\n\n- fix: settle `query.live` reconnect promise on all exit paths, preventing `invalidateAll()` from deadlocking when a live query is offline or interrupted ([#16022](https://github.com/sveltejs/kit/pull/16022))\n\n\n- fix: preserve last value when a `query.live` stream completes without yielding on reconnect ([#16022](https://github.com/sveltejs/kit/pull/16022))\n\n\n- fix: remove `types: ['node']` from generated tsconfig to avoid errors when `@types/node` is not installed ([#15709](https://github.com/sveltejs/kit/pull/15709))\n\n\n- fix: prefer pages over endpoints when prerendering ([#16076](https://github.com/sveltejs/kit/pull/16076))\n\n\n- fix: restore snapshots after afterNavigate callbacks ([#16066](https://github.com/sveltejs/kit/pull/16066))\n\n\n- fix: support `ws:`/`wss:` and `trusted-types-eval` for CSP sources ([#15938](https://github.com/sveltejs/kit/pull/15938))\n\n\n- fix: omit empty `file` inputs from remote form data ([#15898](https://github.com/sveltejs/kit/pull/15898))\n\n\n- fix: fail early if a route with `+page` and `+server` is marked as prerenderable ([#16075](https://github.com/sveltejs/kit/pull/16075))\n\n\n- fix: wait a tick before resetting forms ([#15805](https://github.com/sveltejs/kit/pull/15805))\n\n\n- fix: `preflight` schemas apply correctly when chained before `for` ([#15863](https://github.com/sveltejs/kit/pull/15863))\n\n\n- fix: blank page in SPA mode when root layout `load()` throws ([#15798](https://github.com/sveltejs/kit/pull/15798))\n\n\n- fix: pass all unknown options from the `sveltekit` Vite plugin through to `vite-plugin-svelte` ([#16010](https://github.com/sveltejs/kit/pull/16010))","publishedAt":"2026-06-18T18:37:08.000Z","url":"https://github.com/sveltejs/kit/releases/tag/%40sveltejs/kit%402.66.0","media":[],"prerelease":false,"source":{"slug":"kit","name":"kit","type":"github"},"org":{"slug":"svelte","name":"Svelte"},"product":{"slug":"sveltekit","name":"SvelteKit"},"groupSlug":"sveltekit","groupName":"SvelteKit","coverageCount":0,"composition":null},{"id":"rel_naW7AXLkRiQBCkIxnfAMd","version":"@sveltejs/adapter-node@5.5.5","type":"feature","title":"@sveltejs/adapter-node@5.5.5","summary":"### Patch Changes\n\n\n- fix: bundle entrypoints alongside app code ([#16069](https://github.com/sveltejs/kit/pull/16069))\n\n\n- fix: log the actual adapte...","titleGenerated":null,"titleShort":null,"content":"### Patch Changes\n\n\n- fix: bundle entrypoints alongside app code ([#16069](https://github.com/sveltejs/kit/pull/16069))\n\n\n- fix: log the actual adapter-node listening address ([#15899](https://github.com/sveltejs/kit/pull/15899))\n\n- Updated dependencies [[`63f1b0b`](https://github.com/sveltejs/kit/commit/63f1b0bd0ee2d16ef0c4d1f5bef35afd54d0304a), [`1dbff3f`](https://github.com/sveltejs/kit/commit/1dbff3fec2a335242af8b556c36513dbf9602ea5), [`961ba01`](https://github.com/sveltejs/kit/commit/961ba015ff4f69b954bcb7512a05ccd5ea180eb4), [`d2e108c`](https://github.com/sveltejs/kit/commit/d2e108c13925559c3433b9b46a71174a0f271253), [`d2e108c`](https://github.com/sveltejs/kit/commit/d2e108c13925559c3433b9b46a71174a0f271253), [`d2e108c`](https://github.com/sveltejs/kit/commit/d2e108c13925559c3433b9b46a71174a0f271253), [`860b3c7`](https://github.com/sveltejs/kit/commit/860b3c7d5f52b02fdd07d95305dfdb93357e0ead), [`f8c842c`](https://github.com/sveltejs/kit/commit/f8c842cb8bfb13235bfd6c44f913d51e9e2d70d6), [`d3aa5fe`](https://github.com/sveltejs/kit/commit/d3aa5fe9bdb8fd6bdf0dd75d4575fbcfa37fc560), [`0dd7659`](https://github.com/sveltejs/kit/commit/0dd7659d943e7e635947aed9e96c639e8167b1fb), [`03e9f66`](https://github.com/sveltejs/kit/commit/03e9f660edf026654d65b257d509d4ab190e6f7e), [`57b7b7b`](https://github.com/sveltejs/kit/commit/57b7b7b4f79283b36832450d8476a83cff007526), [`4eabadc`](https://github.com/sveltejs/kit/commit/4eabadca61440dfda690cdd4e8eeb0723fb94258), [`6fbf2b6`](https://github.com/sveltejs/kit/commit/6fbf2b64843123ac2676b04d56085d4c118a91b4), [`276744d`](https://github.com/sveltejs/kit/commit/276744da6585d743d720e8cbaa476bd67ac0fb48), [`8740132`](https://github.com/sveltejs/kit/commit/8740132952c2f7d908b4f1e795f942ad079895be), [`f430a68`](https://github.com/sveltejs/kit/commit/f430a68937744212d2b1bd0ee920cc89cc6f696f), [`1c7a8dc`](https://github.com/sveltejs/kit/commit/1c7a8dca3216b42ff4f69a712e794a485de4d4ee)]:\n  - @sveltejs/kit@2.66.0","publishedAt":"2026-06-18T18:37:05.000Z","url":"https://github.com/sveltejs/kit/releases/tag/%40sveltejs/adapter-node%405.5.5","media":[],"prerelease":false,"source":{"slug":"kit","name":"kit","type":"github"},"org":{"slug":"svelte","name":"Svelte"},"product":{"slug":"sveltekit","name":"SvelteKit"},"groupSlug":"sveltekit","groupName":"SvelteKit","coverageCount":0,"composition":null},{"id":"rel_14fDizBOQnOdcqwhGfR5p","version":"@sveltejs/adapter-vercel@6.3.4","type":"feature","title":"@sveltejs/adapter-vercel@6.3.4","summary":"### Patch Changes\n\n\n- fix: prevent missing immutable assets from being cached as 404s for a year ([#16077](https://github.com/sveltejs/kit/pull/16077)...","titleGenerated":null,"titleShort":null,"content":"### Patch Changes\n\n\n- fix: prevent missing immutable assets from being cached as 404s for a year ([#16077](https://github.com/sveltejs/kit/pull/16077))\n\n- Updated dependencies [[`63f1b0b`](https://github.com/sveltejs/kit/commit/63f1b0bd0ee2d16ef0c4d1f5bef35afd54d0304a), [`1dbff3f`](https://github.com/sveltejs/kit/commit/1dbff3fec2a335242af8b556c36513dbf9602ea5), [`961ba01`](https://github.com/sveltejs/kit/commit/961ba015ff4f69b954bcb7512a05ccd5ea180eb4), [`d2e108c`](https://github.com/sveltejs/kit/commit/d2e108c13925559c3433b9b46a71174a0f271253), [`d2e108c`](https://github.com/sveltejs/kit/commit/d2e108c13925559c3433b9b46a71174a0f271253), [`d2e108c`](https://github.com/sveltejs/kit/commit/d2e108c13925559c3433b9b46a71174a0f271253), [`860b3c7`](https://github.com/sveltejs/kit/commit/860b3c7d5f52b02fdd07d95305dfdb93357e0ead), [`f8c842c`](https://github.com/sveltejs/kit/commit/f8c842cb8bfb13235bfd6c44f913d51e9e2d70d6), [`d3aa5fe`](https://github.com/sveltejs/kit/commit/d3aa5fe9bdb8fd6bdf0dd75d4575fbcfa37fc560), [`0dd7659`](https://github.com/sveltejs/kit/commit/0dd7659d943e7e635947aed9e96c639e8167b1fb), [`03e9f66`](https://github.com/sveltejs/kit/commit/03e9f660edf026654d65b257d509d4ab190e6f7e), [`57b7b7b`](https://github.com/sveltejs/kit/commit/57b7b7b4f79283b36832450d8476a83cff007526), [`4eabadc`](https://github.com/sveltejs/kit/commit/4eabadca61440dfda690cdd4e8eeb0723fb94258), [`6fbf2b6`](https://github.com/sveltejs/kit/commit/6fbf2b64843123ac2676b04d56085d4c118a91b4), [`276744d`](https://github.com/sveltejs/kit/commit/276744da6585d743d720e8cbaa476bd67ac0fb48), [`8740132`](https://github.com/sveltejs/kit/commit/8740132952c2f7d908b4f1e795f942ad079895be), [`f430a68`](https://github.com/sveltejs/kit/commit/f430a68937744212d2b1bd0ee920cc89cc6f696f), [`1c7a8dc`](https://github.com/sveltejs/kit/commit/1c7a8dca3216b42ff4f69a712e794a485de4d4ee)]:\n  - @sveltejs/kit@2.66.0","publishedAt":"2026-06-18T18:37:02.000Z","url":"https://github.com/sveltejs/kit/releases/tag/%40sveltejs/adapter-vercel%406.3.4","media":[],"prerelease":false,"source":{"slug":"kit","name":"kit","type":"github"},"org":{"slug":"svelte","name":"Svelte"},"product":{"slug":"sveltekit","name":"SvelteKit"},"groupSlug":"sveltekit","groupName":"SvelteKit","coverageCount":0,"composition":null},{"id":"rel_xd0P3TheDxi2dx8UPTDcG","version":"@sveltejs/enhanced-img@0.11.0","type":"feature","title":"@sveltejs/enhanced-img@0.11.0","summary":"### Minor Changes\n\n\n- feat: export `EnhancedImgAttributes` type ([#15649](https://github.com/sveltejs/kit/pull/15649))\n\n\n### Patch Changes\n\n\n- fix: ex...","titleGenerated":null,"titleShort":null,"content":"### Minor Changes\n\n\n- feat: export `EnhancedImgAttributes` type ([#15649](https://github.com/sveltejs/kit/pull/15649))\n\n\n### Patch Changes\n\n\n- fix: exclude imports with `?` character from transformation ([#15617](https://github.com/sveltejs/kit/pull/15617))","publishedAt":"2026-06-18T18:36:59.000Z","url":"https://github.com/sveltejs/kit/releases/tag/%40sveltejs/enhanced-img%400.11.0","media":[],"prerelease":false,"source":{"slug":"kit","name":"kit","type":"github"},"org":{"slug":"svelte","name":"Svelte"},"product":{"slug":"sveltekit","name":"SvelteKit"},"groupSlug":"sveltekit","groupName":"SvelteKit","coverageCount":0,"composition":null},{"id":"rel_R2gOiAgW87RVMCjl1BHKK","version":"v20.3.0","type":"feature","title":"v20.3.0","summary":"v20.3.0\n\n### 🎉 New features\n\n- [eas-cli] Add `eas account:audit [ACCOUNT_NAME]` command to view an account's audit logs. ([#3863](https://github.com/...","titleGenerated":null,"titleShort":null,"content":"v20.3.0\n\n### 🎉 New features\n\n- [eas-cli] Add `eas account:audit [ACCOUNT_NAME]` command to view an account's audit logs. ([#3863](https://github.com/expo/eas-cli/pull/3863) by [@keith-kurak](https://github.com/keith-kurak))\n- [eas-cli] `eas update:view [GROUP_ID]` now also accepts a platform-specific update ID, resolving it to and displaying its update group. ([#3864](https://github.com/expo/eas-cli/pull/3864) by [@keith-kurak](https://github.com/keith-kurak))\n- [eas-cli] Add `eas integrations:posthog:connect` command. ([#3836](https://github.com/expo/eas-cli/pull/3836) by [@gwdp](https://github.com/gwdp))\n- [eas-cli] Add `eas integrations:posthog:dashboard` command. ([#3837](https://github.com/expo/eas-cli/pull/3837) by [@gwdp](https://github.com/gwdp))\n- [eas-cli] Add `eas integrations:posthog:disconnect` command. ([#3838](https://github.com/expo/eas-cli/pull/3838) by [@gwdp](https://github.com/gwdp))\n\n### 🐛 Bug fixes\n\n- [eas-cli] `eas integrations:posthog:connect` no longer aborts when `npx expo install` reports an error (for example, on a dynamic app config); it finishes writing the environment variables and prints any remaining manual steps. ([#3877](https://github.com/expo/eas-cli/pull/3877) by [@gwdp](https://github.com/gwdp))\n\n### 🧹 Chores\n\n- [eas-cli] Simplify 2FA now that SMS is no longer supported. ([#3859](https://github.com/expo/eas-cli/pull/3859) by [@wschurman](https://github.com/wschurman))\n","publishedAt":"2026-06-18T17:47:03.000Z","url":"https://github.com/expo/eas-cli/releases/tag/v20.3.0","media":[],"prerelease":false,"source":{"slug":"eas-cli","name":"EAS CLI","type":"github"},"org":{"slug":"expo","name":"Expo"},"product":null,"groupSlug":"eas-cli","groupName":"EAS CLI","coverageCount":0,"composition":null},{"id":"rel_tJWDEKQa20P6XlI5jMUUO","version":"7.0.1","type":"feature","title":"WordPress 7.0.1 Release Schedule","summary":"WordPress 7.0.1 will be a bug-fix-only maintenance release led by a team of four co-leads. The release is scheduled for July 9, 2026, preceded by bug scrubs and an RC1 on July 1.","titleGenerated":"WordPress 7.0.1 release schedule announced as a bug-fix-only maintenance release","titleShort":"Bug-fix maintenance release scheduled for July 9","content":"Since [WordPress 7.0 was released](https://wordpress.org/news/2026/05/armstrong/), contributors have kept a close eye on incoming reports to the WordPress.org Support Forums, Trac, and the Gutenberg repository on GitHub. The volume and severity of tickets mean that the maintenance release should be prepared phlegmatically.\n\nThis release will be co-led by [@cbravobernal](https://profiles.wordpress.org/cbravobernal/), [@estelaris](https://profiles.wordpress.org/estelaris/), [@masteradhoc](https://profiles.wordpress.org/masteradhoc/), and [@jorbin](https://profiles.wordpress.org/jorbin/).\n\n## Schedule\n\nDate/Time\n\nEvent\n\n[Thursday, June 18, 2026 at 15:00 UTC](https://www.timeanddate.com/worldclock/fixedtime.html?iso=20260618T1500)\n\nBug Scrub\n\n[Tuesday, June 23, 2026 at 15:00 UTC](https://www.timeanddate.com/worldclock/fixedtime.html?iso=20260623T1500)\n\nBug Scrub\n\n[Thursday, June 25, 2026 at 20:00 UTC](https://www.timeanddate.com/worldclock/fixedtime.html?iso=20260625T2000)\n\nBug Scrub. WordPress 7.0.2 Milestone will be opened, and some tickets may be punted.\n\n[Tuesday, June 30, 2026 at 10:00 UTC](https://www.timeanddate.com/worldclock/fixedtime.html?iso=20260630T1000)\n\nBug Scrub\n\nWednesday, July 1, 2026 at TBA UTC\n\nWordPress 7.0.1 RC1\n\n[Tuesday, July 7, 2026 at 15:00 UTC](https://www.timeanddate.com/worldclock/fixedtime.html?iso=20260707T1500)\n\nBug Scrub.\n\nThursday, July 9, 2026\n\nWordPress 6.9.1 General Release\n\nSpecific times for RC and General release will be announced in the [7.0 Release Leads](https://wordpress.slack.com/archives/C0A803Z8MA5) room and will be based on availability of individuals helping with the release.\n\n## Targeted Fixes\n\nWordPress 7.0.1 is intended as a bug-fix only maintenance release. Tickets will be included provided they are issues introduced during the 7.0 cycle or intentionally deferred at the end of the 7.0 cycle. You can follow [trac report 4](https://core.trac.wordpress.org/tickets/minor/workflow) or the [7.0.x editor tasks board](https://github.com/orgs/WordPress/projects/271) for proposed fixes.\n\nOne issues already has a [hotfix available in plugin form](https://make.wordpress.org/core/2026/05/28/hotfix-available-for-65286/) if you are facing them on your site.\n\n## Get Involved with 7.0.1\n\nBug Scrubs will happen in the [#core room](https://make.wordpress.org/chat/) during the times posted above. Each of the open tickets is going to require development work along with testing and review. You can also [run your own scrubs](https://make.wordpress.org/core/handbook/tutorials/leading-bug-scrubs/) to help ensure that all of the correct tickets are fixed in this release. Additionally, [some locales have strings in 7.0 in need of translation](https://translate.wordpress.org/stats/).\n\nGeneral coordination for the release will happen in the [#7-0-release-leads channel](https://wordpress.slack.com/archives/C0A803Z8MA5) and decisions around code for the release will be made in the [#core](https://make.wordpress.org/core/tag/core/) room.\n\n*Props to* [@cbravobernal](https://profiles.wordpress.org/cbravobernal/) [@masteradhoc](https://profiles.wordpress.org/masteradhoc/) [@estelaris](https://profiles.wordpress.org/estelaris/) *for assistance with this post and* [@jeffpaul](https://profiles.wordpress.org/jeffpaul/) [@annezazu](https://profiles.wordpress.org/annezazu/) [@4thhubbard](https://profiles.wordpress.org/4thhubbard/) for assistance in assembly the squad.\n\n[#7-0](https://make.wordpress.org/core/tag/7-0/), [#7-0-1](https://make.wordpress.org/core/tag/7-0-1/), [#7-0-x](https://make.wordpress.org/core/tag/7-0-x/), [#minor-releases](https://make.wordpress.org/core/tag/minor-releases/)","publishedAt":"2026-06-18T14:59:18.000Z","url":"https://make.wordpress.org/core/2026/06/18/wordpress-7-0-1-release-schedule/","media":[],"prerelease":false,"source":{"slug":"wordpress-core-dev-notes","name":"WordPress Core Dev Notes","type":"feed"},"org":{"slug":"wordpress","name":"WordPress"},"product":null,"groupSlug":"wordpress-core-dev-notes","groupName":"WordPress Core Dev Notes","coverageCount":0,"composition":null},{"id":"rel_e3FwEDrVwM4-HZog1v8x1","version":null,"type":"feature","title":"Recap: Restoring removed version history.","summary":"WordPress restored version history for PHP files shared between the Gutenberg repository and wordpress-develop, after a build-script change in the 7.0 cycle removed them from version control and caused integration failures, lost minification, bisect delays, and abandoned files persisting in beta/RC releases. The fix uses a merge branch to reconnect history at each Gutenberg sync commit.","titleGenerated":"WordPress restores removed version history for shared Gutenberg-develop files","titleShort":"Shared file version history restored after build change disruption","content":"Since the block editor was first merged into `wordpress/wordpress-develop` (leading up to the WordPress 5.0 release), there has always been a considerable amount of manual work required to sync the necessary changes in the `gutenberg` GitHub repository into SVN. During the early phases of the 7.0 release cycle, [#64393](https://core.trac.wordpress.org/ticket/64393) worked on making changes to the `wordpress-develop` build scripts with the goal of simplifying this process.\n\nWhile the initial iteration of these changes committed in [\\[61438\\]](https://core.trac.wordpress.org/changeset/61438) removed some of that manual friction, specific parts of the change disrupted a few important contributor workflows due to the way that PHP files were removed from version control and added to the `.gitignore` file. These particular PHP files were shared in both repositories, and the idea of removing them was to ensure that the source of truth remains clearly in the Gutenberg repository. Instead of existing in both repositories, a script would create the files in the working copy of the `wordpress/wordpress-develop` repo.\n\n### What went wrong?\n\nUnfortunately, there were a number of unanticipated side-effects of this change:\n\n- A number of existing integrations started failing where the build script was not run due to the fact that WordPress calls `require` directly on these files to load them. This included [the distributed hosting tests](https://make.wordpress.org/hosting/test-results/).\n- Several files that were previously minified by the build script no longer were (see [#65007](https://core.trac.wordpress.org/ticket/65007), [#64909](https://core.trac.wordpress.org/ticket/64909))\n- While the source of truth of these files lives in Gutenberg, it’s valuable to know when the updates were brought into Core and what those updates were. Development in the Gutenberg plugin runs at a different pace than in Core, which means that diagnosing changes to these files from the Gutenberg side is considerably more difficult and time-consuming than when there are changes in version control, which provide pins for when defects are introduced or resolved.\n- Technically, there was a dual source of truth for these files before the change. The ultimate copies which made it into a WordPress release were those which had been committed into SVN, while the Gutenberg plugin might ship changed or updated files. After the change, that “ultimate” copy no longer existed in SVN, except in the final release bundles. The “source of truth” for the files in both contexts (WordPress and the Gutenberg plugin) lived solely in Gutenberg, but might actually be different from each other due to the new commit hash pinning in `wordpress-develop`.\n- Because these files were removed and the change added this new requirement to run the build step, major delays were introduced to any workflow which steps through commits. Even after a series of optimizations, this added over nine hours of runtime just to walk the 800+ commits from 6.8.5 to 6.9.0.\n- Version history for these files was severed in the change, making it suddenly look like the files were never part of the repository. Any attempts to review the history required custom `git` commands not usually available in IDEs or GitHub’s UI.\n- Files that were removed from version control were abandoned on the build server, which did not clean up properly. This resulted in removed files persisting and being included unintentionally in the beta and RC versions (see [#64716](https://core.trac.wordpress.org/ticket/64716) and [#65418](https://core.trac.wordpress.org/ticket/65418)).\n- While it happens from time to time that someone accidentally updates the code in one of these files in the Core repository instead of in Gutenberg where it should be done, the `.gitignore` directives *hide* any of those accidental changes, frustrating an already confusing situation. All `git`\\-based tooling (IDEs, `git`, `git` GUIs, linters, etc…) is unable to see or revert changes to these files, giving a false sense of safety when someone checks in code that will unexpectedly fail once running on a different computer.\n\n### What was resolved?\n\nTwo fundamental problems needed to be resolved:\n\n- Files that are required by WordPress’ boot sequence needed to be restored.\n- The version history continuity for these files would ideally need to restored.\n\nOn one hand, reverting the original change would have been an easy way to restore the missing files. But doing so would make it appear as though the revert commit was introducing *brand new files with the same name as the ones which had been deleted*, rather than restoring the deleted files. The history before January 5 would have remained lost. A revert or a new commit which copies the files back remained an easy option, but something else was worth pursuing: restore the files with their history.\n\n[![](https://make.wordpress.org/core/files/2026/04/restore-branch.drawio-4.png)](https://make.wordpress.org/core/files/2026/04/restore-branch.drawio-4.png)\n\nThe chosen resolution was to create a branch of the code from the revision just before [\\[61438\\]](https://core.trac.wordpress.org/changeset/61438), restore all of the files which were removed, and then perform a *merge* of the branch back into `trunk` to reconnect the version history. Until this point, creating branches was normal in the WordPress codebase for each release, but none had been reintegrated into `trunk` through a merge.\n\nThe merge commit provided an opportunity to restore the file contents *and* connect them to their history. While the original plan was to create a branch with a single commit (the merge commit itself) [@desrosj](https://profiles.wordpress.org/desrosj/) had the suggestion that it would be valuable if the intervening history of changes could also be represented. In other words, to create the restore branch as an effective revert of *the decision* to remove all these files, not just the file objects themselves.\n\nThe result is that the restore branch contains a sequence of commits, where each is associated with a Gutenberg-sync commit in the upstream `trunk` branch. These commits modify the deleted files and introduce new files that *would have been* added had it not been for the `.gitignore` and `svn:ignore` changes. This is tantamount to checking out `trunk` at each Gutenberg sync commit, reverting the `.gitignore` changes, running `npm run build:dev`, and then adding the no-longer-ignored files (but the details are more complicated than this).\n\nAfter the final merge, it’s now possible to examine one of the affected files and immediately know at which Gutenberg sync commit it changed and how. Supposing someone discovered that an issue appeared within the first quarter of 2026, this additional granularity might save the need to scan through hundreds of commits when debugging.\n\n### What was the process for the resolution?\n\nThe original change itself serves as a cautionary guide on how far-reaching the effects can be for fundamental changes to WordPress’ development infrastructure. Because no restoration-merge had ever occurred, it was worth performing full diligence to prevent similar blowback while trying to fix the repository.\n\nThe approach was discussed early on and remained open for a long time to allow for rarer implications to surface — many did. The topic was brought up in [Trac](https://core.trac.wordpress.org/ticket/64393), in the [#core](https://wordpress.slack.com/archives/C02RQBWTW) channel in Slack, and during [weekly Developer Chats in #core](https://wordpress.slack.com/archives/C02RQBWTW/p1771429921631709). The solution was brought to the attention of the systems team for their input, and as much as was possible, the restore was simulated at every stage to catch any failures which could be reasonably anticipated – many were.\n\n`git` is a more powerful companion in situations like this than `svn` is, but ultimately all of WordPress’ code must begin its life in `svn`. Therefore, a script was created to prototype a resolution in `git` to produce the desired outcome in a way that could be tested in local checkouts as well as run the test suite. The goalpost for this test branch was that, if done correctly, in the merge with `trunk` inside of its PR, there would be no follow-up commits from the bot that runs the build command (because no files would be changed through the build). The simulation script made it easy to adjust strategies and add missing steps once certain problems surfaced. One such problem was that some files didn’t make it at the right time into one of the `grunt` lists when it should have; this could have involved a lot of manual work, but it didn’t because of the script. The script still involved a lot of effort, but as many times as it ran, rebuilding the branch within a few minutes, it was clear that it was paying off.\n\nOnce the `git` branch was ready it was time to ensure that the steps in `svn` would actually produce that desired outcome once synchronized. For this, [@abbe](https://profiles.wordpress.org/abbe/) provided a test copy of the `develop.wordpress.org` Subversion repo that could be used to verify the flow. A second script stepped through each commit from the `git` branch and created mirrored commits on the `svn` side, then performed a merge into the test repo’s `trunk` branch. The goalpost for this side was that the end result matched identically to the final exploratory `git` branch. In the end, it took fifteen full iterations of the simulated branch creation to get the expected result. Imagine finding out all of the little nuances only *after* deploying to production!\n\nWith all of the details then ready, it was go-time and time to deploy for real. Sadly, not all aspects of the flow were testable beforehand, and problems did arise which stalled the restoration. The “build” server2 got stuck while processing commits due to a fatal Grunt error and [@aidvu](https://profiles.wordpress.org/aidvu/) had to step in and manually clear up the issues on that server. However, while delayed, all it took to reach the successful end was running the script once more. Thankfully, after preparing each commit and before pushing them, a pause step was built-in for manual review before *committing* to the commit, and this allowed coordination with systems (it’s ideal to build natural throttles in to automation to avoid *billions of errors per second*).\n\n### What is important to understand about this merge?\n\nWhen working with merged branches, `git` automatically represents commits from all of the branches in history, but `svn` doesn’t. This means that `git`\\-based workflows should be working without any trouble. But for those working in `svn`, a basic `svn log` will not show the corresponding sync-commits from the branch. One has to run `svn -g log` to see them. Any `svn`\\-based tooling will therefore hide the commits by default.\n\nThere is one solvable nuance that was cut from scope for this resolution: commit authors and timestamps. While it was demonstrated to be technically possible to match the sync commits with their associated commits in the upstream `trunk` branch, this would have required rewriting metadata in `svn` *after* making the commits, and there was no certainty that this wouldn’t interrupt the `git-svn` sync. Therefore, while each sync-commit matches another commit from January 5 through March 26, each of the restore-branch sync-commits appears in a bunch on March 26. This is a minor issue; regrettable but acceptable given the sensitivity of the work done to bring the repository back into a proper state.\n\n### What still remains to be done?\n\nA few issues arose during the restoration, some of which highlighted pre-existing problems.\n\n- The `git` and subversion “ignores” lists are incompatible and out of sync. These need to be harmonized and it would be ideal to have an automated process flag discrepancies before they are committed ([#64971](https://core.trac.wordpress.org/ticket/64971)).\n- A number of files have been deleted from the `git` repository over time which were never removed from the subversion side. This leaves stale files in `svn` and on the build server. These need to be identified, removed, and added to the `$_old_files` array in `wp-admin/includes/update-core.php` (see [#65418](https://core.trac.wordpress.org/ticket/65418)). Automated detection would be helpful here as well (see [#64878](https://core.trac.wordpress.org/ticket/64878)).\n- The continued discrepancy between WordPress Coding Standards preferences between the Gutenberg and Core repositories remains an obstacle to harmony between the projects. Rulesets should be normalized or removed from the repositories so that accepted changes don’t suddenly reject PRs when synchronizing. This issue also recently came up when restoring the WordPress documentation, as PHP code which was accepted in Gutenberg broke the docs’ generation process once built in Core. This was due to the use of syntax forms which were already known to break tooling and integrations.\n- Functions and hooks maintained upstream in the `gutenberg` repository that are built from the new template files in the `wp-build` package lack proper PHP Docblock comments. Mainly, action and filter hooks had incorrectly formatted Docblocks (fixed in [Gutenberg-78826](https://github.com/WordPress/gutenberg/pull/78826)), and missing `@since` tags (see [Gutenberg-76727](https://github.com/WordPress/gutenberg/issues/76727)).\n\nA few other unrelated issues persist as a result of the build change.\n\n- The workflow for developing simultaneously with the Core and Gutenberg repositories needs to be restored, as the traditional approach of mounting the Gutenberg plugin into the `wp-content/plugins/` directory was severed in the change.\n\n### Thanks you!\n\nA heartfelt “thank you” goes out to everyone who helped with overhauling the build script to reduce friction between the two code bases, and/or this effort to restore file history:\n\n[@4thhubbard](https://profiles.wordpress.org/4thhubbard/), [@762e5e74](https://profiles.wordpress.org/762e5e74/), [@adamsilverstein](https://profiles.wordpress.org/adamsilverstein/), [@aidvu](https://profiles.wordpress.org/aidvu/), [@amykamala](https://profiles.wordpress.org/amykamala/), [@bernhard-reiter](https://profiles.wordpress.org/bernhard-reiter/), [@dd32](https://profiles.wordpress.org/dd32/), [@desrosj](https://profiles.wordpress.org/desrosj/), [@dmsnell](https://profiles.wordpress.org/dmsnell/), [@ellatrix](https://profiles.wordpress.org/ellatrix/), [@gaisma22](https://profiles.wordpress.org/gaisma22/), [@isabel\\_brison](https://profiles.wordpress.org/isabel_brison/), [@johnbillion](https://profiles.wordpress.org/johnbillion/), [@jonsurrell](https://profiles.wordpress.org/jonsurrell/), [@jorbin](https://profiles.wordpress.org/jorbin/), [@jorgefilipecosta](https://profiles.wordpress.org/jorgefilipecosta/), [@jsnajdr](https://profiles.wordpress.org/jsnajdr/), [@jtquip88](https://profiles.wordpress.org/jtquip88/), [@mamaduka](https://profiles.wordpress.org/mamaduka/), [@manhar](https://profiles.wordpress.org/manhar/), [@manzoorwanijk](https://profiles.wordpress.org/manzoorwanijk/), [@mcsf](https://profiles.wordpress.org/mcsf/), [@mywp459](https://profiles.wordpress.org/mywp459/), [@ntsekouras](https://profiles.wordpress.org/ntsekouras/), [@peterwilsoncc](https://profiles.wordpress.org/peterwilsoncc/), [@sabernhardt](https://profiles.wordpress.org/sabernhardt/), [@SirLouen](https://profiles.wordpress.org/sirlouen/), [@swissspidy](https://profiles.wordpress.org/swissspidy/), [@tobiasbg](https://profiles.wordpress.org/tobiasbg/), [@tyxla](https://profiles.wordpress.org/tyxla/), [@westonruter](https://profiles.wordpress.org/westonruter/), [@wildworks](https://profiles.wordpress.org/wildworks/), and [@youknowriad](https://profiles.wordpress.org/youknowriad/).\n\n### Timeline\n\n- January 5 — The change was committed.\n- January 6 — The first set of problems was reported.\n- February 23 — An initial `git` branch was proposed which restored the files in their final state.\n- March 6 — The restore branch was created in Subversion, and successfully synchronized to `git`.\n- March 18 — An expanded `git` branch contained a commit for every associated Gutenberg sync commit in Core.\n- March 24 — Systems provided a test `svn` repository from a backup of `develop.svn.wordpress.org` where a final merge could be tested before being applied to the production repository.\n- March 26 — The branch was merged into Core, restoring the files and their change history.\n\n---\n\n*Props to [@amykamala](https://profiles.wordpress.org/amykamala/) and [@desrosj](https://profiles.wordpress.org/desrosj/) who reviewed this post before publishing.*\n\n1. The wordpress.org build server checks out each commit to the `wordpress-develop` SVN repository, runs `npm install`, `npm run build`, and then commits any changes to the `build` directory to the [core.svn.wordpress.org repository](https://core.svn.wordpress.org/). All release packages are created from this repository. ![↩](https://s.w.org/images/core/emoji/17.0.2/72x72/21a9.png)︎\n\n[#build-test-tools](https://make.wordpress.org/core/tag/build-test-tools/), [#git](https://make.wordpress.org/core/tag/git/), [#post-mortem](https://make.wordpress.org/core/tag/post-mortem/), [#svn](https://make.wordpress.org/core/tag/svn/)","publishedAt":"2026-06-17T18:53:06.000Z","url":"https://make.wordpress.org/core/2026/06/17/recap-restoring-removed-version-history/","media":[{"type":"image","url":"https://make.wordpress.org/core/files/2026/04/restore-branch.drawio-4.png","r2Key":"releases/1d01eb8bdd45a82380ce3c97af0198486209584deebdd43a81dd8ea9afb8613e.png","r2Url":"https://media.releases.sh/releases/1d01eb8bdd45a82380ce3c97af0198486209584deebdd43a81dd8ea9afb8613e.png"},{"type":"image","url":"https://s.w.org/images/core/emoji/17.0.2/72x72/21a9.png","alt":"↩"}],"prerelease":false,"source":{"slug":"wordpress-core-dev-notes","name":"WordPress Core Dev Notes","type":"feed"},"org":{"slug":"wordpress","name":"WordPress"},"product":null,"groupSlug":"wordpress-core-dev-notes","groupName":"WordPress Core Dev Notes","coverageCount":0,"composition":null},{"id":"rel_SFORmGTNl2avUu3Zos_8s","version":"7.1","type":"feature","title":"Announcing the WordPress 7.1 Release Squad","summary":"WordPress 7.1 release squad assembled with Anne McCarthy as release lead. Smaller, focused team structure continues from 6.7—7.0 cycles, with greater emphasis on Make Team Rep coordination.","titleGenerated":"WordPress 7.1 Release Squad announced","titleShort":"Release squad assembled for 7.1","content":"This post is announcing the formation of the 7.1 release squad after a [call for volunteers](https://make.wordpress.org/core/2026/05/21/wordpress-7-1-call-for-volunteers/).\n\n**Exciting News: The** [**WordPress 7.1**](https://make.wordpress.org/core/7-1/) **Release Squad is assembled!**\n\n- Release Lead: [Anne McCarthy](https://profiles.wordpress.org/annezazu/)\n- Release Coordination: [Benjamin Zekavica](https://profiles.wordpress.org/benjamin_zekavica/), [Krupa Nanda](https://profiles.wordpress.org/krupajnanda/)\n- Tech Leads: [Aki Hamano](https://profiles.wordpress.org/wildworks/), [Joe Dolson](https://profiles.wordpress.org/joedolson/)\n- Triage Leads: [Adrian Duffell](https://profiles.wordpress.org/adrianduffell/), [Sajjad Hossain Sagor](https://profiles.wordpress.org/sajjad67/), [Sergey Biryukov](https://profiles.wordpress.org/sergeybiryukov/)\n- Test Leads: [Huzaifa Al Mesbah](https://profiles.wordpress.org/huzaifaalmesbah/), [Nikunj Hatkar](https://profiles.wordpress.org/nikunj8866/)\n\nAs with the [6.7](https://make.wordpress.org/core/2024/07/05/wordpress-6-7-planning-proposal-call-for-volunteers/), [6.8](https://make.wordpress.org/core/2024/11/21/wordpress-6-8-call-for-volunteers/), [6.9](https://make.wordpress.org/core/2025/07/11/wordpress-6-9-planning-proposal-and-call-for-volunteers/), and [7.0](https://make.wordpress.org/core/2026/01/09/wordpress-7-0-call-for-volunteers/) release cycles, WordPress 7.1 will continue the approach of forming a smaller, focused Release Squad.  This streamlined structure places more emphasis on collaboration with the various [Make Team Reps](https://make.wordpress.org/updates/team-reps/), who are encouraged to help coordinate efforts from within their [respective teams](https://make.wordpress.org/).  The goals are to reduce the overhead on the Release Squad while still ensuring each Make Team’s contributions and priorities are represented throughout the cycle, and to reduce overlap between a Make Team Rep and that team’s Release Squad Leads.  Noteworthy Contributors will be captured from Team Reps towards the end of the release cycle.\n\nThe number of volunteers far exceeded the available squad roles, so we selected folks whose experience and focus best aligned with the needs of the 7.1 release.  If you weren’t selected this time, your contributions are still incredibly valuable, and there are plenty of ways to stay involved throughout the release cycle, including testing, bug scrubs, triage, documentation, and more.  Every contribution helps move WordPress forward, and we’re grateful for your continued participation.\n\nBig thanks to everyone who volunteered for the release squad, and heartfelt appreciation to everyone helping move WordPress 7.1 forward through testing, triage, documentation, bug scrubs, and more.  Your efforts make this release possible, and there’s a lot to be excited about as WordPress 7.1 comes together!\n\n*Props to [@tyxla](https://profiles.wordpress.org/tyxla/), [@annezazu](https://profiles.wordpress.org/annezazu/), [@jorbin](https://profiles.wordpress.org/jorbin/) for reviewing this post and [@jorbin](https://profiles.wordpress.org/jorbin/), [@desrosj](https://profiles.wordpress.org/desrosj/), [@annezazu](https://profiles.wordpress.org/annezazu/), [@tyxla](https://profiles.wordpress.org/tyxla/), and [@4thhubbard](https://profiles.wordpress.org/4thhubbard/) for helping assemble the 7.1 release squad.*\n\n[#7-1](https://make.wordpress.org/core/tag/7-1/), [#planning](https://make.wordpress.org/core/tag/planning/)","publishedAt":"2026-06-17T15:03:18.000Z","url":"https://make.wordpress.org/core/2026/06/17/announcing-the-wordpress-7-1-release-squad/","media":[],"prerelease":false,"source":{"slug":"wordpress-core-dev-notes","name":"WordPress Core Dev Notes","type":"feed"},"org":{"slug":"wordpress","name":"WordPress"},"product":null,"groupSlug":"wordpress-core-dev-notes","groupName":"WordPress Core Dev Notes","coverageCount":0,"composition":null}],"pagination":{"nextCursor":"2026-06-17T15:03:18.000Z|2026-06-17T19:03:19.250Z|rel_SFORmGTNl2avUu3Zos_8s","limit":20}}