diff --git a/.changeset/wild-eels-dream.md b/.changeset/wild-eels-dream.md
new file mode 100644
index 000000000000..1a1f325403b8
--- /dev/null
+++ b/.changeset/wild-eels-dream.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Runs `astro:config:done` hook first before generating the internal route manifest
diff --git a/packages/astro/src/config/index.ts b/packages/astro/src/config/index.ts
index 7e7b548f1fcf..a3c236403793 100644
--- a/packages/astro/src/config/index.ts
+++ b/packages/astro/src/config/index.ts
@@ -53,6 +53,7 @@ export function getViteConfig(
 		const { astroConfig: config } = await resolveConfig(inlineAstroConfig, cmd);
 		let settings = await createSettings(config, userViteConfig.root);
 		settings = await runHookConfigSetup({ settings, command: cmd, logger });
+		await runHookConfigDone({ settings, logger });
 		const manifest = await createRouteManifest({ settings }, logger);
 		const devSSRManifest = createDevelopmentManifest(settings);
 		const viteConfig = await createVite(
@@ -66,7 +67,6 @@ export function getViteConfig(
 			},
 			{ settings, command: cmd, logger, mode, sync: false, manifest, ssrManifest: devSSRManifest },
 		);
-		await runHookConfigDone({ settings, logger });
 		return mergeConfig(viteConfig, userViteConfig);
 	};
 }
diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts
index 1fcbd6f03fcb..954514ab1c62 100644
--- a/packages/astro/src/core/build/index.ts
+++ b/packages/astro/src/core/build/index.ts
@@ -119,11 +119,10 @@ class AstroBuilder {
 			command: 'build',
 			logger: logger,
 		});
+		await runHookConfigDone({ settings: this.settings, logger: logger, command: 'build' });
 
 		this.manifest = await createRouteManifest({ settings: this.settings }, this.logger);
 
-		await runHookConfigDone({ settings: this.settings, logger: logger, command: 'build' });
-
 		// If we're building for the server, we need to ensure that an adapter is installed.
 		// If the adapter installed does not support a server output, an error will be thrown when the adapter is added, so no need to check here.
 		if (!this.settings.config.adapter && this.settings.buildOutput === 'server') {
diff --git a/packages/astro/src/core/dev/container.ts b/packages/astro/src/core/dev/container.ts
index 3484227afb9b..eb5451da5a35 100644
--- a/packages/astro/src/core/dev/container.ts
+++ b/packages/astro/src/core/dev/container.ts
@@ -53,6 +53,7 @@ export async function createContainer({
 		logger: logger,
 		isRestart,
 	});
+	await runHookConfigDone({ settings, logger, command: 'dev' });
 
 	const {
 		base,
@@ -85,8 +86,6 @@ export async function createContainer({
 	const manifest = await createRouteManifest({ settings, fsMod: fs }, logger, { dev: true });
 	const devSSRManifest = createDevelopmentManifest(settings);
 
-	await runHookConfigDone({ settings, logger, command: 'dev' });
-
 	warnMissingAdapter(logger, settings);
 
 	const mode = inlineConfig?.mode ?? 'development';
diff --git a/packages/astro/src/core/preview/index.ts b/packages/astro/src/core/preview/index.ts
index dbaf102300cb..6c2d982d4c46 100644
--- a/packages/astro/src/core/preview/index.ts
+++ b/packages/astro/src/core/preview/index.ts
@@ -36,11 +36,11 @@ export default async function preview(inlineConfig: AstroInlineConfig): Promise<
 		command: 'preview',
 		logger: logger,
 	});
+	await runHookConfigDone({ settings: settings, logger: logger, command: 'preview' });
 
 	// Create a route manifest so we can know if the build output is a static site or not
 	await createRouteManifest({ settings: settings, cwd: inlineConfig.root }, logger);
 
-	await runHookConfigDone({ settings: settings, logger: logger, command: 'preview' });
 
 	if (settings.buildOutput === 'static') {
 		if (!fs.existsSync(settings.config.outDir)) {
diff --git a/packages/astro/src/core/routing/manifest/create.ts b/packages/astro/src/core/routing/manifest/create.ts
index 9f925fe69d3f..47c9d343c75f 100644
--- a/packages/astro/src/core/routing/manifest/create.ts
+++ b/packages/astro/src/core/routing/manifest/create.ts
@@ -516,7 +516,9 @@ export async function createRouteManifest(
 		...[...filteredFiledBasedRoutes, ...injectedRoutes, ...redirectRoutes].sort(routeComparator),
 	];
 
-	settings.buildOutput = getPrerenderDefault(config) ? 'static' : 'server';
+	// NOTE: `buildOutput` may already be set by `runHookConfigDone` if the adapter only
+	// support server build output
+	settings.buildOutput ??= getPrerenderDefault(config) ? 'static' : 'server';
 
 	// Check the prerender option for each route
 	const limit = pLimit(10);
diff --git a/packages/astro/src/core/sync/index.ts b/packages/astro/src/core/sync/index.ts
index b1e75097da03..aa892a466684 100644
--- a/packages/astro/src/core/sync/index.ts
+++ b/packages/astro/src/core/sync/index.ts
@@ -67,10 +67,10 @@ export default async function sync(
 		settings,
 		logger,
 	});
-	const manifest = await createRouteManifest({ settings, fsMod: fs }, logger);
-
 	await runHookConfigDone({ settings, logger });
 
+	const manifest = await createRouteManifest({ settings, fsMod: fs }, logger);
+
 	return await syncInternal({
 		settings,
 		logger,