diff --git a/CHANGELOG.md b/CHANGELOG.md
index dd75af133731..f3e13bedee71 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 8.3.5
+
+- CLI: Update the React Native init to include v8 dependencies - [#29273](https://github.com/storybookjs/storybook/pull/29273), thanks @dannyhw!
+- Vitest plugin: Fix renamed export stories - [#29250](https://github.com/storybookjs/storybook/pull/29250), thanks @shilman!
+
 ## 8.3.4
 
 - Addon Test: Support story name as test description - [#29147](https://github.com/storybookjs/storybook/pull/29147), thanks @InfiniteXyy!
diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md
index 40c0aa95376f..8c9a74c850e4 100644
--- a/CHANGELOG.prerelease.md
+++ b/CHANGELOG.prerelease.md
@@ -1,3 +1,8 @@
+## 8.4.0-alpha.5
+
+- Core: Migrate from `express` to `polka` - [#29230](https://github.com/storybookjs/storybook/pull/29230), thanks @43081j!
+- Core: Remove dependence on `file-system-cache` - [#29256](https://github.com/storybookjs/storybook/pull/29256), thanks @ndelangen!
+
 ## 8.4.0-alpha.4
 
 - Blocks: Prebundle `es-toolkit` - [#29259](https://github.com/storybookjs/storybook/pull/29259), thanks @JReinhold!
diff --git a/code/__mocks__/fs.ts b/code/__mocks__/fs.ts
index 50e34e8e4ca1..f617d31141f6 100644
--- a/code/__mocks__/fs.ts
+++ b/code/__mocks__/fs.ts
@@ -19,6 +19,7 @@ export const realpathSync = vi.fn();
 export const readdir = vi.fn();
 export const readdirSync = vi.fn();
 export const readlinkSync = vi.fn();
+export const mkdirSync = vi.fn();
 
 export default {
   __setMockFiles,
@@ -29,4 +30,5 @@ export default {
   readdir,
   readdirSync,
   readlinkSync,
+  mkdirSync,
 };
diff --git a/code/builders/builder-vite/package.json b/code/builders/builder-vite/package.json
index b9bff0b1c02a..dc7e9dd9c6b7 100644
--- a/code/builders/builder-vite/package.json
+++ b/code/builders/builder-vite/package.json
@@ -47,15 +47,15 @@
     "@types/find-cache-dir": "^3.2.1",
     "browser-assert": "^1.2.1",
     "es-module-lexer": "^1.5.0",
-    "express": "^4.19.2",
     "find-cache-dir": "^3.0.0",
     "magic-string": "^0.30.0",
     "ts-dedent": "^2.0.0"
   },
   "devDependencies": {
-    "@types/express": "^4.17.21",
     "@types/node": "^22.0.0",
     "glob": "^10.0.0",
+    "polka": "^1.0.0-next.28",
+    "sirv": "^2.0.4",
     "slash": "^5.0.0",
     "typescript": "^5.3.2",
     "vite": "^4.0.4"
diff --git a/code/builders/builder-vite/src/index.ts b/code/builders/builder-vite/src/index.ts
index 0962e1676e4e..9ab66f2771d0 100644
--- a/code/builders/builder-vite/src/index.ts
+++ b/code/builders/builder-vite/src/index.ts
@@ -3,10 +3,9 @@ import { cp, readFile } from 'node:fs/promises';
 import { join, parse } from 'node:path';
 
 import { NoStatsForViteDevError } from 'storybook/internal/server-errors';
-import type { Options } from 'storybook/internal/types';
+import type { Middleware, Options } from 'storybook/internal/types';
 
-import type { RequestHandler } from 'express';
-import express from 'express';
+import sirv from 'sirv';
 import { corePath } from 'storybook/core-path';
 import type { ViteDevServer } from 'vite';
 
@@ -20,16 +19,18 @@ export { hasVitePlugins } from './utils/has-vite-plugins';
 
 export * from './types';
 
-function iframeMiddleware(options: Options, server: ViteDevServer): RequestHandler {
+function iframeMiddleware(options: Options, server: ViteDevServer): Middleware {
   return async (req, res, next) => {
-    if (!req.url.match(/^\/iframe\.html($|\?)/)) {
+    if (!req.url || !req.url.match(/^\/iframe\.html($|\?)/)) {
       next();
       return;
     }
+    // the base isn't used for anything, but it's required by the URL constructor
+    const url = new URL(req.url, 'http://localhost:6006');
 
     // We need to handle `html-proxy` params for style tag HMR https://github.com/storybookjs/builder-vite/issues/266#issuecomment-1055677865
     // e.g. /iframe.html?html-proxy&index=0.css
-    if (req.query['html-proxy'] !== undefined) {
+    if (url.searchParams.has('html-proxy')) {
       next();
       return;
     }
@@ -40,7 +41,9 @@ function iframeMiddleware(options: Options, server: ViteDevServer): RequestHandl
     const generated = await transformIframeHtml(indexHtml, options);
     const transformed = await server.transformIndexHtml('/iframe.html', generated);
     res.setHeader('Content-Type', 'text/html');
-    res.status(200).send(transformed);
+    res.statusCode = 200;
+    res.write(transformed);
+    res.end();
   };
 }
 
@@ -59,10 +62,14 @@ export const start: ViteBuilder['start'] = async ({
   server = await createViteServer(options as Options, devServer);
 
   const previewResolvedDir = join(corePath, 'dist/preview');
-  const previewDirOrigin = previewResolvedDir;
-
-  router.use(`/sb-preview`, express.static(previewDirOrigin, { immutable: true, maxAge: '5m' }));
-
+  router.use(
+    '/sb-preview',
+    sirv(previewResolvedDir, {
+      maxAge: 300000,
+      dev: true,
+      immutable: true,
+    })
+  );
   router.use(iframeMiddleware(options as Options, server));
   router.use(server.middlewares);
 
@@ -81,10 +88,8 @@ export const build: ViteBuilder['build'] = async ({ options }) => {
   const viteCompilation = viteBuild(options as Options);
 
   const previewResolvedDir = join(corePath, 'dist/preview');
-  const previewDirOrigin = previewResolvedDir;
   const previewDirTarget = join(options.outputDir || '', `sb-preview`);
-
-  const previewFiles = cp(previewDirOrigin, previewDirTarget, {
+  const previewFiles = cp(previewResolvedDir, previewDirTarget, {
     filter: (src) => {
       const { ext } = parse(src);
       if (ext) {
diff --git a/code/builders/builder-vite/src/list-stories.ts b/code/builders/builder-vite/src/list-stories.ts
index 5eefb9b8fb74..d5b417f2553c 100644
--- a/code/builders/builder-vite/src/list-stories.ts
+++ b/code/builders/builder-vite/src/list-stories.ts
@@ -3,6 +3,7 @@ import { isAbsolute, join } from 'node:path';
 import { commonGlobOptions, normalizeStories } from 'storybook/internal/common';
 import type { Options } from 'storybook/internal/types';
 
+// eslint-disable-next-line depend/ban-dependencies
 import { glob } from 'glob';
 import slash from 'slash';
 
diff --git a/code/builders/builder-vite/src/plugins/code-generator-plugin.ts b/code/builders/builder-vite/src/plugins/code-generator-plugin.ts
index 77509b97cf93..79dba3844060 100644
--- a/code/builders/builder-vite/src/plugins/code-generator-plugin.ts
+++ b/code/builders/builder-vite/src/plugins/code-generator-plugin.ts
@@ -50,7 +50,7 @@ export function codeGeneratorPlugin(options: Options): Plugin {
     },
     config(config, { command }) {
       // If we are building the static distribution, add iframe.html as an entry.
-      // In development mode, it's not an entry - instead, we use an express middleware
+      // In development mode, it's not an entry - instead, we use a middleware
       // to serve iframe.html. The reason is that Vite's dev server (at the time of writing)
       // does not support virtual files as entry points.
       if (command === 'build') {
diff --git a/code/builders/builder-webpack5/package.json b/code/builders/builder-webpack5/package.json
index e6f8716ffc4f..0c122fc4a33a 100644
--- a/code/builders/builder-webpack5/package.json
+++ b/code/builders/builder-webpack5/package.json
@@ -72,7 +72,6 @@
     "constants-browserify": "^1.0.0",
     "css-loader": "^6.7.1",
     "es-module-lexer": "^1.5.0",
-    "express": "^4.19.2",
     "fork-ts-checker-webpack-plugin": "^8.0.0",
     "html-webpack-plugin": "^5.5.0",
     "magic-string": "^0.30.5",
@@ -95,6 +94,7 @@
     "@types/terser-webpack-plugin": "^5.2.0",
     "@types/webpack-hot-middleware": "^2.25.6",
     "pretty-hrtime": "^1.0.3",
+    "sirv": "^2.0.4",
     "slash": "^5.0.0",
     "typescript": "^5.3.2"
   },
diff --git a/code/builders/builder-webpack5/src/index.ts b/code/builders/builder-webpack5/src/index.ts
index ffc11812562b..a8af6e699ad4 100644
--- a/code/builders/builder-webpack5/src/index.ts
+++ b/code/builders/builder-webpack5/src/index.ts
@@ -12,8 +12,8 @@ import type { Builder, Options } from 'storybook/internal/types';
 
 import { checkWebpackVersion } from '@storybook/core-webpack';
 
-import express from 'express';
 import prettyTime from 'pretty-hrtime';
+import sirv from 'sirv';
 import { corePath } from 'storybook/core-path';
 import type { Configuration, Stats, StatsOptions } from 'webpack';
 import webpack, { ProgressPlugin } from 'webpack';
@@ -137,7 +137,7 @@ const starter: StarterFunction = async function* starterGeneratorFn({
   }
 
   yield;
-  const modulesCount = (await options.cache?.get('modulesCount').catch(() => {})) || 1000;
+  const modulesCount = await options.cache?.get('modulesCount', 1000);
   let totalModules: number;
   let value = 0;
 
@@ -147,7 +147,7 @@ const starter: StarterFunction = async function* starterGeneratorFn({
       const progress = { value, message: message.charAt(0).toUpperCase() + message.slice(1) };
       if (message === 'building') {
         // arg3 undefined in webpack5
-        const counts = (arg3 && arg3.match(/(\d+)\/(\d+)/)) || [];
+        const counts = (arg3 && arg3.match(/entries (\d+)\/(\d+)/)) || [];
         const complete = parseInt(counts[1], 10);
         const total = parseInt(counts[2], 10);
         if (!Number.isNaN(complete) && !Number.isNaN(total)) {
@@ -180,10 +180,14 @@ const starter: StarterFunction = async function* starterGeneratorFn({
   compilation = webpackDevMiddleware(compiler, middlewareOptions);
 
   const previewResolvedDir = join(corePath, 'dist/preview');
-  const previewDirOrigin = previewResolvedDir;
-
-  router.use(`/sb-preview`, express.static(previewDirOrigin, { immutable: true, maxAge: '5m' }));
-
+  router.use(
+    '/sb-preview',
+    sirv(previewResolvedDir, {
+      maxAge: 300000,
+      dev: true,
+      immutable: true,
+    })
+  );
   router.use(compilation);
   router.use(webpackHotMiddleware(compiler, { log: false }));
 
@@ -289,10 +293,8 @@ const builder: BuilderFunction = async function* builderGeneratorFn({ startTime,
   });
 
   const previewResolvedDir = join(corePath, 'dist/preview');
-  const previewDirOrigin = previewResolvedDir;
   const previewDirTarget = join(options.outputDir || '', `sb-preview`);
-
-  const previewFiles = cp(previewDirOrigin, previewDirTarget, {
+  const previewFiles = cp(previewResolvedDir, previewDirTarget, {
     filter: (src) => {
       const { ext } = parse(src);
       if (ext) {
diff --git a/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts b/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts
index ea8b55d4973c..763f2bf15646 100644
--- a/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts
+++ b/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts
@@ -72,7 +72,7 @@ export default async (
     docsOptions,
     entries,
     nonNormalizedStories,
-    modulesCount = 1000,
+    modulesCount,
     build,
     tagsOptions,
   ] = await Promise.all([
@@ -86,7 +86,7 @@ export default async (
     presets.apply('docs'),
     presets.apply<string[]>('entries', []),
     presets.apply('stories', []),
-    options.cache?.get('modulesCount').catch(() => {}),
+    options.cache?.get('modulesCount', 1000),
     options.presets.apply('build'),
     presets.apply('tags', {}),
   ]);
diff --git a/code/core/package.json b/code/core/package.json
index 9a8dff954fdb..09a26d547178 100644
--- a/code/core/package.json
+++ b/code/core/package.json
@@ -278,12 +278,10 @@
   },
   "dependencies": {
     "@storybook/csf": "^0.1.11",
-    "@types/express": "^4.17.21",
     "better-opn": "^3.0.2",
     "browser-assert": "^1.2.1",
     "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0",
     "esbuild-register": "^3.5.0",
-    "express": "^4.19.2",
     "jsdoc-type-pratt-parser": "^4.0.0",
     "process": "^0.11.10",
     "recast": "^0.23.5",
@@ -307,6 +305,7 @@
     "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
     "@fal-works/esbuild-plugin-global-externals": "^2.1.2",
     "@ndelangen/get-tarball": "^3.0.7",
+    "@polka/compression": "^1.0.0-next.28",
     "@popperjs/core": "^2.6.0",
     "@radix-ui/react-dialog": "^1.0.5",
     "@radix-ui/react-scroll-area": "1.2.0-rc.7",
@@ -316,7 +315,6 @@
     "@storybook/icons": "^1.2.10",
     "@tanstack/react-virtual": "^3.3.0",
     "@testing-library/react": "^14.0.0",
-    "@types/compression": "^1.7.0",
     "@types/cross-spawn": "^6.0.2",
     "@types/detect-port": "^1.3.0",
     "@types/diff": "^5.0.9",
@@ -346,7 +344,6 @@
     "cli-table3": "^0.6.1",
     "commander": "^12.1.0",
     "comment-parser": "^1.4.1",
-    "compression": "^1.7.4",
     "copy-to-clipboard": "^3.3.1",
     "cross-spawn": "^7.0.3",
     "css": "^3.0.0",
@@ -362,10 +359,8 @@
     "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0",
     "esbuild-plugin-alias": "^0.2.1",
     "execa": "^8.0.1",
-    "express": "^4.19.2",
     "fd-package-json": "^1.2.0",
     "fetch-retry": "^6.0.0",
-    "file-system-cache": "^2.4.4",
     "find-cache-dir": "^5.0.0",
     "find-up": "^7.0.0",
     "flush-promises": "^1.0.2",
@@ -387,6 +382,7 @@
     "picomatch": "^2.3.0",
     "picoquery": "^1.4.0",
     "polished": "^4.2.2",
+    "polka": "^1.0.0-next.28",
     "prettier": "^3.2.5",
     "pretty-hrtime": "^1.0.3",
     "prompts": "^2.4.0",
@@ -402,6 +398,7 @@
     "react-transition-group": "^4.4.5",
     "require-from-string": "^2.0.2",
     "resolve-from": "^5.0.0",
+    "sirv": "^2.0.4",
     "slash": "^5.0.0",
     "source-map": "^0.7.4",
     "store2": "^2.14.2",
diff --git a/code/core/src/builder-manager/index.ts b/code/core/src/builder-manager/index.ts
index b068caf206c7..faad0a288acf 100644
--- a/code/core/src/builder-manager/index.ts
+++ b/code/core/src/builder-manager/index.ts
@@ -9,7 +9,7 @@ import { logger } from '@storybook/core/node-logger';
 import { globalExternals } from '@fal-works/esbuild-plugin-global-externals';
 import { pnpPlugin } from '@yarnpkg/esbuild-plugin-pnp';
 import aliasPlugin from 'esbuild-plugin-alias';
-import express from 'express';
+import sirv from 'sirv';
 
 import type {
   BuilderBuildResult,
@@ -26,6 +26,7 @@ import { wrapManagerEntries } from './utils/managerEntries';
 import { safeResolve } from './utils/safeResolve';
 import { getTemplatePath, renderHTML } from './utils/template';
 
+const isRootPath = /^\/($|\?)/;
 let compilation: Compilation;
 let asyncIterator: ReturnType<StarterFunction> | ReturnType<BuilderFunction>;
 
@@ -165,8 +166,22 @@ const starter: StarterFunction = async function* starterGeneratorFn({
     'manager'
   );
 
-  router.use(`/sb-addons`, express.static(addonsDir, { immutable: true, maxAge: '5m' }));
-  router.use(`/sb-manager`, express.static(coreDirOrigin, { immutable: true, maxAge: '5m' }));
+  router.use(
+    '/sb-addons',
+    sirv(addonsDir, {
+      maxAge: 300000,
+      dev: true,
+      immutable: true,
+    })
+  );
+  router.use(
+    '/sb-manager',
+    sirv(coreDirOrigin, {
+      maxAge: 300000,
+      dev: true,
+      immutable: true,
+    })
+  );
 
   const { cssFiles, jsFiles } = await readOrderedFiles(addonsDir, compilation?.outputFiles);
 
@@ -193,15 +208,19 @@ const starter: StarterFunction = async function* starterGeneratorFn({
 
   yield;
 
-  router.use(`/`, ({ path }, res, next) => {
-    if (path === '/') {
-      res.status(200).send(html);
+  router.use('/', ({ url }, res, next) => {
+    if (url && isRootPath.test(url)) {
+      res.statusCode = 200;
+      res.write(html);
+      res.end();
     } else {
       next();
     }
   });
-  router.use(`/index.html`, ({ path }, res) => {
-    res.status(200).send(html);
+  router.use(`/index.html`, (req, res) => {
+    res.statusCode = 200;
+    res.write(html);
+    res.end();
   });
 
   return {
@@ -250,7 +269,6 @@ const builder: BuilderFunction = async function* builderGeneratorFn({ startTime,
   // TODO: this doesn't watch, we should change this to use the esbuild watch API: https://esbuild.github.io/api/#watch
   compilation = await instance({
     ...config,
-
     minify: true,
   });
 
diff --git a/code/core/src/cli/detect.test.ts b/code/core/src/cli/detect.test.ts
index 95c1b126dca3..ea7f8139fda3 100644
--- a/code/core/src/cli/detect.test.ts
+++ b/code/core/src/cli/detect.test.ts
@@ -24,6 +24,7 @@ vi.mock('fs', () => ({
   readdirSync: vi.fn(),
   readlinkSync: vi.fn(),
   default: vi.fn(),
+  mkdirSync: vi.fn(),
 }));
 
 vi.mock('@storybook/core/node-logger');
diff --git a/code/core/src/cli/dev.ts b/code/core/src/cli/dev.ts
index 6d05f140fa38..26ff6250f3a8 100644
--- a/code/core/src/cli/dev.ts
+++ b/code/core/src/cli/dev.ts
@@ -44,14 +44,16 @@ export const dev = async (cliOptions: CLIOptions) => {
 
   const packageJson = await findPackage(__dirname);
   invariant(packageJson, 'Failed to find the closest package.json file.');
+  type Options = Parameters<typeof buildDevStandalone>[0];
+
   const options = {
     ...cliOptions,
     configDir: cliOptions.configDir || './.storybook',
     configType: 'DEVELOPMENT',
     ignorePreview: !!cliOptions.previewUrl && !cliOptions.forceBuildPreview,
-    cache,
+    cache: cache as any,
     packageJson,
-  } as Parameters<typeof buildDevStandalone>[0];
+  } as Options;
 
   await withTelemetry(
     'dev',
diff --git a/code/core/src/common/js-package-manager/JsPackageManager.ts b/code/core/src/common/js-package-manager/JsPackageManager.ts
index 5b0bdde0fdb6..21f870852d4d 100644
--- a/code/core/src/common/js-package-manager/JsPackageManager.ts
+++ b/code/core/src/common/js-package-manager/JsPackageManager.ts
@@ -2,8 +2,8 @@ import { existsSync, readFileSync } from 'node:fs';
 import { readFile, writeFile } from 'node:fs/promises';
 import { dirname, resolve } from 'node:path';
 
-import type { CommonOptions } from 'execa';
-import { execaCommand, execaCommandSync } from 'execa';
+// eslint-disable-next-line depend/ban-dependencies
+import { type CommonOptions, execaCommand, execaCommandSync } from 'execa';
 import picocolors from 'picocolors';
 import { gt, satisfies } from 'semver';
 import invariant from 'tiny-invariant';
diff --git a/code/core/src/common/utils/file-cache.ts b/code/core/src/common/utils/file-cache.ts
index de65cc988383..590ddf60d608 100644
--- a/code/core/src/common/utils/file-cache.ts
+++ b/code/core/src/common/utils/file-cache.ts
@@ -1,11 +1,158 @@
-import * as fsc from 'file-system-cache';
+/** This file is a modified copy from https://git.nfp.is/TheThing/fs-cache-fast */
+import { createHash, randomBytes } from 'node:crypto';
+import { mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
+import { readFile, readdir, rm, writeFile } from 'node:fs/promises';
+import { tmpdir } from 'node:os';
+import { join } from 'node:path';
 
-// @ts-expect-error (needed due to it's use of `exports.default`)
-const Cache = (fsc.default.default || fsc.default) as typeof fsc.default;
+interface FileSystemCacheOptions {
+  ns?: string;
+  prefix?: string;
+  hash_alg?: string;
+  basePath?: string;
+  ttl?: number;
+}
+
+interface CacheItem {
+  key: string;
+  content?: any;
+  value?: any;
+}
+
+interface CacheSetOptions {
+  ttl?: number;
+  encoding?: BufferEncoding;
+}
+
+export class FileSystemCache {
+  private prefix: string;
+
+  private hash_alg: string;
+
+  private cache_dir: string;
+
+  private ttl: number;
+
+  constructor(options: FileSystemCacheOptions = {}) {
+    this.prefix = (options.ns || options.prefix || '') + '-';
+    this.hash_alg = options.hash_alg || 'md5';
+    this.cache_dir =
+      options.basePath || join(tmpdir(), randomBytes(15).toString('base64').replace(/\//g, '-'));
+    this.ttl = options.ttl || 0;
+    createHash(this.hash_alg); // Verifies hash algorithm is available
+    mkdirSync(this.cache_dir, { recursive: true });
+  }
+
+  private generateHash(name: string): string {
+    return join(this.cache_dir, this.prefix + createHash(this.hash_alg).update(name).digest('hex'));
+  }
+
+  private isExpired(parsed: { ttl?: number }, now: number): boolean {
+    return parsed.ttl != null && now > parsed.ttl;
+  }
+
+  private parseCacheData<T>(data: string, fallback: T | null): T | null {
+    const parsed = JSON.parse(data);
+    return this.isExpired(parsed, Date.now()) ? fallback : (parsed.content as T);
+  }
 
-export type Options = Parameters<typeof Cache>['0'];
-export type FileSystemCache = ReturnType<typeof Cache>;
+  private parseSetData<T>(key: string, data: T, opts: CacheSetOptions = {}): string {
+    const ttl = opts.ttl ?? this.ttl;
+    return JSON.stringify({ key, content: data, ...(ttl && { ttl: Date.now() + ttl * 1000 }) });
+  }
+
+  public async get<T = any>(name: string, fallback?: T): Promise<T> {
+    try {
+      const data = await readFile(this.generateHash(name), 'utf8');
+      return this.parseCacheData(data, fallback) as T;
+    } catch {
+      return fallback as T;
+    }
+  }
+
+  public getSync<T>(name: string, fallback?: T): T {
+    try {
+      const data = readFileSync(this.generateHash(name), 'utf8');
+      return this.parseCacheData(data, fallback) as T;
+    } catch {
+      return fallback as T;
+    }
+  }
+
+  public async set<T>(
+    name: string,
+    data: T,
+    orgOpts: CacheSetOptions | number = {}
+  ): Promise<void> {
+    const opts: CacheSetOptions = typeof orgOpts === 'number' ? { ttl: orgOpts } : orgOpts;
+    await writeFile(this.generateHash(name), this.parseSetData(name, data, opts), {
+      encoding: opts.encoding || 'utf8',
+    });
+  }
+
+  public setSync<T>(name: string, data: T, orgOpts: CacheSetOptions | number = {}): void {
+    const opts: CacheSetOptions = typeof orgOpts === 'number' ? { ttl: orgOpts } : orgOpts;
+    writeFileSync(this.generateHash(name), this.parseSetData(name, data, opts), {
+      encoding: opts.encoding || 'utf8',
+    });
+  }
+
+  public async setMany(items: CacheItem[], options?: CacheSetOptions): Promise<void> {
+    await Promise.all(items.map((item) => this.set(item.key, item.content ?? item.value, options)));
+  }
+
+  public setManySync(items: CacheItem[], options?: CacheSetOptions): void {
+    items.forEach((item) => this.setSync(item.key, item.content ?? item.value, options));
+  }
+
+  public async remove(name: string): Promise<void> {
+    await rm(this.generateHash(name), { force: true });
+  }
+
+  public removeSync(name: string): void {
+    rmSync(this.generateHash(name), { force: true });
+  }
+
+  public async clear(): Promise<void> {
+    const files = await readdir(this.cache_dir);
+    await Promise.all(
+      files
+        .filter((f) => f.startsWith(this.prefix))
+        .map((f) => rm(join(this.cache_dir, f), { force: true }))
+    );
+  }
+
+  public clearSync(): void {
+    readdirSync(this.cache_dir)
+      .filter((f) => f.startsWith(this.prefix))
+      .forEach((f) => rmSync(join(this.cache_dir, f), { force: true }));
+  }
+
+  public async getAll(): Promise<CacheItem[]> {
+    const now = Date.now();
+    const files = await readdir(this.cache_dir);
+    const items = await Promise.all(
+      files
+        .filter((f) => f.startsWith(this.prefix))
+        .map((f) => readFile(join(this.cache_dir, f), 'utf8'))
+    );
+    return items
+      .map((data) => JSON.parse(data))
+      .filter((entry) => entry.content && !this.isExpired(entry, now));
+  }
+
+  public async load(): Promise<{ files: CacheItem[] }> {
+    const res = await this.getAll();
+    return {
+      files: res.map((entry) => ({
+        path: this.generateHash(entry.key),
+        value: entry.content,
+        key: entry.key,
+      })),
+    };
+  }
+}
 
-export function createFileSystemCache(options: Options): FileSystemCache {
-  return Cache(options);
+export function createFileSystemCache(options: FileSystemCacheOptions): FileSystemCache {
+  return new FileSystemCache(options);
 }
diff --git a/code/core/src/common/utils/validate-configuration-files.ts b/code/core/src/common/utils/validate-configuration-files.ts
index 3e35a6f2bafb..ccd0dba864ea 100644
--- a/code/core/src/common/utils/validate-configuration-files.ts
+++ b/code/core/src/common/utils/validate-configuration-files.ts
@@ -3,6 +3,7 @@ import { resolve } from 'node:path';
 import { once } from '@storybook/core/node-logger';
 import { MainFileMissingError } from '@storybook/core/server-errors';
 
+// eslint-disable-next-line depend/ban-dependencies
 import { glob } from 'glob';
 import slash from 'slash';
 import { dedent } from 'ts-dedent';
diff --git a/code/core/src/core-server/dev-server.ts b/code/core/src/core-server/dev-server.ts
index cdf1027d1872..325d33366514 100644
--- a/code/core/src/core-server/dev-server.ts
+++ b/code/core/src/core-server/dev-server.ts
@@ -4,8 +4,8 @@ import type { Options } from '@storybook/core/types';
 import { logger } from '@storybook/core/node-logger';
 import { MissingBuilderError } from '@storybook/core/server-errors';
 
-import compression from 'compression';
-import express from 'express';
+import compression from '@polka/compression';
+import polka from 'polka';
 import invariant from 'tiny-invariant';
 
 import type { StoryIndexGenerator } from './utils/StoryIndexGenerator';
@@ -17,19 +17,13 @@ import { getAccessControlMiddleware } from './utils/getAccessControlMiddleware';
 import { getStoryIndexGenerator } from './utils/getStoryIndexGenerator';
 import { getMiddleware } from './utils/middleware';
 import { openInBrowser } from './utils/open-in-browser';
-import { router } from './utils/router';
 import { getServerAddresses } from './utils/server-address';
 import { getServer } from './utils/server-init';
 import { useStatics } from './utils/server-statics';
 
 export async function storybookDevServer(options: Options) {
-  const app = express();
-
-  const [server, features, core] = await Promise.all([
-    getServer(app, options),
-    options.presets.apply('features'),
-    options.presets.apply('core'),
-  ]);
+  const [server, core] = await Promise.all([getServer(options), options.presets.apply('core')]);
+  const app = polka({ server });
 
   const serverChannel = await options.presets.apply(
     'experimental_serverChannel',
@@ -39,7 +33,7 @@ export async function storybookDevServer(options: Options) {
   let indexError: Error | undefined;
   // try get index generator, if failed, send telemetry without storyCount, then rethrow the error
   const initializedStoryIndexGenerator: Promise<StoryIndexGenerator | undefined> =
-    getStoryIndexGenerator(features ?? {}, options, serverChannel).catch((err) => {
+    getStoryIndexGenerator(app, options, serverChannel).catch((err) => {
       indexError = err;
       return undefined;
     });
@@ -53,20 +47,13 @@ export async function storybookDevServer(options: Options) {
   app.use(getAccessControlMiddleware(core?.crossOriginIsolated ?? false));
   app.use(getCachingMiddleware());
 
-  getMiddleware(options.configDir)(router);
-
-  app.use(router);
+  getMiddleware(options.configDir)(app);
 
   const { port, host, initialPath } = options;
   invariant(port, 'expected options to have a port');
   const proto = options.https ? 'https' : 'http';
   const { address, networkAddress } = getServerAddresses(port, host, proto, initialPath);
 
-  const listening = new Promise<void>((resolve, reject) => {
-    // @ts-expect-error (Following line doesn't match TypeScript signature at all 🤔)
-    server.listen({ port, host }, (error: Error) => (error ? reject(error) : resolve()));
-  });
-
   if (!core?.builder) {
     throw new MissingBuilderError();
   }
@@ -76,7 +63,7 @@ export async function storybookDevServer(options: Options) {
   const [previewBuilder, managerBuilder] = await Promise.all([
     getPreviewBuilder(builderName, options.configDir),
     getManagerBuilder(),
-    useStatics(router, options),
+    useStatics(app, options),
   ]);
 
   if (options.debugWebpack) {
@@ -86,7 +73,7 @@ export async function storybookDevServer(options: Options) {
   const managerResult = await managerBuilder.start({
     startTime: process.hrtime(),
     options,
-    router,
+    router: app,
     server,
     channel: serverChannel,
   });
@@ -101,7 +88,7 @@ export async function storybookDevServer(options: Options) {
       .start({
         startTime: process.hrtime(),
         options,
-        router,
+        router: app,
         server,
         channel: serverChannel,
       })
@@ -123,12 +110,17 @@ export async function storybookDevServer(options: Options) {
 
   // this is a preview route, the builder has to be started before we can serve it
   // this handler keeps request to that route pending until the builder is ready to serve it, preventing a 404
-  router.get('/iframe.html', (req, res, next) => {
+  app.use('/iframe.html', (req, res, next) => {
     // We need to catch here or node will treat any errors thrown by `previewStarted` as
     // unhandled and exit (even though they are very much handled below)
     previewStarted.catch(() => {}).then(() => next());
   });
 
+  const listening = new Promise<void>((resolve, reject) => {
+    server.once('error', reject);
+    app.listen({ port, host }, resolve);
+  });
+
   await Promise.all([initializedStoryIndexGenerator, listening]).then(async ([indexGenerator]) => {
     if (indexGenerator && !options.ci && !options.smokeTest && options.open) {
       openInBrowser(host ? networkAddress : address);
@@ -143,7 +135,7 @@ export async function storybookDevServer(options: Options) {
   const previewResult = await previewStarted;
 
   // Now the preview has successfully started, we can count this as a 'dev' event.
-  doTelemetry(core, initializedStoryIndexGenerator, options);
+  doTelemetry(app, core, initializedStoryIndexGenerator, options);
 
   return { previewResult, managerResult, address, networkAddress };
 }
diff --git a/code/core/src/core-server/utils/StoryIndexGenerator.ts b/code/core/src/core-server/utils/StoryIndexGenerator.ts
index aed65a46bf6b..164613d7e4c2 100644
--- a/code/core/src/core-server/utils/StoryIndexGenerator.ts
+++ b/code/core/src/core-server/utils/StoryIndexGenerator.ts
@@ -130,6 +130,7 @@ export class StoryIndexGenerator {
         const fullGlob = slash(join(specifier.directory, specifier.files));
 
         // Dynamically import globby because it is a pure ESM module
+        // eslint-disable-next-line depend/ban-dependencies
         const { globby } = await import('globby');
 
         const files = await globby(fullGlob, {
diff --git a/code/core/src/core-server/utils/__tests__/remove-mdx-stories.test.ts b/code/core/src/core-server/utils/__tests__/remove-mdx-stories.test.ts
index f1342ad48a9a..87fe8317ea35 100644
--- a/code/core/src/core-server/utils/__tests__/remove-mdx-stories.test.ts
+++ b/code/core/src/core-server/utils/__tests__/remove-mdx-stories.test.ts
@@ -5,6 +5,7 @@ import { describe, expect, it, vi } from 'vitest';
 import { normalizeStoriesEntry } from '@storybook/core/common';
 import { type StoriesEntry } from '@storybook/core/types';
 
+// eslint-disable-next-line depend/ban-dependencies
 import { glob as globOriginal } from 'glob';
 import slash from 'slash';
 
diff --git a/code/core/src/core-server/utils/doTelemetry.ts b/code/core/src/core-server/utils/doTelemetry.ts
index 534d409765e0..0e9b48b8c8f5 100644
--- a/code/core/src/core-server/utils/doTelemetry.ts
+++ b/code/core/src/core-server/utils/doTelemetry.ts
@@ -1,16 +1,17 @@
 import { getPrecedingUpgrade, telemetry } from '@storybook/core/telemetry';
 import type { CoreConfig, Options } from '@storybook/core/types';
 
+import type Polka from 'polka';
 import invariant from 'tiny-invariant';
 
 import { sendTelemetryError } from '../withTelemetry';
 import type { StoryIndexGenerator } from './StoryIndexGenerator';
 import { useStorybookMetadata } from './metadata';
-import { router } from './router';
 import { summarizeIndex } from './summarizeIndex';
 import { versionStatus } from './versionStatus';
 
 export async function doTelemetry(
+  app: Polka.Polka,
   core: CoreConfig,
   initializedStoryIndexGenerator: Promise<StoryIndexGenerator | undefined>,
   options: Options
@@ -52,6 +53,6 @@ export async function doTelemetry(
   }
 
   if (!core?.disableProjectJson) {
-    useStorybookMetadata(router, options.configDir);
+    useStorybookMetadata(app, options.configDir);
   }
 }
diff --git a/code/core/src/core-server/utils/get-caching-middleware.ts b/code/core/src/core-server/utils/get-caching-middleware.ts
index d01cb3e5e922..88cc96c2ae70 100644
--- a/code/core/src/core-server/utils/get-caching-middleware.ts
+++ b/code/core/src/core-server/utils/get-caching-middleware.ts
@@ -1,8 +1,8 @@
-import type { RequestHandler } from 'express';
+import type { Middleware } from '../../types';
 
-export function getCachingMiddleware(): RequestHandler {
+export function getCachingMiddleware(): Middleware {
   return (req, res, next) => {
-    res.header('Cache-Control', 'no-store');
+    res.setHeader('Cache-Control', 'no-store');
     next();
   };
 }
diff --git a/code/core/src/core-server/utils/getAccessControlMiddleware.ts b/code/core/src/core-server/utils/getAccessControlMiddleware.ts
index 9eb8851e6a5c..0b5c3428b842 100644
--- a/code/core/src/core-server/utils/getAccessControlMiddleware.ts
+++ b/code/core/src/core-server/utils/getAccessControlMiddleware.ts
@@ -1,16 +1,16 @@
-import type { RequestHandler } from 'express';
+import type { Middleware } from '../../types';
 
-export function getAccessControlMiddleware(crossOriginIsolated: boolean): RequestHandler {
+export function getAccessControlMiddleware(crossOriginIsolated: boolean): Middleware {
   return (req, res, next) => {
-    res.header('Access-Control-Allow-Origin', '*');
-    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
+    res.setHeader('Access-Control-Allow-Origin', '*');
+    res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
     // These headers are required to enable SharedArrayBuffer
     // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
     if (crossOriginIsolated) {
       // These headers are required to enable SharedArrayBuffer
       // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
-      res.header('Cross-Origin-Opener-Policy', 'same-origin');
-      res.header('Cross-Origin-Embedder-Policy', 'require-corp');
+      res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
+      res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
     }
     next();
   };
diff --git a/code/core/src/core-server/utils/getStoryIndexGenerator.ts b/code/core/src/core-server/utils/getStoryIndexGenerator.ts
index 6e5e4960b132..d91373d825cf 100644
--- a/code/core/src/core-server/utils/getStoryIndexGenerator.ts
+++ b/code/core/src/core-server/utils/getStoryIndexGenerator.ts
@@ -1,15 +1,14 @@
 import { normalizeStories } from '@storybook/core/common';
 import type { DocsOptions, Options } from '@storybook/core/types';
 
+import type Polka from 'polka';
+
 import { StoryIndexGenerator } from './StoryIndexGenerator';
 import type { ServerChannel } from './get-server-channel';
-import { router } from './router';
 import { useStoriesJson } from './stories-json';
 
 export async function getStoryIndexGenerator(
-  features: {
-    argTypeTargetsV7?: boolean;
-  },
+  app: Polka.Polka,
   options: Options,
   serverChannel: ServerChannel
 ): Promise<StoryIndexGenerator | undefined> {
@@ -34,7 +33,7 @@ export async function getStoryIndexGenerator(
   const initializedStoryIndexGenerator = generator.initialize().then(() => generator);
 
   useStoriesJson({
-    router,
+    app,
     initializedStoryIndexGenerator,
     normalizedStories,
     serverChannel,
diff --git a/code/core/src/core-server/utils/metadata.ts b/code/core/src/core-server/utils/metadata.ts
index a617b3e1f52c..a9a2ebb337ba 100644
--- a/code/core/src/core-server/utils/metadata.ts
+++ b/code/core/src/core-server/utils/metadata.ts
@@ -2,7 +2,7 @@ import { writeFile } from 'node:fs/promises';
 
 import { getStorybookMetadata } from '@storybook/core/telemetry';
 
-import type { Request, Response, Router } from 'express';
+import type Polka from 'polka';
 
 export async function extractStorybookMetadata(outputFile: string, configDir: string) {
   const storybookMetadata = await getStorybookMetadata(configDir);
@@ -10,10 +10,11 @@ export async function extractStorybookMetadata(outputFile: string, configDir: st
   await writeFile(outputFile, JSON.stringify(storybookMetadata));
 }
 
-export function useStorybookMetadata(router: Router, configDir?: string) {
-  router.use('/project.json', async (req: Request, res: Response) => {
+export function useStorybookMetadata(app: Polka.Polka, configDir?: string) {
+  app.use('/project.json', async (req, res) => {
     const storybookMetadata = await getStorybookMetadata(configDir);
-    res.header('Content-Type', 'application/json');
-    res.send(JSON.stringify(storybookMetadata));
+    res.setHeader('Content-Type', 'application/json');
+    res.write(JSON.stringify(storybookMetadata));
+    res.end();
   });
 }
diff --git a/code/core/src/core-server/utils/remove-mdx-entries.ts b/code/core/src/core-server/utils/remove-mdx-entries.ts
index f71488712a49..da431155016a 100644
--- a/code/core/src/core-server/utils/remove-mdx-entries.ts
+++ b/code/core/src/core-server/utils/remove-mdx-entries.ts
@@ -3,6 +3,7 @@ import { isAbsolute, join, relative } from 'node:path';
 import { commonGlobOptions, normalizeStories } from '@storybook/core/common';
 import type { Options, StoriesEntry } from '@storybook/core/types';
 
+// eslint-disable-next-line depend/ban-dependencies
 import { glob } from 'glob';
 import slash from 'slash';
 
diff --git a/code/core/src/core-server/utils/router.ts b/code/core/src/core-server/utils/router.ts
deleted file mode 100644
index 894388991b5f..000000000000
--- a/code/core/src/core-server/utils/router.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { Router } from 'express';
-
-// @ts-expect-error (Converted from ts-ignore)
-
-export const router: Router = new Router();
diff --git a/code/core/src/core-server/utils/search-files.ts b/code/core/src/core-server/utils/search-files.ts
index b0e743895aa9..723f74341b34 100644
--- a/code/core/src/core-server/utils/search-files.ts
+++ b/code/core/src/core-server/utils/search-files.ts
@@ -31,6 +31,7 @@ export async function searchFiles({
   fileExtensions?: string[];
 }): Promise<SearchResult> {
   // Dynamically import globby because it is a pure ESM module
+  // eslint-disable-next-line depend/ban-dependencies
   const { globby, isDynamicPattern } = await import('globby');
 
   const hasSearchSpecialGlobChars = isDynamicPattern(searchQuery, { cwd });
diff --git a/code/core/src/core-server/utils/server-init.ts b/code/core/src/core-server/utils/server-init.ts
index 60710cb19cfb..d06c3421e7bc 100644
--- a/code/core/src/core-server/utils/server-init.ts
+++ b/code/core/src/core-server/utils/server-init.ts
@@ -2,21 +2,17 @@ import { readFile } from 'node:fs/promises';
 
 import { logger } from '@storybook/core/node-logger';
 
-import type { Express } from 'express';
 import http from 'http';
 import https from 'https';
 
-export async function getServer(
-  app: Express,
-  options: {
-    https?: boolean;
-    sslCert?: string;
-    sslKey?: string;
-    sslCa?: string[];
-  }
-) {
+export async function getServer(options: {
+  https?: boolean;
+  sslCert?: string;
+  sslKey?: string;
+  sslCa?: string[];
+}) {
   if (!options.https) {
-    return http.createServer(app);
+    return http.createServer();
   }
 
   if (!options.sslCert) {
@@ -35,5 +31,5 @@ export async function getServer(
     key: await readFile(options.sslKey, { encoding: 'utf8' }),
   };
 
-  return https.createServer(sslOptions, app);
+  return https.createServer(sslOptions);
 }
diff --git a/code/core/src/core-server/utils/server-statics.ts b/code/core/src/core-server/utils/server-statics.ts
index b6bc406923e8..3e21b4a3ea58 100644
--- a/code/core/src/core-server/utils/server-statics.ts
+++ b/code/core/src/core-server/utils/server-statics.ts
@@ -6,22 +6,19 @@ import type { Options } from '@storybook/core/types';
 
 import { logger } from '@storybook/core/node-logger';
 
-import type { Router } from 'express';
-import express from 'express';
 import picocolors from 'picocolors';
+import type Polka from 'polka';
+import sirv from 'sirv';
 import { dedent } from 'ts-dedent';
 
-export async function useStatics(router: Router, options: Options) {
+export async function useStatics(app: Polka.Polka, options: Options): Promise<void> {
   const staticDirs = (await options.presets.apply('staticDirs')) ?? [];
   const faviconPath = await options.presets.apply<string>('favicon');
 
-  const statics = [
-    ...staticDirs.map((dir) => (typeof dir === 'string' ? dir : `${dir.from}:${dir.to}`)),
-  ];
-
-  if (statics && statics.length > 0) {
-    await Promise.all(
-      statics.map(async (dir) => {
+  await Promise.all(
+    staticDirs
+      .map((dir) => (typeof dir === 'string' ? dir : `${dir.from}:${dir.to}`))
+      .map(async (dir) => {
         try {
           const normalizedDir =
             staticDirs && !isAbsolute(dir)
@@ -40,17 +37,30 @@ export async function useStatics(router: Router, options: Options) {
             );
           }
 
-          router.use(targetEndpoint, express.static(staticPath, { index: false }));
+          app.use(
+            targetEndpoint,
+            sirv(staticPath, {
+              dev: true,
+              etag: true,
+              extensions: [],
+            })
+          );
         } catch (e) {
           if (e instanceof Error) {
             logger.warn(e.message);
           }
         }
       })
-    );
-  }
+  );
 
-  router.get(`/${basename(faviconPath)}`, (req, res) => res.sendFile(faviconPath));
+  app.get(
+    `/${basename(faviconPath)}`,
+    sirv(faviconPath, {
+      dev: true,
+      etag: true,
+      extensions: [],
+    })
+  );
 }
 
 export const parseStaticDir = async (arg: string) => {
diff --git a/code/core/src/core-server/utils/stories-json.test.ts b/code/core/src/core-server/utils/stories-json.test.ts
index 3faa5da2fe19..4868c149b724 100644
--- a/code/core/src/core-server/utils/stories-json.test.ts
+++ b/code/core/src/core-server/utils/stories-json.test.ts
@@ -7,7 +7,7 @@ import { normalizeStoriesEntry } from '@storybook/core/common';
 import { STORY_INDEX_INVALIDATED } from '@storybook/core/core-events';
 
 import { debounce } from 'es-toolkit/compat';
-import type { Request, Response, Router } from 'express';
+import type Polka from 'polka';
 import Watchpack from 'watchpack';
 
 import { csfIndexer } from '../presets/common-preset';
@@ -58,30 +58,30 @@ const getInitializedStoryIndexGenerator = async (
 
 describe('useStoriesJson', () => {
   const use = vi.fn();
-  const router: Router = { use } as any;
-  const send = vi.fn();
+  const app: Polka.Polka = { use } as any;
+  const end = vi.fn();
   const write = vi.fn();
-  const response: Response = {
+  const response: Polka.Response = {
     header: vi.fn(),
-    send,
+    send: vi.fn(),
     status: vi.fn(),
     setHeader: vi.fn(),
     flushHeaders: vi.fn(),
     write,
     flush: vi.fn(),
-    end: vi.fn(),
+    end,
     on: vi.fn(),
   } as any;
 
   beforeEach(async () => {
     use.mockClear();
-    send.mockClear();
+    end.mockClear();
     write.mockClear();
     vi.mocked(debounce).mockImplementation((cb) => cb as any);
     Watchpack.mockClear();
   });
 
-  const request: Request = {
+  const request: Polka.Request = {
     headers: { accept: 'application/json' },
   } as any;
 
@@ -90,7 +90,7 @@ describe('useStoriesJson', () => {
       const mockServerChannel = { emit: vi.fn() } as any as ServerChannel;
       console.time('useStoriesJson');
       useStoriesJson({
-        router,
+        app,
         serverChannel: mockServerChannel,
         workingDir,
         normalizedStories,
@@ -105,8 +105,8 @@ describe('useStoriesJson', () => {
       await route(request, response);
       console.timeEnd('route');
 
-      expect(send).toHaveBeenCalledTimes(1);
-      expect(JSON.parse(send.mock.calls[0][0])).toMatchInlineSnapshot(`
+      expect(end).toHaveBeenCalledTimes(1);
+      expect(JSON.parse(end.mock.calls[0][0])).toMatchInlineSnapshot(`
         {
           "entries": {
             "a--metaof": {
@@ -368,7 +368,7 @@ describe('useStoriesJson', () => {
       const mockServerChannel = { emit: vi.fn() } as any as ServerChannel;
 
       useStoriesJson({
-        router,
+        app,
         serverChannel: mockServerChannel,
         workingDir,
         normalizedStories,
@@ -379,14 +379,14 @@ describe('useStoriesJson', () => {
       const route = use.mock.calls[0][1];
 
       const firstPromise = route(request, response);
-      const secondResponse = { ...response, send: vi.fn(), status: vi.fn() };
+      const secondResponse = { ...response, end: vi.fn(), status: vi.fn() };
       const secondPromise = route(request, secondResponse);
 
       await Promise.all([firstPromise, secondPromise]);
 
-      expect(send).toHaveBeenCalledTimes(1);
-      expect(response.status).not.toEqual(500);
-      expect(secondResponse.send).toHaveBeenCalledTimes(1);
+      expect(end).toHaveBeenCalledTimes(1);
+      expect(response.statusCode).not.toEqual(500);
+      expect(secondResponse.end).toHaveBeenCalledTimes(1);
       expect(secondResponse.status).not.toEqual(500);
     });
   });
@@ -394,13 +394,13 @@ describe('useStoriesJson', () => {
   describe('SSE endpoint', () => {
     beforeEach(() => {
       use.mockClear();
-      send.mockClear();
+      end.mockClear();
     });
 
     it('sends invalidate events', async () => {
       const mockServerChannel = { emit: vi.fn() } as any as ServerChannel;
       useStoriesJson({
-        router,
+        app,
         serverChannel: mockServerChannel,
         workingDir,
         normalizedStories,
@@ -434,7 +434,7 @@ describe('useStoriesJson', () => {
     it('only sends one invalidation when multiple event listeners are listening', async () => {
       const mockServerChannel = { emit: vi.fn() } as any as ServerChannel;
       useStoriesJson({
-        router,
+        app,
         serverChannel: mockServerChannel,
         workingDir,
         normalizedStories,
@@ -476,7 +476,7 @@ describe('useStoriesJson', () => {
 
       const mockServerChannel = { emit: vi.fn() } as any as ServerChannel;
       useStoriesJson({
-        router,
+        app,
         serverChannel: mockServerChannel,
         workingDir,
         normalizedStories,
diff --git a/code/core/src/core-server/utils/stories-json.ts b/code/core/src/core-server/utils/stories-json.ts
index 3426aa689de1..a33e12eb0393 100644
--- a/code/core/src/core-server/utils/stories-json.ts
+++ b/code/core/src/core-server/utils/stories-json.ts
@@ -6,7 +6,7 @@ import type { NormalizedStoriesSpecifier, StoryIndex } from '@storybook/core/typ
 import { STORY_INDEX_INVALIDATED } from '@storybook/core/core-events';
 
 import { debounce } from 'es-toolkit/compat';
-import type { Request, Response, Router } from 'express';
+import type Polka from 'polka';
 
 import type { StoryIndexGenerator } from './StoryIndexGenerator';
 import type { ServerChannel } from './get-server-channel';
@@ -26,14 +26,14 @@ export async function extractStoriesJson(
 }
 
 export function useStoriesJson({
-  router,
+  app,
   initializedStoryIndexGenerator,
   workingDir = process.cwd(),
   configDir,
   serverChannel,
   normalizedStories,
 }: {
-  router: Router;
+  app: Polka.Polka;
   initializedStoryIndexGenerator: Promise<StoryIndexGenerator>;
   serverChannel: ServerChannel;
   workingDir?: string;
@@ -58,15 +58,15 @@ export function useStoriesJson({
     });
   }
 
-  router.use('/index.json', async (req: Request, res: Response) => {
+  app.use('/index.json', async (req, res) => {
     try {
       const generator = await initializedStoryIndexGenerator;
       const index = await generator.getIndex();
-      res.header('Content-Type', 'application/json');
-      res.send(JSON.stringify(index));
+      res.setHeader('Content-Type', 'application/json');
+      res.end(JSON.stringify(index));
     } catch (err) {
-      res.status(500);
-      res.send(err instanceof Error ? err.toString() : String(err));
+      res.statusCode = 500;
+      res.end(err instanceof Error ? err.toString() : String(err));
     }
   });
 }
diff --git a/code/core/src/core-server/utils/watch-story-specifiers.ts b/code/core/src/core-server/utils/watch-story-specifiers.ts
index b320520dc9a4..6fa8d3e83a6f 100644
--- a/code/core/src/core-server/utils/watch-story-specifiers.ts
+++ b/code/core/src/core-server/utils/watch-story-specifiers.ts
@@ -97,6 +97,7 @@ export function watchStorySpecifiers(
             );
 
             // Dynamically import globby because it is a pure ESM module
+            // eslint-disable-next-line depend/ban-dependencies
             const { globby } = await import('globby');
 
             // glob only supports forward slashes
diff --git a/code/core/src/telemetry/get-portable-stories-usage.ts b/code/core/src/telemetry/get-portable-stories-usage.ts
index e328a3283c57..cd9da7f4f589 100644
--- a/code/core/src/telemetry/get-portable-stories-usage.ts
+++ b/code/core/src/telemetry/get-portable-stories-usage.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line depend/ban-dependencies
 import { execaCommand } from 'execa';
 
 import { createFileSystemCache, resolvePathInStorybookCache } from '../common';
diff --git a/code/core/src/types/modules/core-common.ts b/code/core/src/types/modules/core-common.ts
index 8e71a4cadb2a..dbdabe22122c 100644
--- a/code/core/src/types/modules/core-common.ts
+++ b/code/core/src/types/modules/core-common.ts
@@ -1,11 +1,11 @@
 /* eslint-disable @typescript-eslint/naming-convention */
-import type { Router } from 'express';
-import type { FileSystemCache } from 'file-system-cache';
 // should be node:http, but that caused the ui/manager to fail to build, might be able to switch this back once ui/manager is in the core
-import type { Server } from 'http';
-import type * as telejson from 'telejson';
+import type { Server as HttpServer, IncomingMessage, ServerResponse } from 'http';
+import type { Server as NetServer } from 'net';
+import type { Options as TelejsonOptions } from 'telejson';
 import type { PackageJson as PackageJsonFromTypeFest } from 'type-fest';
 
+import type { FileSystemCache } from '../../common/utils/file-cache';
 import type { Indexer, StoriesEntry } from './indexer';
 
 /** ⚠️ This file contains internal WIP types they MUST NOT be exported outside this package for now! */
@@ -26,7 +26,7 @@ export interface CoreConfig {
       };
   renderer?: RendererName;
   disableWebpackDefaults?: boolean;
-  channelOptions?: Partial<telejson.Options>;
+  channelOptions?: Partial<TelejsonOptions>;
   /** Disables the generation of project.json, a file containing Storybook metadata */
   disableProjectJson?: boolean;
   /**
@@ -156,7 +156,7 @@ export interface LoadOptions {
   configDir?: string;
   cacheKey?: string;
   ignorePreview?: boolean;
-  extendServer?: (server: Server) => void;
+  extendServer?: (server: HttpServer) => void;
 }
 
 export interface CLIOptions {
@@ -211,13 +211,37 @@ export type Options = LoadOptions &
   CLIOptions &
   BuilderOptions & { build?: TestBuildConfig };
 
+// A minimal version of Polka's interface to avoid exposing internal implementation details
+export type Middleware<T extends IncomingMessage = IncomingMessage> = (
+  req: T & IncomingMessage,
+  res: ServerResponse,
+  next: (err?: string | Error) => Promise<void> | void
+) => Promise<void> | void;
+
+interface ServerApp<T extends IncomingMessage = IncomingMessage> {
+  server: NetServer;
+
+  use(pattern: RegExp | string, ...handlers: Middleware<T>[]): this;
+  use(...handlers: Middleware<T>[]): this;
+
+  get(pattern: RegExp | string, ...handlers: Middleware<T>[]): this;
+  post(pattern: RegExp | string, ...handlers: Middleware<T>[]): this;
+  put(pattern: RegExp | string, ...handlers: Middleware<T>[]): this;
+  patch(pattern: RegExp | string, ...handlers: Middleware<T>[]): this;
+  delete(pattern: RegExp | string, ...handlers: Middleware<T>[]): this;
+  head(pattern: RegExp | string, ...handlers: Middleware<T>[]): this;
+  options(pattern: RegExp | string, ...handlers: Middleware<T>[]): this;
+  connect(pattern: RegExp | string, ...handlers: Middleware<T>[]): this;
+  trace(pattern: RegExp | string, ...handlers: Middleware<T>[]): this;
+}
+
 export interface Builder<Config, BuilderStats extends Stats = Stats> {
   getConfig: (options: Options) => Promise<Config>;
   start: (args: {
     options: Options;
     startTime: ReturnType<typeof process.hrtime>;
-    router: Router;
-    server: Server;
+    router: ServerApp;
+    server: HttpServer;
     channel: ServerChannel;
   }) => Promise<void | {
     stats?: BuilderStats;
diff --git a/code/lib/cli-storybook/src/automigrate/fixes/mdx-1-to-3.ts b/code/lib/cli-storybook/src/automigrate/fixes/mdx-1-to-3.ts
index e53ee7cde234..155ee08246f6 100644
--- a/code/lib/cli-storybook/src/automigrate/fixes/mdx-1-to-3.ts
+++ b/code/lib/cli-storybook/src/automigrate/fixes/mdx-1-to-3.ts
@@ -51,6 +51,7 @@ export const mdx1to3: Fix<Mdx1to3Options> = {
 
   async check() {
     // Dynamically import globby because it is a pure ESM module
+    // eslint-disable-next-line depend/ban-dependencies
     const { globby } = await import('globby');
 
     const storiesMdxFiles = await globby('./!(node_modules)**/*.(story|stories).mdx');
diff --git a/code/lib/cli-storybook/src/automigrate/fixes/mdx-gfm.ts b/code/lib/cli-storybook/src/automigrate/fixes/mdx-gfm.ts
index 8369f8896ef3..41fc1b4a3a0b 100644
--- a/code/lib/cli-storybook/src/automigrate/fixes/mdx-gfm.ts
+++ b/code/lib/cli-storybook/src/automigrate/fixes/mdx-gfm.ts
@@ -47,6 +47,7 @@ export const mdxgfm: Fix<Options> = {
       }
 
       // Dynamically import globby because it is a pure ESM module
+      // eslint-disable-next-line depend/ban-dependencies
       const { globby } = await import('globby');
 
       const files = await globby(pattern, commonGlobOptions(pattern));
diff --git a/code/lib/cli-storybook/src/automigrate/fixes/mdx-to-csf.ts b/code/lib/cli-storybook/src/automigrate/fixes/mdx-to-csf.ts
index 55e36258c9cd..217b3dcacb93 100644
--- a/code/lib/cli-storybook/src/automigrate/fixes/mdx-to-csf.ts
+++ b/code/lib/cli-storybook/src/automigrate/fixes/mdx-to-csf.ts
@@ -2,6 +2,7 @@ import type { StoriesEntry } from 'storybook/internal/types';
 
 import { runCodemod } from '@storybook/codemod';
 
+// eslint-disable-next-line depend/ban-dependencies
 import { glob } from 'glob';
 import picocolors from 'picocolors';
 import { prompt } from 'prompts';
diff --git a/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.ts b/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.ts
index 9b5892b51a32..8eda42d9b9ba 100644
--- a/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.ts
+++ b/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.ts
@@ -70,6 +70,7 @@ export const missingStorybookDependencies: Fix<MissingStorybookDependenciesOptio
 
   async check({ packageManager }) {
     // Dynamically import globby because it is a pure ESM module
+    // eslint-disable-next-line depend/ban-dependencies
     const { globby } = await import('globby');
 
     const result = await checkInstallations(packageManager, consolidatedPackages);
diff --git a/code/lib/cli-storybook/src/automigrate/fixes/prompt-remove-react.test.ts b/code/lib/cli-storybook/src/automigrate/fixes/prompt-remove-react.test.ts
index 2e6c644bed54..07ed5571ac09 100644
--- a/code/lib/cli-storybook/src/automigrate/fixes/prompt-remove-react.test.ts
+++ b/code/lib/cli-storybook/src/automigrate/fixes/prompt-remove-react.test.ts
@@ -3,6 +3,7 @@ import { describe, expect, it, vi } from 'vitest';
 import type { JsPackageManager } from 'storybook/internal/common';
 import type { StorybookConfig } from 'storybook/internal/types';
 
+// eslint-disable-next-line depend/ban-dependencies
 import { glob } from 'glob';
 
 import { removeReactDependency } from './prompt-remove-react';
diff --git a/code/lib/cli-storybook/src/warn.ts b/code/lib/cli-storybook/src/warn.ts
index ef995d87ef76..f76cd1c6ea4e 100644
--- a/code/lib/cli-storybook/src/warn.ts
+++ b/code/lib/cli-storybook/src/warn.ts
@@ -7,6 +7,7 @@ interface Options {
 export const warn = async ({ hasTSDependency }: Options) => {
   if (!hasTSDependency) {
     // Dynamically import globby because it is a pure ESM module
+    // eslint-disable-next-line depend/ban-dependencies
     const { globby } = await import('globby');
 
     const files = await globby(['**/*.@(ts|tsx)', '!**/node_modules', '!**/*.d.ts']);
diff --git a/code/lib/codemod/src/index.ts b/code/lib/codemod/src/index.ts
index ec80bd250d3f..80bc90932918 100644
--- a/code/lib/codemod/src/index.ts
+++ b/code/lib/codemod/src/index.ts
@@ -65,6 +65,7 @@ export async function runCodemod(
   }
 
   // Dynamically import globby because it is a pure ESM module
+  // eslint-disable-next-line depend/ban-dependencies
   const { globby } = await import('globby');
 
   const files = await globby([glob, '!**/node_modules', '!**/dist']);
diff --git a/code/lib/create-storybook/src/generators/baseGenerator.ts b/code/lib/create-storybook/src/generators/baseGenerator.ts
index b1aea02b11e1..1a44e3ba272b 100644
--- a/code/lib/create-storybook/src/generators/baseGenerator.ts
+++ b/code/lib/create-storybook/src/generators/baseGenerator.ts
@@ -11,6 +11,7 @@ import type { JsPackageManager } from 'storybook/internal/common';
 import { getPackageDetails, versions as packageVersions } from 'storybook/internal/common';
 import type { SupportedFrameworks } from 'storybook/internal/types';
 
+// eslint-disable-next-line depend/ban-dependencies
 import ora from 'ora';
 import invariant from 'tiny-invariant';
 import { dedent } from 'ts-dedent';
diff --git a/code/lib/create-storybook/src/scaffold-new-project.ts b/code/lib/create-storybook/src/scaffold-new-project.ts
index f41d9c876010..c07ff8c9fba4 100644
--- a/code/lib/create-storybook/src/scaffold-new-project.ts
+++ b/code/lib/create-storybook/src/scaffold-new-project.ts
@@ -7,6 +7,7 @@ import { GenerateNewProjectOnInitError } from 'storybook/internal/server-errors'
 import { telemetry } from 'storybook/internal/telemetry';
 
 import boxen from 'boxen';
+// eslint-disable-next-line depend/ban-dependencies
 import execa from 'execa';
 import picocolors from 'picocolors';
 import prompts from 'prompts';
diff --git a/code/package.json b/code/package.json
index dd66a8428ae6..e441ef956340 100644
--- a/code/package.json
+++ b/code/package.json
@@ -168,7 +168,6 @@
     "@testing-library/react": "^16.0.0",
     "@testing-library/user-event": "^14.5.2",
     "@trivago/prettier-plugin-sort-imports": "^4.3.0",
-    "@types/express": "^4.17.21",
     "@types/mock-require": "^2.0.3",
     "@types/node": "^22.0.0",
     "@types/react": "^18.0.37",
@@ -191,6 +190,7 @@
     "esbuild-plugin-alias": "^0.2.1",
     "eslint": "^8.56.0",
     "eslint-import-resolver-typescript": "^3.6.1",
+    "eslint-plugin-depend": "^0.11.0",
     "eslint-plugin-local-rules": "portal:../scripts/eslint-plugin-local-rules",
     "eslint-plugin-playwright": "^1.6.2",
     "eslint-plugin-storybook": "^0.8.0",
@@ -293,5 +293,6 @@
         "Dependency Upgrades"
       ]
     ]
-  }
+  },
+  "deferredNextVersion": "8.4.0-alpha.5"
 }
diff --git a/code/yarn.lock b/code/yarn.lock
index 1b04c78853dc..2c6f7244e415 100644
--- a/code/yarn.lock
+++ b/code/yarn.lock
@@ -4656,6 +4656,20 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@polka/compression@npm:^1.0.0-next.28":
+  version: 1.0.0-next.28
+  resolution: "@polka/compression@npm:1.0.0-next.28"
+  checksum: 10c0/e55912f0a8d5dfcda6f7eb9b8d87cc65782a652003f47e7caf0bd88d81f5c280d9a8310441ee34e2774662ed39369e4f9d5fdb3f3a6adc8f18bc1ee97245fff3
+  languageName: node
+  linkType: hard
+
+"@polka/url@npm:^1.0.0-next.21":
+  version: 1.0.0-next.28
+  resolution: "@polka/url@npm:1.0.0-next.28"
+  checksum: 10c0/acc5ea62597e4da2fb42dbee02749d07f102ae7d6d2c966bf7e423c79cd65d1621da305af567e6e7c232f3b565e242d1ec932cbb3dcc0db1508d02e9a2cafa2e
+  languageName: node
+  linkType: hard
+
 "@polka/url@npm:^1.0.0-next.24":
   version: 1.0.0-next.25
   resolution: "@polka/url@npm:1.0.0-next.25"
@@ -5791,15 +5805,15 @@ __metadata:
   resolution: "@storybook/builder-vite@workspace:builders/builder-vite"
   dependencies:
     "@storybook/csf-plugin": "workspace:*"
-    "@types/express": "npm:^4.17.21"
     "@types/find-cache-dir": "npm:^3.2.1"
     "@types/node": "npm:^22.0.0"
     browser-assert: "npm:^1.2.1"
     es-module-lexer: "npm:^1.5.0"
-    express: "npm:^4.19.2"
     find-cache-dir: "npm:^3.0.0"
     glob: "npm:^10.0.0"
     magic-string: "npm:^0.30.0"
+    polka: "npm:^1.0.0-next.28"
+    sirv: "npm:^2.0.4"
     slash: "npm:^5.0.0"
     ts-dedent: "npm:^2.0.0"
     typescript: "npm:^5.3.2"
@@ -5836,7 +5850,6 @@ __metadata:
     constants-browserify: "npm:^1.0.0"
     css-loader: "npm:^6.7.1"
     es-module-lexer: "npm:^1.5.0"
-    express: "npm:^4.19.2"
     fork-ts-checker-webpack-plugin: "npm:^8.0.0"
     html-webpack-plugin: "npm:^5.5.0"
     magic-string: "npm:^0.30.5"
@@ -5844,6 +5857,7 @@ __metadata:
     pretty-hrtime: "npm:^1.0.3"
     process: "npm:^0.11.10"
     semver: "npm:^7.3.7"
+    sirv: "npm:^2.0.4"
     slash: "npm:^5.0.0"
     style-loader: "npm:^3.3.1"
     terser-webpack-plugin: "npm:^5.3.1"
@@ -6015,6 +6029,7 @@ __metadata:
     "@emotion/use-insertion-effect-with-fallbacks": "npm:^1.0.1"
     "@fal-works/esbuild-plugin-global-externals": "npm:^2.1.2"
     "@ndelangen/get-tarball": "npm:^3.0.7"
+    "@polka/compression": "npm:^1.0.0-next.28"
     "@popperjs/core": "npm:^2.6.0"
     "@radix-ui/react-dialog": "npm:^1.0.5"
     "@radix-ui/react-scroll-area": "npm:1.2.0-rc.7"
@@ -6025,12 +6040,10 @@ __metadata:
     "@storybook/icons": "npm:^1.2.10"
     "@tanstack/react-virtual": "npm:^3.3.0"
     "@testing-library/react": "npm:^14.0.0"
-    "@types/compression": "npm:^1.7.0"
     "@types/cross-spawn": "npm:^6.0.2"
     "@types/detect-port": "npm:^1.3.0"
     "@types/diff": "npm:^5.0.9"
     "@types/ejs": "npm:^3.1.1"
-    "@types/express": "npm:^4.17.21"
     "@types/find-cache-dir": "npm:^5.0.0"
     "@types/js-yaml": "npm:^4.0.5"
     "@types/node": "npm:^22.0.0"
@@ -6058,7 +6071,6 @@ __metadata:
     cli-table3: "npm:^0.6.1"
     commander: "npm:^12.1.0"
     comment-parser: "npm:^1.4.1"
-    compression: "npm:^1.7.4"
     copy-to-clipboard: "npm:^3.3.1"
     cross-spawn: "npm:^7.0.3"
     css: "npm:^3.0.0"
@@ -6075,10 +6087,8 @@ __metadata:
     esbuild-plugin-alias: "npm:^0.2.1"
     esbuild-register: "npm:^3.5.0"
     execa: "npm:^8.0.1"
-    express: "npm:^4.19.2"
     fd-package-json: "npm:^1.2.0"
     fetch-retry: "npm:^6.0.0"
-    file-system-cache: "npm:^2.4.4"
     find-cache-dir: "npm:^5.0.0"
     find-up: "npm:^7.0.0"
     flush-promises: "npm:^1.0.2"
@@ -6101,6 +6111,7 @@ __metadata:
     picomatch: "npm:^2.3.0"
     picoquery: "npm:^1.4.0"
     polished: "npm:^4.2.2"
+    polka: "npm:^1.0.0-next.28"
     prettier: "npm:^3.2.5"
     pretty-hrtime: "npm:^1.0.3"
     process: "npm:^0.11.10"
@@ -6119,6 +6130,7 @@ __metadata:
     require-from-string: "npm:^2.0.2"
     resolve-from: "npm:^5.0.0"
     semver: "npm:^7.6.2"
+    sirv: "npm:^2.0.4"
     slash: "npm:^5.0.0"
     source-map: "npm:^0.7.4"
     store2: "npm:^2.14.2"
@@ -6868,7 +6880,6 @@ __metadata:
     "@testing-library/react": "npm:^16.0.0"
     "@testing-library/user-event": "npm:^14.5.2"
     "@trivago/prettier-plugin-sort-imports": "npm:^4.3.0"
-    "@types/express": "npm:^4.17.21"
     "@types/mock-require": "npm:^2.0.3"
     "@types/node": "npm:^22.0.0"
     "@types/react": "npm:^18.0.37"
@@ -6891,6 +6902,7 @@ __metadata:
     esbuild-plugin-alias: "npm:^0.2.1"
     eslint: "npm:^8.56.0"
     eslint-import-resolver-typescript: "npm:^3.6.1"
+    eslint-plugin-depend: "npm:^0.11.0"
     eslint-plugin-local-rules: "portal:../scripts/eslint-plugin-local-rules"
     eslint-plugin-playwright: "npm:^1.6.2"
     eslint-plugin-storybook: "npm:^0.8.0"
@@ -7648,15 +7660,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/compression@npm:^1.7.0":
-  version: 1.7.5
-  resolution: "@types/compression@npm:1.7.5"
-  dependencies:
-    "@types/express": "npm:*"
-  checksum: 10c0/3818f3d10cede38a835b40b80c341eae162aef1691f2e8f81178a77dbc109f04234cf760b6066eaa06ecbb1da143433c00db2fd9999198b76cd5a193e1d09675
-  languageName: node
-  linkType: hard
-
 "@types/concat-stream@npm:^2.0.0":
   version: 2.0.3
   resolution: "@types/concat-stream@npm:2.0.3"
@@ -7807,7 +7810,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/express@npm:*, @types/express@npm:^4.17.13, @types/express@npm:^4.17.21":
+"@types/express@npm:*, @types/express@npm:^4.17.13":
   version: 4.17.21
   resolution: "@types/express@npm:4.17.21"
   dependencies:
@@ -7844,16 +7847,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/fs-extra@npm:11.0.1":
-  version: 11.0.1
-  resolution: "@types/fs-extra@npm:11.0.1"
-  dependencies:
-    "@types/jsonfile": "npm:*"
-    "@types/node": "npm:*"
-  checksum: 10c0/a65f1fae47849fe1a17441dcabc9400390303405972ff3cbb3578746cea8916b23d5e7652bf57a87767f75a9b2f37caac499b78b5230ae08fef0ba58b34c3a85
-  languageName: node
-  linkType: hard
-
 "@types/fs-extra@npm:^5.0.5":
   version: 5.1.0
   resolution: "@types/fs-extra@npm:5.1.0"
@@ -7988,15 +7981,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/jsonfile@npm:*":
-  version: 6.1.2
-  resolution: "@types/jsonfile@npm:6.1.2"
-  dependencies:
-    "@types/node": "npm:*"
-  checksum: 10c0/c2943f9bfa7867b33fb362b88a932efdc00e9e5f2762b6ef912617cb0a3e3221a98920f8976a4cf817aa576e03d28a25391236e9644e2ebe648081b08df62ef5
-  languageName: node
-  linkType: hard
-
 "@types/loader-utils@npm:^2.0.5":
   version: 2.0.6
   resolution: "@types/loader-utils@npm:2.0.6"
@@ -8164,15 +8148,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/ramda@npm:0.29.3":
-  version: 0.29.3
-  resolution: "@types/ramda@npm:0.29.3"
-  dependencies:
-    types-ramda: "npm:^0.29.4"
-  checksum: 10c0/9c62a4600f5df5e65a01ffe4a470500c98f7c0d093fde47e0d4257675f1ec50effe4696cb004a6b53227948db67ea26a2345dbc91819ecc868105c0f64cecd1e
-  languageName: node
-  linkType: hard
-
 "@types/range-parser@npm:*":
   version: 1.2.5
   resolution: "@types/range-parser@npm:1.2.5"
@@ -14336,6 +14311,17 @@ __metadata:
   languageName: node
   linkType: hard
 
+"eslint-plugin-depend@npm:^0.11.0":
+  version: 0.11.0
+  resolution: "eslint-plugin-depend@npm:0.11.0"
+  dependencies:
+    fd-package-json: "npm:^1.2.0"
+    module-replacements: "npm:^2.1.0"
+    semver: "npm:^7.6.3"
+  checksum: 10c0/64baf4d4f5d406efa1f13bda723ff0eb5fe4cee0ae8c3679fcdfccb4d7ba3a9472416fa3c54d75f1bde3e0123e55a85774662484a5b0355812f21a8968ee784a
+  languageName: node
+  linkType: hard
+
 "eslint-plugin-eslint-comments@npm:^3.2.0":
   version: 3.2.0
   resolution: "eslint-plugin-eslint-comments@npm:3.2.0"
@@ -15009,7 +14995,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"express@npm:^4.17.3, express@npm:^4.19.2":
+"express@npm:^4.17.3":
   version: 4.19.2
   resolution: "express@npm:4.19.2"
   dependencies:
@@ -15268,18 +15254,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"file-system-cache@npm:^2.4.4":
-  version: 2.4.4
-  resolution: "file-system-cache@npm:2.4.4"
-  dependencies:
-    "@types/fs-extra": "npm:11.0.1"
-    "@types/ramda": "npm:0.29.3"
-    fs-extra: "npm:11.1.1"
-    ramda: "npm:0.29.0"
-  checksum: 10c0/274bd9c2f8f81d0c3b2cc0d077807c969b48cac4857ae77f87b4b480548252aa42d3a43b3e9d4bb54df567eb70f0c384782514fcea74b78765543e9496e27e2d
-  languageName: node
-  linkType: hard
-
 "filelist@npm:^1.0.4":
   version: 1.0.4
   resolution: "filelist@npm:1.0.4"
@@ -15723,17 +15697,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"fs-extra@npm:11.1.1":
-  version: 11.1.1
-  resolution: "fs-extra@npm:11.1.1"
-  dependencies:
-    graceful-fs: "npm:^4.2.0"
-    jsonfile: "npm:^6.0.1"
-    universalify: "npm:^2.0.0"
-  checksum: 10c0/a2480243d7dcfa7d723c5f5b24cf4eba02a6ccece208f1524a2fbde1c629492cfb9a59e4b6d04faff6fbdf71db9fdc8ef7f396417a02884195a625f5d8dc9427
-  languageName: node
-  linkType: hard
-
 "fs-extra@npm:^10.0.0, fs-extra@npm:^10.1.0":
   version: 10.1.0
   resolution: "fs-extra@npm:10.1.0"
@@ -21040,6 +21003,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"module-replacements@npm:^2.1.0":
+  version: 2.5.0
+  resolution: "module-replacements@npm:2.5.0"
+  checksum: 10c0/7fcbcb19151778a2f2fa70b7bffb134bb8922b2306e2a0d7b4a863467a9d6d9d5fed537763c43272e22b69dbddaf1610746b42a68b4663aa225e85f9ae9b03c8
+  languageName: node
+  linkType: hard
+
 "mri@npm:^1.1.0, mri@npm:^1.2.0":
   version: 1.2.0
   resolution: "mri@npm:1.2.0"
@@ -22804,6 +22774,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"polka@npm:^1.0.0-next.28":
+  version: 1.0.0-next.28
+  resolution: "polka@npm:1.0.0-next.28"
+  dependencies:
+    "@polka/url": "npm:^1.0.0-next.21"
+    trouter: "npm:^4.0.0"
+  checksum: 10c0/206bab3eb1c3c44c2fba9704d998b144ec36c4852b0b97192a1fd3953f215b739e2286852492c13dcc9faecea0f7825a76356d6eef7e02afd6a800d1dbb84ead
+  languageName: node
+  linkType: hard
+
 "popper.js@npm:^1.16.0":
   version: 1.16.1
   resolution: "popper.js@npm:1.16.1"
@@ -23614,13 +23594,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"ramda@npm:0.29.0":
-  version: 0.29.0
-  resolution: "ramda@npm:0.29.0"
-  checksum: 10c0/b00eaaf1c62b06a99affa1d583e256bd65ad27ab9d0ef512f55d7d93b842e7cd244a4a09179f61fdd8548362e409323867a2b0477cbd0626b5644eb6ac7c53da
-  languageName: node
-  linkType: hard
-
 "randombytes@npm:^2.0.0, randombytes@npm:^2.0.1, randombytes@npm:^2.0.5, randombytes@npm:^2.1.0":
   version: 2.1.0
   resolution: "randombytes@npm:2.1.0"
@@ -24322,6 +24295,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"regexparam@npm:^3.0.0":
+  version: 3.0.0
+  resolution: "regexparam@npm:3.0.0"
+  checksum: 10c0/a6430d7b97d5a7d5518f37a850b6b73aab479029d02f46af4fa0e8e4a1d7aad05b7a0d2d10c86ded21a14d5f0fa4c68525f873a5fca2efeefcccd93c36627459
+  languageName: node
+  linkType: hard
+
 "regexpp@npm:^3.2.0":
   version: 3.2.0
   resolution: "regexpp@npm:3.2.0"
@@ -27276,6 +27256,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"trouter@npm:^4.0.0":
+  version: 4.0.0
+  resolution: "trouter@npm:4.0.0"
+  dependencies:
+    regexparam: "npm:^3.0.0"
+  checksum: 10c0/e27326a831187c6a47a72b62212364e3f88247fa2a8723e5030e14a0002b69756fb51f97efbda2466deb05f4a78ecb83c2a1a7b343e9659cbfb3f370156f1e12
+  languageName: node
+  linkType: hard
+
 "try-catch@npm:^3.0.0":
   version: 3.0.1
   resolution: "try-catch@npm:3.0.1"
@@ -27377,13 +27366,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"ts-toolbelt@npm:^9.6.0":
-  version: 9.6.0
-  resolution: "ts-toolbelt@npm:9.6.0"
-  checksum: 10c0/838f9a2f0fe881d5065257a23b402c41315b33ff987b73db3e2b39fcb70640c4c7220e1ef118ed5676763543724fdbf4eda7b0e2c17acb667ed1401336af9f8c
-  languageName: node
-  linkType: hard
-
 "tsconfig-paths-webpack-plugin@npm:^4.0.1":
   version: 4.1.0
   resolution: "tsconfig-paths-webpack-plugin@npm:4.1.0"
@@ -27567,15 +27549,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"types-ramda@npm:^0.29.4":
-  version: 0.29.10
-  resolution: "types-ramda@npm:0.29.10"
-  dependencies:
-    ts-toolbelt: "npm:^9.6.0"
-  checksum: 10c0/cc6439341a60a4f2b49e1ac447c8a0279f161464fd0a204abaa57e90e101772c0b1adc185a7c0715c3836c19594a9ec268c1e5c4394d0e409cb71d141def3963
-  languageName: node
-  linkType: hard
-
 "typescript@npm:^3.8.3":
   version: 3.9.10
   resolution: "typescript@npm:3.9.10"
diff --git a/docs/versions/next.json b/docs/versions/next.json
index ab225ca861a5..d74fdfbac9b2 100644
--- a/docs/versions/next.json
+++ b/docs/versions/next.json
@@ -1 +1 @@
-{"version":"8.4.0-alpha.4","info":{"plain":"- Blocks: Prebundle `es-toolkit` - [#29259](https://github.com/storybookjs/storybook/pull/29259), thanks @JReinhold!\n- CLI: Update the React Native init to include v8 dependencies - [#29273](https://github.com/storybookjs/storybook/pull/29273), thanks @dannyhw!\n- Core: Upgrade `esbuild`, broadening version range - [#29254](https://github.com/storybookjs/storybook/pull/29254), thanks @ndelangen!\n- Vitest plugin: Fix renamed export stories - [#29250](https://github.com/storybookjs/storybook/pull/29250), thanks @shilman!"}}
+{"version":"8.4.0-alpha.5","info":{"plain":"- Core: Migrate from `express` to `polka` - [#29230](https://github.com/storybookjs/storybook/pull/29230), thanks @43081j!\n- Core: Remove dependence on `file-system-cache` - [#29256](https://github.com/storybookjs/storybook/pull/29256), thanks @ndelangen!"}}
diff --git a/scripts/.eslintrc.cjs b/scripts/.eslintrc.cjs
index 2af8b19b61c1..b49fe70944d0 100644
--- a/scripts/.eslintrc.cjs
+++ b/scripts/.eslintrc.cjs
@@ -1,6 +1,11 @@
 module.exports = {
   root: true,
-  extends: ['@storybook/eslint-config-storybook', 'plugin:storybook/recommended'],
+  extends: [
+    //
+    '@storybook/eslint-config-storybook',
+    'plugin:storybook/recommended',
+    'plugin:depend/recommended'
+  ],
   parserOptions: {
     tsconfigRootDir: __dirname,
     project: ['./tsconfig.json'],
@@ -11,6 +16,9 @@ module.exports = {
     '@typescript-eslint/consistent-type-imports': ['error', { disallowTypeAnnotations: false }],
     'no-use-before-define': 'off',
     'eslint-comments/disable-enable-pair': ['error', { allowWholeFile: true }],
+    "depend/ban-dependencies": ["error", {
+      "modules": ["lodash", "chalk", "qs", "handlebars", "fs-extra"]
+    }]
   },
   overrides: [
     {
diff --git a/scripts/bench/utils.ts b/scripts/bench/utils.ts
index 1bd3a3f849ae..673fb56c4360 100644
--- a/scripts/bench/utils.ts
+++ b/scripts/bench/utils.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line depend/ban-dependencies
 import { ensureDir, readJSON, readdir, writeJSON } from 'fs-extra';
 import { join } from 'path';
 import type { Page } from 'playwright-core';
diff --git a/scripts/build-package.ts b/scripts/build-package.ts
index 96ddb84c2fbc..ee6cf109cbe8 100644
--- a/scripts/build-package.ts
+++ b/scripts/build-package.ts
@@ -1,5 +1,7 @@
 import { program } from 'commander';
+// eslint-disable-next-line depend/ban-dependencies
 import { execaCommand } from 'execa';
+// eslint-disable-next-line depend/ban-dependencies
 import { readJSON } from 'fs-extra';
 import { posix, resolve, sep } from 'path';
 import picocolors from 'picocolors';
@@ -9,7 +11,7 @@ import windowSize from 'window-size';
 import { getWorkspaces } from './utils/workspace';
 
 async function run() {
-  const packages = await getWorkspaces();
+  const packages = (await getWorkspaces()).filter(({ name }) => name !== '@storybook/root');
   const packageTasks = packages
     .map((pkg) => {
       let suffix = pkg.name.replace('@storybook/', '');
diff --git a/scripts/check-package.ts b/scripts/check-package.ts
index 8b9c49985fb5..035ae8a74ec6 100644
--- a/scripts/check-package.ts
+++ b/scripts/check-package.ts
@@ -2,7 +2,9 @@
 // without having to build dts files for all packages in the monorepo.
 // It is not implemented yet for angular, svelte and vue.
 import { program } from 'commander';
+// eslint-disable-next-line depend/ban-dependencies
 import { execaCommand } from 'execa';
+// eslint-disable-next-line depend/ban-dependencies
 import { readJSON } from 'fs-extra';
 import { resolve } from 'path';
 import picocolors from 'picocolors';
diff --git a/scripts/combine-compodoc.ts b/scripts/combine-compodoc.ts
index eefc905fc132..7b934854d015 100755
--- a/scripts/combine-compodoc.ts
+++ b/scripts/combine-compodoc.ts
@@ -1,8 +1,11 @@
 // Compodoc does not follow symlinks (it ignores them and their contents entirely)
 // So, we need to run a separate compodoc process on every symlink inside the project,
 // then combine the results into one large documentation.json
+// eslint-disable-next-line depend/ban-dependencies
 import { execaCommand } from 'execa';
+// eslint-disable-next-line depend/ban-dependencies
 import { lstat, readFile, realpath, writeFile } from 'fs-extra';
+// eslint-disable-next-line depend/ban-dependencies
 import { globSync } from 'glob';
 import { join, resolve } from 'path';
 
diff --git a/scripts/dangerfile.ts b/scripts/dangerfile.ts
index 93382ae441cf..961d77cbd2f8 100644
--- a/scripts/dangerfile.ts
+++ b/scripts/dangerfile.ts
@@ -4,8 +4,11 @@ import { danger, fail } from 'danger';
 
 execSync('npm install lodash');
 
+// eslint-disable-next-line depend/ban-dependencies
 const flatten = require('lodash/flatten.js');
+// eslint-disable-next-line depend/ban-dependencies
 const intersection = require('lodash/intersection.js');
+// eslint-disable-next-line depend/ban-dependencies
 const isEmpty = require('lodash/isEmpty.js');
 
 const pkg = require('../code/package.json');
diff --git a/scripts/event-log-collector.ts b/scripts/event-log-collector.ts
index f3ad10700887..1e4a656960b1 100644
--- a/scripts/event-log-collector.ts
+++ b/scripts/event-log-collector.ts
@@ -1,9 +1,10 @@
-import express from 'express';
+import { json } from '@polka/parse';
+import polka from 'polka';
 
 const PORT = process.env.PORT || 6007;
 
-const server = express();
-server.use(express.json());
+const server = polka();
+server.use(json());
 
 const events: Record<string, unknown>[] = [];
 server.post('/event-log', (req, res) => {
@@ -14,7 +15,7 @@ server.post('/event-log', (req, res) => {
 
 server.get('/event-log', (_req, res) => {
   console.log(`Sending ${events.length} events`);
-  res.json(events);
+  res.end(JSON.stringify(events));
 });
 
 server.listen(PORT, () => {
diff --git a/scripts/get-report-message.ts b/scripts/get-report-message.ts
index 4774bc0f8ca2..60f556b91014 100644
--- a/scripts/get-report-message.ts
+++ b/scripts/get-report-message.ts
@@ -1,4 +1,6 @@
+// eslint-disable-next-line depend/ban-dependencies
 import { execaCommand } from 'execa';
+// eslint-disable-next-line depend/ban-dependencies
 import { readJson } from 'fs-extra';
 import { join } from 'path';
 
diff --git a/scripts/get-template.ts b/scripts/get-template.ts
index 728632392489..cb351eab0410 100644
--- a/scripts/get-template.ts
+++ b/scripts/get-template.ts
@@ -1,4 +1,5 @@
 import { program } from 'commander';
+// eslint-disable-next-line depend/ban-dependencies
 import { pathExists, readFile } from 'fs-extra';
 import { readdir } from 'fs/promises';
 import picocolors from 'picocolors';
diff --git a/scripts/knip.config.ts b/scripts/knip.config.ts
index ef23f8c556bd..c57b570a8ac0 100644
--- a/scripts/knip.config.ts
+++ b/scripts/knip.config.ts
@@ -1,5 +1,6 @@
 import { join, relative } from 'node:path';
 
+// eslint-disable-next-line depend/ban-dependencies
 import fg from 'fast-glob';
 import type { KnipConfig } from 'knip';
 import { match } from 'minimatch';
diff --git a/scripts/package.json b/scripts/package.json
index d38128434b76..d7c89c37cb20 100644
--- a/scripts/package.json
+++ b/scripts/package.json
@@ -64,6 +64,7 @@
     "@nx/workspace": "18.0.6",
     "@octokit/graphql": "^5.0.5",
     "@octokit/request": "^8.1.2",
+    "@polka/parse": "^1.0.0-next.28",
     "@storybook/eslint-config-storybook": "^4.0.0",
     "@storybook/linter-config": "^4.0.0",
     "@testing-library/dom": "^10.4.0",
@@ -75,7 +76,6 @@
     "@types/detect-port": "^1.3.5",
     "@types/ejs": "^3.1.5",
     "@types/escodegen": "^0.0.6",
-    "@types/express": "^4.17.21",
     "@types/fs-extra": "^11.0.4",
     "@types/http-server": "^0.12.4",
     "@types/jest": "^29.5.12",
@@ -112,6 +112,7 @@
     "eslint": "^8.57.0",
     "eslint-config-airbnb-typescript": "^18.0.0",
     "eslint-config-prettier": "^9.1.0",
+    "eslint-plugin-depend": "^0.11.0",
     "eslint-plugin-eslint-comments": "^3.2.0",
     "eslint-plugin-file-progress": "^1.4.0",
     "eslint-plugin-html": "^8.1.1",
@@ -123,7 +124,6 @@
     "eslint-plugin-react-hooks": "^4.6.2",
     "eslint-plugin-storybook": "^0.8.0",
     "execa": "^6.1.0",
-    "express": "^4.19.2",
     "fast-folder-size": "^2.2.0",
     "fast-glob": "^3.3.2",
     "find-up": "^5.0.0",
@@ -146,6 +146,7 @@
     "picocolors": "^1.1.0",
     "playwright": "1.46.0",
     "playwright-core": "1.46.0",
+    "polka": "^1.0.0-next.28",
     "prettier": "^3.3.2",
     "prettier-plugin-brace-style": "^0.6.2",
     "prettier-plugin-css-order": "^2.1.2",
diff --git a/scripts/prepare/addon-bundle.ts b/scripts/prepare/addon-bundle.ts
index fa5e14a0e4c4..16683ea38ff2 100755
--- a/scripts/prepare/addon-bundle.ts
+++ b/scripts/prepare/addon-bundle.ts
@@ -3,7 +3,9 @@ import { builtinModules } from 'node:module';
 
 import type { Metafile } from 'esbuild';
 import aliasPlugin from 'esbuild-plugin-alias';
+// eslint-disable-next-line depend/ban-dependencies
 import * as fs from 'fs-extra';
+// eslint-disable-next-line depend/ban-dependencies
 import { glob } from 'glob';
 import { dirname, join, parse, posix, relative, sep } from 'path';
 import slash from 'slash';
diff --git a/scripts/prepare/bundle.ts b/scripts/prepare/bundle.ts
index 4651774257c8..d3a671034d17 100755
--- a/scripts/prepare/bundle.ts
+++ b/scripts/prepare/bundle.ts
@@ -3,7 +3,9 @@ import { dirname, join, parse, posix, relative, resolve, sep } from 'node:path';
 
 import type { Metafile } from 'esbuild';
 import aliasPlugin from 'esbuild-plugin-alias';
+// eslint-disable-next-line depend/ban-dependencies
 import * as fs from 'fs-extra';
+// eslint-disable-next-line depend/ban-dependencies
 import { glob } from 'glob';
 import slash from 'slash';
 import { dedent } from 'ts-dedent';
diff --git a/scripts/prepare/check.ts b/scripts/prepare/check.ts
index dbf09429492b..0462b6094464 100755
--- a/scripts/prepare/check.ts
+++ b/scripts/prepare/check.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line depend/ban-dependencies
 import fs from 'fs-extra';
 import { join } from 'path';
 import ts from 'typescript';
diff --git a/scripts/prepare/tools.ts b/scripts/prepare/tools.ts
index eb4214a945ba..d2c58b420833 100644
--- a/scripts/prepare/tools.ts
+++ b/scripts/prepare/tools.ts
@@ -5,7 +5,9 @@ import * as process from 'node:process';
 import { globalExternals } from '@fal-works/esbuild-plugin-global-externals';
 import { spawn } from 'cross-spawn';
 import * as esbuild from 'esbuild';
+// eslint-disable-next-line depend/ban-dependencies
 import { readJson } from 'fs-extra';
+// eslint-disable-next-line depend/ban-dependencies
 import { glob } from 'glob';
 import limit from 'p-limit';
 import picocolors from 'picocolors';
diff --git a/scripts/prepare/tsc.ts b/scripts/prepare/tsc.ts
index 6a6aba2643bd..af6b39e15050 100755
--- a/scripts/prepare/tsc.ts
+++ b/scripts/prepare/tsc.ts
@@ -1,4 +1,6 @@
+// eslint-disable-next-line depend/ban-dependencies
 import { emptyDir, move, readJson } from 'fs-extra';
+// eslint-disable-next-line depend/ban-dependencies
 import { globSync } from 'glob';
 import { join } from 'path';
 import * as ts from 'typescript';
diff --git a/scripts/release/__tests__/is-pr-frozen.test.ts b/scripts/release/__tests__/is-pr-frozen.test.ts
index 681069af7256..27baeaa4a723 100644
--- a/scripts/release/__tests__/is-pr-frozen.test.ts
+++ b/scripts/release/__tests__/is-pr-frozen.test.ts
@@ -3,6 +3,7 @@ import { join } from 'node:path';
 
 import { describe, expect, it, vi } from 'vitest';
 
+// eslint-disable-next-line depend/ban-dependencies
 import * as fsExtraImp from 'fs-extra';
 import * as simpleGitImp from 'simple-git';
 
diff --git a/scripts/release/__tests__/version.test.ts b/scripts/release/__tests__/version.test.ts
index 3572e4cb76ee..58dd785c0284 100644
--- a/scripts/release/__tests__/version.test.ts
+++ b/scripts/release/__tests__/version.test.ts
@@ -3,7 +3,9 @@ import { join } from 'node:path';
 
 import { describe, expect, it, vi } from 'vitest';
 
+// eslint-disable-next-line depend/ban-dependencies
 import { execaCommand } from 'execa';
+// eslint-disable-next-line depend/ban-dependencies
 import * as fsExtraImp from 'fs-extra';
 
 import type * as MockedFSToExtra from '../../../code/__mocks__/fs-extra';
diff --git a/scripts/release/__tests__/write-changelog.test.ts b/scripts/release/__tests__/write-changelog.test.ts
index f0346066b26c..59e1ccb6fd60 100644
--- a/scripts/release/__tests__/write-changelog.test.ts
+++ b/scripts/release/__tests__/write-changelog.test.ts
@@ -3,6 +3,7 @@ import { join } from 'node:path';
 
 import { beforeEach, describe, expect, it, vi } from 'vitest';
 
+// eslint-disable-next-line depend/ban-dependencies
 import * as fsExtraImp from 'fs-extra';
 import { dedent } from 'ts-dedent';
 
diff --git a/scripts/release/get-changelog-from-file.ts b/scripts/release/get-changelog-from-file.ts
index 354605e04644..de8bc4e386e9 100644
--- a/scripts/release/get-changelog-from-file.ts
+++ b/scripts/release/get-changelog-from-file.ts
@@ -2,6 +2,7 @@ import { join } from 'node:path';
 
 import { setOutput } from '@actions/core';
 import { program } from 'commander';
+// eslint-disable-next-line depend/ban-dependencies
 import { readFile } from 'fs-extra';
 import picocolors from 'picocolors';
 import semver from 'semver';
diff --git a/scripts/release/get-current-version.ts b/scripts/release/get-current-version.ts
index 8530f6cf9646..b0133cf03f7f 100644
--- a/scripts/release/get-current-version.ts
+++ b/scripts/release/get-current-version.ts
@@ -1,6 +1,7 @@
 import { join } from 'node:path';
 
 import { setOutput } from '@actions/core';
+// eslint-disable-next-line depend/ban-dependencies
 import { readJson } from 'fs-extra';
 import picocolors from 'picocolors';
 
diff --git a/scripts/release/is-pr-frozen.ts b/scripts/release/is-pr-frozen.ts
index d8c80708fc71..e198e89d8202 100644
--- a/scripts/release/is-pr-frozen.ts
+++ b/scripts/release/is-pr-frozen.ts
@@ -2,6 +2,7 @@ import { join } from 'node:path';
 
 import { setOutput } from '@actions/core';
 import { program } from 'commander';
+// eslint-disable-next-line depend/ban-dependencies
 import { readJson } from 'fs-extra';
 import picocolors from 'picocolors';
 
diff --git a/scripts/release/label-patches.ts b/scripts/release/label-patches.ts
index c1d8fa945e11..0ddbd60af981 100644
--- a/scripts/release/label-patches.ts
+++ b/scripts/release/label-patches.ts
@@ -1,4 +1,5 @@
 import { program } from 'commander';
+// eslint-disable-next-line depend/ban-dependencies
 import ora from 'ora';
 import { v4 as uuidv4 } from 'uuid';
 
diff --git a/scripts/release/pick-patches.ts b/scripts/release/pick-patches.ts
index d25667cc4974..54dc6a21b2bb 100644
--- a/scripts/release/pick-patches.ts
+++ b/scripts/release/pick-patches.ts
@@ -1,5 +1,6 @@
 import { setOutput } from '@actions/core';
 import { program } from 'commander';
+// eslint-disable-next-line depend/ban-dependencies
 import ora from 'ora';
 import picocolors from 'picocolors';
 import invariant from 'tiny-invariant';
diff --git a/scripts/release/publish.ts b/scripts/release/publish.ts
index 83839dd4a003..f2054d93398e 100644
--- a/scripts/release/publish.ts
+++ b/scripts/release/publish.ts
@@ -1,7 +1,9 @@
 import { join } from 'node:path';
 
 import { program } from 'commander';
+// eslint-disable-next-line depend/ban-dependencies
 import { execaCommand } from 'execa';
+// eslint-disable-next-line depend/ban-dependencies
 import { readJson } from 'fs-extra';
 import pRetry from 'p-retry';
 import picocolors from 'picocolors';
diff --git a/scripts/release/version.ts b/scripts/release/version.ts
index bdaef52fa18e..7d18b99aeca5 100644
--- a/scripts/release/version.ts
+++ b/scripts/release/version.ts
@@ -2,7 +2,9 @@ import { join } from 'node:path';
 
 import { setOutput } from '@actions/core';
 import { program } from 'commander';
+// eslint-disable-next-line depend/ban-dependencies
 import { execaCommand } from 'execa';
+// eslint-disable-next-line depend/ban-dependencies
 import { readFile, readJson, writeFile, writeJson } from 'fs-extra';
 import picocolors from 'picocolors';
 import semver from 'semver';
diff --git a/scripts/release/write-changelog.ts b/scripts/release/write-changelog.ts
index 59e0d3273958..9e8b1e342cb2 100644
--- a/scripts/release/write-changelog.ts
+++ b/scripts/release/write-changelog.ts
@@ -1,6 +1,7 @@
 import { join } from 'node:path';
 
 import { program } from 'commander';
+// eslint-disable-next-line depend/ban-dependencies
 import { readFile, writeFile, writeJson } from 'fs-extra';
 import picocolors from 'picocolors';
 import semver from 'semver';
diff --git a/scripts/reset.js b/scripts/reset.js
index ed93cbce800b..d9049633d2bc 100644
--- a/scripts/reset.js
+++ b/scripts/reset.js
@@ -1,6 +1,7 @@
 import { spawn } from 'node:child_process';
 import { appendFile, writeFileSync } from 'node:fs';
 
+// eslint-disable-next-line depend/ban-dependencies
 import { remove } from 'fs-extra';
 import trash from 'trash';
 
diff --git a/scripts/run-registry.ts b/scripts/run-registry.ts
index 825788b24f51..5f179501583d 100755
--- a/scripts/run-registry.ts
+++ b/scripts/run-registry.ts
@@ -5,7 +5,9 @@ import type { Server } from 'node:http';
 import { join, resolve as resolvePath } from 'node:path';
 
 import { program } from 'commander';
+// eslint-disable-next-line depend/ban-dependencies
 import { execa, execaSync } from 'execa';
+// eslint-disable-next-line depend/ban-dependencies
 import { pathExists, readJSON, remove } from 'fs-extra';
 import pLimit from 'p-limit';
 import picocolors from 'picocolors';
diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts
index d92696383699..495d142c0196 100755
--- a/scripts/sandbox/generate.ts
+++ b/scripts/sandbox/generate.ts
@@ -1,7 +1,10 @@
 import * as ghActions from '@actions/core';
 import { program } from 'commander';
+// eslint-disable-next-line depend/ban-dependencies
 import type { Options as ExecaOptions } from 'execa';
+// eslint-disable-next-line depend/ban-dependencies
 import { execaCommand } from 'execa';
+// eslint-disable-next-line depend/ban-dependencies
 import { copy, emptyDir, ensureDir, move, remove, rename, writeFile } from 'fs-extra';
 import pLimit from 'p-limit';
 import { join, relative } from 'path';
diff --git a/scripts/sandbox/publish.ts b/scripts/sandbox/publish.ts
index 7ddb549c3900..f83048dff5cd 100755
--- a/scripts/sandbox/publish.ts
+++ b/scripts/sandbox/publish.ts
@@ -1,7 +1,10 @@
 import { program } from 'commander';
+// eslint-disable-next-line depend/ban-dependencies
 import { execaCommand } from 'execa';
 import { existsSync } from 'fs';
+// eslint-disable-next-line depend/ban-dependencies
 import { copy, emptyDir, remove, writeFile } from 'fs-extra';
+// eslint-disable-next-line depend/ban-dependencies
 import { glob } from 'glob';
 import { dirname, join, relative } from 'path';
 
diff --git a/scripts/sandbox/utils/git.ts b/scripts/sandbox/utils/git.ts
index 17022db63fca..2ea8b89f29b4 100644
--- a/scripts/sandbox/utils/git.ts
+++ b/scripts/sandbox/utils/git.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line depend/ban-dependencies
 import { execaCommand } from 'execa';
 import invariant from 'tiny-invariant';
 
diff --git a/scripts/sandbox/utils/template.ts b/scripts/sandbox/utils/template.ts
index 11b6c1e86d5a..825cd6e58641 100644
--- a/scripts/sandbox/utils/template.ts
+++ b/scripts/sandbox/utils/template.ts
@@ -1,4 +1,5 @@
 import { render } from 'ejs';
+// eslint-disable-next-line depend/ban-dependencies
 import { readFile } from 'fs-extra';
 import prettier from 'prettier';
 
diff --git a/scripts/sandbox/utils/yarn.ts b/scripts/sandbox/utils/yarn.ts
index a2d579b2cde0..8f4163256a08 100644
--- a/scripts/sandbox/utils/yarn.ts
+++ b/scripts/sandbox/utils/yarn.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line depend/ban-dependencies
 import { move, remove } from 'fs-extra';
 import { join } from 'path';
 
diff --git a/scripts/strict-ts.ts b/scripts/strict-ts.ts
index 990cbe866ccf..bf0710f5a583 100644
--- a/scripts/strict-ts.ts
+++ b/scripts/strict-ts.ts
@@ -1,6 +1,7 @@
 import { existsSync, readFileSync } from 'node:fs';
 import { dirname, join } from 'node:path';
 
+// eslint-disable-next-line depend/ban-dependencies
 import glob from 'fast-glob';
 import JSON5 from 'json5';
 
diff --git a/scripts/task.ts b/scripts/task.ts
index 905b53b82cae..9a28f8e79546 100644
--- a/scripts/task.ts
+++ b/scripts/task.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line depend/ban-dependencies
 import { outputFile, pathExists, readFile } from 'fs-extra';
 import type { TestCase } from 'junit-xml';
 import { getJunitXml } from 'junit-xml';
diff --git a/scripts/tasks/build.ts b/scripts/tasks/build.ts
index 4a74dcba1f55..796532e2bc0c 100644
--- a/scripts/tasks/build.ts
+++ b/scripts/tasks/build.ts
@@ -1,4 +1,5 @@
 import dirSize from 'fast-folder-size';
+// eslint-disable-next-line depend/ban-dependencies
 import { pathExists } from 'fs-extra';
 import { join } from 'path';
 import { promisify } from 'util';
diff --git a/scripts/tasks/compile.ts b/scripts/tasks/compile.ts
index 2fe631c5f615..bb0bf918812a 100644
--- a/scripts/tasks/compile.ts
+++ b/scripts/tasks/compile.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line depend/ban-dependencies
 import { readFile } from 'fs-extra';
 import { resolve } from 'path';
 
diff --git a/scripts/tasks/generate.ts b/scripts/tasks/generate.ts
index 3e1b0ddc5bc3..5736803a551d 100644
--- a/scripts/tasks/generate.ts
+++ b/scripts/tasks/generate.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line depend/ban-dependencies
 import { pathExists, remove } from 'fs-extra';
 import { join } from 'path';
 
diff --git a/scripts/tasks/install.ts b/scripts/tasks/install.ts
index 90342845687e..0299c18d2fe4 100644
--- a/scripts/tasks/install.ts
+++ b/scripts/tasks/install.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line depend/ban-dependencies
 import { pathExists, remove } from 'fs-extra';
 import { join } from 'path';
 
diff --git a/scripts/tasks/publish.ts b/scripts/tasks/publish.ts
index d83ffb9272b2..987286207dd1 100644
--- a/scripts/tasks/publish.ts
+++ b/scripts/tasks/publish.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line depend/ban-dependencies
 import { pathExists } from 'fs-extra';
 import { resolve } from 'path';
 
diff --git a/scripts/tasks/sandbox-parts.ts b/scripts/tasks/sandbox-parts.ts
index a2df1e8e1691..78f8dad696cc 100644
--- a/scripts/tasks/sandbox-parts.ts
+++ b/scripts/tasks/sandbox-parts.ts
@@ -1,6 +1,7 @@
 // This file requires many imports from `../code`, which requires both an install and bootstrap of
 // the repo to work properly. So we load it async in the task runner *after* those steps.
 import { isFunction } from 'es-toolkit';
+// eslint-disable-next-line depend/ban-dependencies
 import {
   copy,
   ensureDir,
diff --git a/scripts/tasks/sandbox.ts b/scripts/tasks/sandbox.ts
index 93d5cf823c93..5b3494d9955f 100644
--- a/scripts/tasks/sandbox.ts
+++ b/scripts/tasks/sandbox.ts
@@ -1,4 +1,5 @@
 import dirSize from 'fast-folder-size';
+// eslint-disable-next-line depend/ban-dependencies
 import { pathExists, remove } from 'fs-extra';
 import { join } from 'path';
 import { promisify } from 'util';
diff --git a/scripts/upload-bench.ts b/scripts/upload-bench.ts
index 9766079b9dc8..48e5fa618896 100644
--- a/scripts/upload-bench.ts
+++ b/scripts/upload-bench.ts
@@ -1,4 +1,5 @@
 import { BigQuery } from '@google-cloud/bigquery';
+// eslint-disable-next-line depend/ban-dependencies
 import { execaCommand } from 'execa';
 import { join } from 'path';
 
diff --git a/scripts/utils/exec.ts b/scripts/utils/exec.ts
index c12c9eea2f9f..a4a77ebd2244 100644
--- a/scripts/utils/exec.ts
+++ b/scripts/utils/exec.ts
@@ -1,5 +1,5 @@
-import type { ExecaChildProcess, Options } from 'execa';
-import { execa } from 'execa';
+// eslint-disable-next-line depend/ban-dependencies
+import { type ExecaChildProcess, type Options, execa } from 'execa';
 import picocolors from 'picocolors';
 
 const logger = console;
diff --git a/scripts/utils/filterExistsInCodeDir.ts b/scripts/utils/filterExistsInCodeDir.ts
index 7a22fdf8d2f2..673148f916eb 100644
--- a/scripts/utils/filterExistsInCodeDir.ts
+++ b/scripts/utils/filterExistsInCodeDir.ts
@@ -1,5 +1,6 @@
 import { join, resolve } from 'node:path';
 
+// eslint-disable-next-line depend/ban-dependencies
 import { pathExists } from 'fs-extra';
 
 import { CODE_DIRECTORY } from './constants';
diff --git a/scripts/utils/package-json.ts b/scripts/utils/package-json.ts
index cc88350ddfaa..16bdb67f7078 100644
--- a/scripts/utils/package-json.ts
+++ b/scripts/utils/package-json.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line depend/ban-dependencies
 import { readJSON, writeJSON } from 'fs-extra';
 import { join } from 'path';
 
diff --git a/scripts/utils/paths.ts b/scripts/utils/paths.ts
index 36db99f4e093..7253fdff740c 100644
--- a/scripts/utils/paths.ts
+++ b/scripts/utils/paths.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line depend/ban-dependencies
 import { pathExists } from 'fs-extra';
 import { join } from 'path';
 
diff --git a/scripts/utils/serve.ts b/scripts/utils/serve.ts
deleted file mode 100644
index 98ba1da21c63..000000000000
--- a/scripts/utils/serve.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import express from 'express';
-import type { Server } from 'http';
-import serveStatic from 'serve-static';
-
-export const serve = async (location: string, port: string): Promise<Server> => {
-  return new Promise((resolve) => {
-    const app = express();
-
-    app.use(serveStatic(location));
-    const server = app.listen(port, () => {
-      resolve(server);
-    });
-  });
-};
diff --git a/scripts/utils/workspace.ts b/scripts/utils/workspace.ts
index 98a0164ec5ac..fcba0311b09d 100644
--- a/scripts/utils/workspace.ts
+++ b/scripts/utils/workspace.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line depend/ban-dependencies
 import { execaCommand } from 'execa';
 import memoize from 'memoizerific';
 
diff --git a/scripts/utils/yarn.ts b/scripts/utils/yarn.ts
index 0b8147dfa983..1f78e58162c5 100644
--- a/scripts/utils/yarn.ts
+++ b/scripts/utils/yarn.ts
@@ -1,5 +1,6 @@
 import { join } from 'node:path';
 
+// eslint-disable-next-line depend/ban-dependencies
 import { pathExists, readJSON, writeJSON } from 'fs-extra';
 
 // TODO -- should we generate this file a second time outside of CLI?
diff --git a/scripts/vite-ecosystem-ci/before-test.js b/scripts/vite-ecosystem-ci/before-test.js
index 93da3f28519b..35ba21734d06 100644
--- a/scripts/vite-ecosystem-ci/before-test.js
+++ b/scripts/vite-ecosystem-ci/before-test.js
@@ -8,7 +8,8 @@ import { readFile, writeFile } from 'node:fs/promises';
 import { dirname, resolve } from 'node:path';
 import { fileURLToPath } from 'node:url';
 
-import { execa, execaCommand } from 'execa';
+// eslint-disable-next-line depend/ban-dependencies
+import { execaCommand } from 'execa';
 
 const filename = fileURLToPath(import.meta.url);
 // eslint-disable-next-line no-underscore-dangle, @typescript-eslint/naming-convention
diff --git a/scripts/yarn.lock b/scripts/yarn.lock
index a17539cb16d5..5f52272a0427 100644
--- a/scripts/yarn.lock
+++ b/scripts/yarn.lock
@@ -1301,6 +1301,20 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@polka/parse@npm:^1.0.0-next.28":
+  version: 1.0.0-next.28
+  resolution: "@polka/parse@npm:1.0.0-next.28"
+  checksum: 10c0/42c53dfdc4b39a3b516fbd4358b2472b22f36e6038e25d463afb3f133fb1d5af84d7eb4d245ab66bc5793d6414299fdd9093803e5214e560f0693f2176fc58b6
+  languageName: node
+  linkType: hard
+
+"@polka/url@npm:^1.0.0-next.21":
+  version: 1.0.0-next.28
+  resolution: "@polka/url@npm:1.0.0-next.28"
+  checksum: 10c0/acc5ea62597e4da2fb42dbee02749d07f102ae7d6d2c966bf7e423c79cd65d1621da305af567e6e7c232f3b565e242d1ec932cbb3dcc0db1508d02e9a2cafa2e
+  languageName: node
+  linkType: hard
+
 "@rollup/rollup-android-arm-eabi@npm:4.21.0":
   version: 4.21.0
   resolution: "@rollup/rollup-android-arm-eabi@npm:4.21.0"
@@ -1527,6 +1541,7 @@ __metadata:
     "@nx/workspace": "npm:18.0.6"
     "@octokit/graphql": "npm:^5.0.5"
     "@octokit/request": "npm:^8.1.2"
+    "@polka/parse": "npm:^1.0.0-next.28"
     "@storybook/eslint-config-storybook": "npm:^4.0.0"
     "@storybook/linter-config": "npm:^4.0.0"
     "@testing-library/dom": "npm:^10.4.0"
@@ -1538,7 +1553,6 @@ __metadata:
     "@types/detect-port": "npm:^1.3.5"
     "@types/ejs": "npm:^3.1.5"
     "@types/escodegen": "npm:^0.0.6"
-    "@types/express": "npm:^4.17.21"
     "@types/fs-extra": "npm:^11.0.4"
     "@types/http-server": "npm:^0.12.4"
     "@types/jest": "npm:^29.5.12"
@@ -1576,6 +1590,7 @@ __metadata:
     eslint: "npm:^8.57.0"
     eslint-config-airbnb-typescript: "npm:^18.0.0"
     eslint-config-prettier: "npm:^9.1.0"
+    eslint-plugin-depend: "npm:^0.11.0"
     eslint-plugin-eslint-comments: "npm:^3.2.0"
     eslint-plugin-file-progress: "npm:^1.4.0"
     eslint-plugin-html: "npm:^8.1.1"
@@ -1587,7 +1602,6 @@ __metadata:
     eslint-plugin-react-hooks: "npm:^4.6.2"
     eslint-plugin-storybook: "npm:^0.8.0"
     execa: "npm:^6.1.0"
-    express: "npm:^4.19.2"
     fast-folder-size: "npm:^2.2.0"
     fast-glob: "npm:^3.3.2"
     find-up: "npm:^5.0.0"
@@ -1611,6 +1625,7 @@ __metadata:
     picocolors: "npm:^1.1.0"
     playwright: "npm:1.46.0"
     playwright-core: "npm:1.46.0"
+    polka: "npm:^1.0.0-next.28"
     prettier: "npm:^3.3.2"
     prettier-plugin-brace-style: "npm:^0.6.2"
     prettier-plugin-css-order: "npm:^2.1.2"
@@ -1770,16 +1785,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/body-parser@npm:*":
-  version: 1.19.4
-  resolution: "@types/body-parser@npm:1.19.4"
-  dependencies:
-    "@types/connect": "npm:*"
-    "@types/node": "npm:*"
-  checksum: 10c0/bec2b8a97861a960ee415f7ab3c2aeb7f4d779fd364d27ddee46057897ea571735f1f854f5ee41682964315d4e3699f62427998b9c21851d773398ef535f0612
-  languageName: node
-  linkType: hard
-
 "@types/concat-stream@npm:^2.0.0":
   version: 2.0.1
   resolution: "@types/concat-stream@npm:2.0.1"
@@ -1853,30 +1858,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/express-serve-static-core@npm:^4.17.33":
-  version: 4.17.39
-  resolution: "@types/express-serve-static-core@npm:4.17.39"
-  dependencies:
-    "@types/node": "npm:*"
-    "@types/qs": "npm:*"
-    "@types/range-parser": "npm:*"
-    "@types/send": "npm:*"
-  checksum: 10c0/b23b005fddd2ba3f7142ec9713f06b5582c7712cdf99c3419d3972364903b348a103c3264d9a761d6497140e3b89bd416454684c4bdeff206b4c59b86e96428a
-  languageName: node
-  linkType: hard
-
-"@types/express@npm:^4.17.21":
-  version: 4.17.21
-  resolution: "@types/express@npm:4.17.21"
-  dependencies:
-    "@types/body-parser": "npm:*"
-    "@types/express-serve-static-core": "npm:^4.17.33"
-    "@types/qs": "npm:*"
-    "@types/serve-static": "npm:*"
-  checksum: 10c0/12e562c4571da50c7d239e117e688dc434db1bac8be55613294762f84fd77fbd0658ccd553c7d3ab02408f385bc93980992369dd30e2ecd2c68c358e6af8fabf
-  languageName: node
-  linkType: hard
-
 "@types/fs-extra@npm:^11.0.4":
   version: 11.0.4
   resolution: "@types/fs-extra@npm:11.0.4"
@@ -2098,20 +2079,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/qs@npm:*":
-  version: 6.9.9
-  resolution: "@types/qs@npm:6.9.9"
-  checksum: 10c0/aede2a4181a49ae8548a1354bac3f8235cb0c5aab066b10875a3e68e88a199e220f4284e7e2bb75a3c18e5d4ff6abe1a6ce0389ef31b63952cc45e0f4d885ba0
-  languageName: node
-  linkType: hard
-
-"@types/range-parser@npm:*":
-  version: 1.2.6
-  resolution: "@types/range-parser@npm:1.2.6"
-  checksum: 10c0/46e7fffc54cdacc8fb0cd576f8f9a6436453f0176205d6ec55434a460c7677e78e688673426d5db5e480501b2943ba08a16ececa3a354c222093551c7217fb8f
-  languageName: node
-  linkType: hard
-
 "@types/react-dom@npm:^18.3.0":
   version: 18.3.0
   resolution: "@types/react-dom@npm:18.3.0"
@@ -2155,7 +2122,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@types/serve-static@npm:*, @types/serve-static@npm:^1.15.7":
+"@types/serve-static@npm:^1.15.7":
   version: 1.15.7
   resolution: "@types/serve-static@npm:1.15.7"
   dependencies:
@@ -5517,6 +5484,17 @@ __metadata:
   languageName: node
   linkType: hard
 
+"eslint-plugin-depend@npm:^0.11.0":
+  version: 0.11.0
+  resolution: "eslint-plugin-depend@npm:0.11.0"
+  dependencies:
+    fd-package-json: "npm:^1.2.0"
+    module-replacements: "npm:^2.1.0"
+    semver: "npm:^7.6.3"
+  checksum: 10c0/64baf4d4f5d406efa1f13bda723ff0eb5fe4cee0ae8c3679fcdfccb4d7ba3a9472416fa3c54d75f1bde3e0123e55a85774662484a5b0355812f21a8968ee784a
+  languageName: node
+  linkType: hard
+
 "eslint-plugin-eslint-comments@npm:^3.2.0":
   version: 3.2.0
   resolution: "eslint-plugin-eslint-comments@npm:3.2.0"
@@ -6016,7 +5994,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"express@npm:4.19.2, express@npm:^4.19.2":
+"express@npm:4.19.2":
   version: 4.19.2
   resolution: "express@npm:4.19.2"
   dependencies:
@@ -6182,6 +6160,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"fd-package-json@npm:^1.2.0":
+  version: 1.2.0
+  resolution: "fd-package-json@npm:1.2.0"
+  dependencies:
+    walk-up-path: "npm:^3.0.1"
+  checksum: 10c0/712a78a12bd8ec8482867b26bbcb2ff1dca9b096a416150c138e1512f1879c6d23dfb41b03b8e9226afc1e58a35df4738e9f9ae57032ff1dbbae75acfb70343b
+  languageName: node
+  linkType: hard
+
 "fd-slicer@npm:~1.1.0":
   version: 1.1.0
   resolution: "fd-slicer@npm:1.1.0"
@@ -9820,6 +9807,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"module-replacements@npm:^2.1.0":
+  version: 2.5.0
+  resolution: "module-replacements@npm:2.5.0"
+  checksum: 10c0/7fcbcb19151778a2f2fa70b7bffb134bb8922b2306e2a0d7b4a863467a9d6d9d5fed537763c43272e22b69dbddaf1610746b42a68b4663aa225e85f9ae9b03c8
+  languageName: node
+  linkType: hard
+
 "mount-point@npm:^3.0.0":
   version: 3.0.0
   resolution: "mount-point@npm:3.0.0"
@@ -10968,6 +10962,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"polka@npm:^1.0.0-next.28":
+  version: 1.0.0-next.28
+  resolution: "polka@npm:1.0.0-next.28"
+  dependencies:
+    "@polka/url": "npm:^1.0.0-next.21"
+    trouter: "npm:^4.0.0"
+  checksum: 10c0/206bab3eb1c3c44c2fba9704d998b144ec36c4852b0b97192a1fd3953f215b739e2286852492c13dcc9faecea0f7825a76356d6eef7e02afd6a800d1dbb84ead
+  languageName: node
+  linkType: hard
+
 "portfinder@npm:^1.0.28":
   version: 1.0.32
   resolution: "portfinder@npm:1.0.32"
@@ -11627,6 +11631,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"regexparam@npm:^3.0.0":
+  version: 3.0.0
+  resolution: "regexparam@npm:3.0.0"
+  checksum: 10c0/a6430d7b97d5a7d5518f37a850b6b73aab479029d02f46af4fa0e8e4a1d7aad05b7a0d2d10c86ded21a14d5f0fa4c68525f873a5fca2efeefcccd93c36627459
+  languageName: node
+  linkType: hard
+
 "remark-cli@npm:^12.0.0, remark-cli@npm:^12.0.1":
   version: 12.0.1
   resolution: "remark-cli@npm:12.0.1"
@@ -12381,6 +12392,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"semver@npm:^7.6.3":
+  version: 7.6.3
+  resolution: "semver@npm:7.6.3"
+  bin:
+    semver: bin/semver.js
+  checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf
+  languageName: node
+  linkType: hard
+
 "send@npm:0.18.0":
   version: 0.18.0
   resolution: "send@npm:0.18.0"
@@ -13500,6 +13520,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"trouter@npm:^4.0.0":
+  version: 4.0.0
+  resolution: "trouter@npm:4.0.0"
+  dependencies:
+    regexparam: "npm:^3.0.0"
+  checksum: 10c0/e27326a831187c6a47a72b62212364e3f88247fa2a8723e5030e14a0002b69756fb51f97efbda2466deb05f4a78ecb83c2a1a7b343e9659cbfb3f370156f1e12
+  languageName: node
+  linkType: hard
+
 "try-catch@npm:^3.0.0":
   version: 3.0.1
   resolution: "try-catch@npm:3.0.1"