diff --git a/.changeset/afraid-experts-explain.md b/.changeset/afraid-experts-explain.md
new file mode 100644
index 0000000000..38eb3709d0
--- /dev/null
+++ b/.changeset/afraid-experts-explain.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli-node': patch
+---
+
+Added `type` field to `BackstagePackageJson` type.
diff --git a/.changeset/beige-dingos-destroy.md b/.changeset/beige-dingos-destroy.md
new file mode 100644
index 0000000000..325c150119
--- /dev/null
+++ b/.changeset/beige-dingos-destroy.md
@@ -0,0 +1,18 @@
+---
+'@backstage/cli': minor
+---
+
+**BREAKING**: Add support for native ESM in Node.js code. This changes the behavior of dynamic import expressions in Node.js code. Typically this can be fixed by replacing `import(...)` with `require(...)`, with an `as typeof import(...)` cast if needed for types. This is because dynamic imports will no longer be transformed to `require(...)` calls, but instead be left as-is. This in turn allows you to load ESM modules from CommonJS code using `import(...)`.
+
+This change adds support for the following in Node.js packages, across type checking, package builds, runtime transforms and Jest tests:
+
+- Dynamic imports that load ESM modules from CommonJS code.
+- Both `.mjs` and `.mts` files as explicit ESM files, as well as `.cjs` and `.cts` as explicit CommonJS files.
+- Support for the `"type": "module"` field in `package.json` to indicate that the package is an ESM package.
+
+There are a few caveats to be aware of:
+
+- To enable support for native ESM in tests, you need to run the tests with the `--experimental-vm-modules` flag enabled, typically via `NODE_OPTIONS='--experimental-vm-modules'`.
+- Declaring a package as `"type": "module"` in `package.json` is supported, but in tests it will cause all local transitive dependencies to also be treated as ESM, regardless of whether they declare `"type": "module"` or not.
+- Node.js has an [ESM interoperability layer with CommonJS](https://nodejs.org/docs/latest-v22.x/api/esm.html#interoperability-with-commonjs) that allows for imports from ESM to identify named exports in CommonJS packages. This interoperability layer is **only** enabled when importing packages with a `.cts` or `.cjs` extension. This is because the interoperability layer is not fully compatible with the NPM ecosystem, and would break package if it was enabled for `.js` files.
+- Dynamic imports of CommonJS packages will vary in shape depending on the runtime, i.e. test vs local development, etc. It is therefore recommended to avoid dynamic imports of CommonJS packages and instead use `require`, or to use the explicit CommonJS extensions as mentioned above. If you do need to dynamically import CommonJS packages, avoid using `default` exports, as the shape of them vary across different environments and you would otherwise need to manually unwrap the import based on the shape of the module object.
diff --git a/.changeset/clean-squids-build.md b/.changeset/clean-squids-build.md
new file mode 100644
index 0000000000..3c1e0b56a7
--- /dev/null
+++ b/.changeset/clean-squids-build.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-notifications-backend': patch
+'@backstage/plugin-notifications': patch
+---
+
+added topic filter for notifications
diff --git a/.changeset/curly-humans-prove.md b/.changeset/curly-humans-prove.md
new file mode 100644
index 0000000000..4e0ca9c90e
--- /dev/null
+++ b/.changeset/curly-humans-prove.md
@@ -0,0 +1,7 @@
+---
+'@backstage/backend-test-utils': patch
+'@backstage/backend-defaults': patch
+'@backstage/config-loader': patch
+---
+
+Internal refactor to use explicit `require` for lazy-loading dependency.
diff --git a/.changeset/dry-horses-report.md b/.changeset/dry-horses-report.md
new file mode 100644
index 0000000000..b7a0b4cd46
--- /dev/null
+++ b/.changeset/dry-horses-report.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-test-utils': patch
+---
+
+Sync feature installation compatibility logic with `@backstage/backend-app-api`.
diff --git a/.changeset/fair-mangos-sleep.md b/.changeset/fair-mangos-sleep.md
new file mode 100644
index 0000000000..8f0a6371c3
--- /dev/null
+++ b/.changeset/fair-mangos-sleep.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend': patch
+---
+
+Cleanup `refresh_state_references` for entity processors and providers that are no longer in control of a `refresh_state` row for entity
diff --git a/.changeset/quiet-phones-sell.md b/.changeset/quiet-phones-sell.md
new file mode 100644
index 0000000000..f41f5d685e
--- /dev/null
+++ b/.changeset/quiet-phones-sell.md
@@ -0,0 +1,5 @@
+---
+'@backstage/repo-tools': patch
+---
+
+Internal refactor to support native ESM.
diff --git a/.changeset/sharp-years-drive.md b/.changeset/sharp-years-drive.md
new file mode 100644
index 0000000000..92ade2b972
--- /dev/null
+++ b/.changeset/sharp-years-drive.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-search-backend-module-catalog': patch
+---
+
+Modified the logic for generating the location URL by encoding the entity property values with `encodeURIComponent`. This enhancement improves the safety and reliability of the URL.
diff --git a/.changeset/twelve-eyes-stare.md b/.changeset/twelve-eyes-stare.md
new file mode 100644
index 0000000000..bd2db50c9b
--- /dev/null
+++ b/.changeset/twelve-eyes-stare.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-dynamic-feature-service': patch
+---
+
+Make sure changes are successfully tracked before starting up scanner.
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 951900dd49..bcf5ed94a0 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -202,7 +202,7 @@ jobs:
env:
CI: true
- NODE_OPTIONS: --max-old-space-size=8192 --no-node-snapshot
+ NODE_OPTIONS: --max-old-space-size=8192 --no-node-snapshot --experimental-vm-modules
INTEGRATION_TEST_GITHUB_TOKEN: ${{ secrets.INTEGRATION_TEST_GITHUB_TOKEN }}
INTEGRATION_TEST_GITLAB_TOKEN: ${{ secrets.INTEGRATION_TEST_GITLAB_TOKEN }}
INTEGRATION_TEST_BITBUCKET_TOKEN: ${{ secrets.INTEGRATION_TEST_BITBUCKET_TOKEN }}
diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml
index 01160254f4..1eee6e61f3 100644
--- a/.github/workflows/verify_windows.yml
+++ b/.github/workflows/verify_windows.yml
@@ -21,7 +21,7 @@ jobs:
env:
CI: true
- NODE_OPTIONS: --max-old-space-size=8192 --no-node-snapshot
+ NODE_OPTIONS: --max-old-space-size=8192 --no-node-snapshot --experimental-vm-modules
INTEGRATION_TEST_GITHUB_TOKEN: ${{ secrets.INTEGRATION_TEST_GITHUB_TOKEN }}
INTEGRATION_TEST_GITLAB_TOKEN: ${{ secrets.INTEGRATION_TEST_GITLAB_TOKEN }}
INTEGRATION_TEST_BITBUCKET_TOKEN: ${{ secrets.INTEGRATION_TEST_BITBUCKET_TOKEN }}
diff --git a/canon-docs/package.json b/canon-docs/package.json
index 824a645f99..9fddf08c20 100644
--- a/canon-docs/package.json
+++ b/canon-docs/package.json
@@ -9,11 +9,15 @@
"watch-css": "node scripts/watch-css.js"
},
"dependencies": {
+ "@codemirror/lang-sass": "^6.0.2",
+ "@lezer/highlight": "^1.2.1",
"@mdx-js/loader": "^3.1.0",
"@mdx-js/react": "^3.1.0",
"@next/mdx": "^15.1.4",
"@storybook/react": "^8.4.7",
"@types/mdx": "^2.0.13",
+ "@uiw/codemirror-themes": "^4.23.7",
+ "@uiw/react-codemirror": "^4.23.7",
"next": "14.2.23",
"react": "^18",
"react-dom": "^18",
diff --git a/canon-docs/src/app/globals.css b/canon-docs/src/app/globals.css
index 4b39735a22..5efc0407e7 100644
--- a/canon-docs/src/app/globals.css
+++ b/canon-docs/src/app/globals.css
@@ -35,3 +35,37 @@ iframe {
font-weight: var(--shiki-dark-font-weight) !important;
text-decoration: var(--shiki-dark-text-decoration) !important;
}
+
+.cm-editor {
+ transition: background-color 0.2s ease-in-out;
+}
+
+.ͼ2 .cm-gutters {
+ background-color: var(--canon-surface-2);
+ border-right: 1px solid var(--canon-border-base);
+ transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out;
+}
+
+.ͼ1 .cm-lineNumbers .cm-gutterElement {
+ padding-right: 8px;
+ padding-left: 8px;
+ font-size: 0.875rem;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ min-width: 34px;
+}
+
+.cm-line {
+ font-size: 0.875rem;
+}
+
+.ͼ1 .cm-line {
+ padding-left: 12px;
+ padding-top: 1px;
+ padding-bottom: 1px;
+}
+
+.cm-focused {
+ outline: none !important;
+}
diff --git a/canon-docs/src/app/layout.tsx b/canon-docs/src/app/layout.tsx
index 6eb1856a1d..99b5f22739 100644
--- a/canon-docs/src/app/layout.tsx
+++ b/canon-docs/src/app/layout.tsx
@@ -2,7 +2,7 @@ import type { Metadata } from 'next';
import { Sidebar } from '../components/Sidebar';
import { Toolbar } from '@/components/Toolbar';
import { Providers } from './providers';
-
+import { CustomTheme } from '@/components/CustomTheme';
import styles from './page.module.css';
import './globals.css';
@@ -13,6 +13,7 @@ import '/public/backstage.css';
export const metadata: Metadata = {
title: 'Canon',
description: 'UI library for Backstage',
+ metadataBase: new URL('https://canon.backstage.io'),
};
export default function RootLayout({
@@ -35,6 +36,7 @@ export default function RootLayout({
{children}
+