diff --git a/packages/@apphosting/adapter-nextjs/e2e/config-override-test-cases.yaml b/packages/@apphosting/adapter-nextjs/e2e/config-override-test-cases.yaml
index ee40c3b3..8802f395 100644
--- a/packages/@apphosting/adapter-nextjs/e2e/config-override-test-cases.yaml
+++ b/packages/@apphosting/adapter-nextjs/e2e/config-override-test-cases.yaml
@@ -200,3 +200,4 @@ tests:
 
       module.exports = nextConfig;
     file: next.config.js
+  - name: without-a-next-config
diff --git a/packages/@apphosting/adapter-nextjs/e2e/config-override.spec.ts b/packages/@apphosting/adapter-nextjs/e2e/config-override.spec.ts
index a2ab5beb..d98c4e62 100644
--- a/packages/@apphosting/adapter-nextjs/e2e/config-override.spec.ts
+++ b/packages/@apphosting/adapter-nextjs/e2e/config-override.spec.ts
@@ -30,7 +30,7 @@ const compiledFilesPath = posix.join(
 const requiredServerFilePath = posix.join(compiledFilesPath, "required-server-files.json");
 
 describe("next.config override", () => {
-  it("should have images optimization disabled", async function () {
+  it("should have image optimization disabled", async function () {
     if (
       scenario.includes("with-empty-config") ||
       scenario.includes("with-images-unoptimized-false") ||
@@ -53,7 +53,7 @@ describe("next.config override", () => {
   });
 
   it("should preserve other user set next configs", async function () {
-    if (scenario.includes("with-empty-config")) {
+    if (scenario.includes("with-empty-config") || scenario.includes("without-a-next-config")) {
       // eslint-disable-next-line @typescript-eslint/no-invalid-this
       this.skip();
     }
diff --git a/packages/@apphosting/adapter-nextjs/e2e/run-local.ts b/packages/@apphosting/adapter-nextjs/e2e/run-local.ts
index a46d2a93..d8a2afd4 100644
--- a/packages/@apphosting/adapter-nextjs/e2e/run-local.ts
+++ b/packages/@apphosting/adapter-nextjs/e2e/run-local.ts
@@ -53,10 +53,9 @@ const scenarios: Scenario[] = [
     tests: ["middleware.spec.ts"], // Only run middleware-specific tests
   },
   ...configOverrideTestScenarios.map(
-    (scenario: { name: string; config: string; file: string }) => ({
+    (scenario: { name: string; config?: string; file?: string }) => ({
       name: scenario.name,
       setup: async (cwd: string) => {
-        const configContent = scenario.config;
         const files = await fsExtra.readdir(cwd);
         const configFiles = files
           .filter((file) => file.startsWith("next.config."))
@@ -67,6 +66,12 @@ const scenarios: Scenario[] = [
           console.log(`Removed existing config file: ${file}`);
         }
 
+        // skip creating the test config if data is not provided
+        if (!scenario.config || !scenario.file) {
+          return;
+        }
+
+        const configContent = scenario.config;
         await fsExtra.writeFile(join(cwd, scenario.file), configContent);
         console.log(`Created ${scenario.file} file with ${scenario.name} config`);
       },
diff --git a/packages/@apphosting/adapter-nextjs/src/bin/build.ts b/packages/@apphosting/adapter-nextjs/src/bin/build.ts
index eedb6bbb..b7fb4d37 100644
--- a/packages/@apphosting/adapter-nextjs/src/bin/build.ts
+++ b/packages/@apphosting/adapter-nextjs/src/bin/build.ts
@@ -5,7 +5,6 @@ import {
   generateBuildOutput,
   validateOutputDirectory,
   getAdapterMetadata,
-  exists,
 } from "../utils.js";
 import { join } from "path";
 import { getBuildOptions, runBuild } from "@apphosting/common";
@@ -30,16 +29,14 @@ const originalConfig = await loadConfig(root, opts.projectDirectory);
  * load.
  *
  * If the app does not have a next.config.[js|mjs|ts] file in the first place,
- * then can skip config override.
+ * then one is created with the overrides.
  *
  * Note: loadConfig always returns a fileName (default: next.config.js) even if
  * one does not exist in the app's root: https://github.com/vercel/next.js/blob/23681508ca34b66a6ef55965c5eac57de20eb67f/packages/next/src/server/config.ts#L1115
  */
-const originalConfigPath = join(root, originalConfig.configFileName);
-if (await exists(originalConfigPath)) {
-  await overrideNextConfig(root, originalConfig.configFileName);
-  await validateNextConfigOverride(root, opts.projectDirectory, originalConfig.configFileName);
-}
+
+await overrideNextConfig(root, originalConfig.configFileName);
+await validateNextConfigOverride(root, opts.projectDirectory, originalConfig.configFileName);
 
 await runBuild();
 
diff --git a/packages/@apphosting/adapter-nextjs/src/overrides.spec.ts b/packages/@apphosting/adapter-nextjs/src/overrides.spec.ts
index d5ea7928..47c748ef 100644
--- a/packages/@apphosting/adapter-nextjs/src/overrides.spec.ts
+++ b/packages/@apphosting/adapter-nextjs/src/overrides.spec.ts
@@ -190,6 +190,18 @@ describe("next config overrides", () => {
     : fahOptimizedConfig(originalConfig);
   `;
 
+  const defaultNextConfig = `
+    // @ts-nocheck
+
+    /** @type {import('next').NextConfig} */
+    const nextConfig = {
+      images: {
+        unoptimized: true,
+      }
+    }
+
+    module.exports = nextConfig
+  `;
   beforeEach(() => {
     tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "test-overrides"));
   });
@@ -319,14 +331,11 @@ describe("next config overrides", () => {
     );
   });
 
-  it("should not do anything if no next.config.* file exists", async () => {
+  it("should create a default next.config.js file if one does not exist yet", async () => {
     const { overrideNextConfig } = await importOverrides;
     await overrideNextConfig(tmpDir, "next.config.js");
-
-    // Assert that no next.config* files were created
-    const files = fs.readdirSync(tmpDir);
-    const nextConfigFiles = files.filter((file) => file.startsWith("next.config"));
-    assert.strictEqual(nextConfigFiles.length, 0, "No next.config files should exist");
+    const updatedConfig = fs.readFileSync(path.join(tmpDir, "next.config.js"), "utf-8");
+    assert.equal(normalizeWhitespace(updatedConfig), normalizeWhitespace(defaultNextConfig));
   });
 });
 
@@ -334,19 +343,17 @@ describe("validateNextConfigOverride", () => {
   let tmpDir: string;
   let root: string;
   let projectRoot: string;
-  let originalConfigFileName: string;
-  let newConfigFileName: string;
-  let originalConfigPath: string;
-  let newConfigPath: string;
+  let configFileName: string;
+  let preservedConfigFileName: string;
+  let preservedConfigFilePath: string;
 
   beforeEach(() => {
     tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "test-next-config-override"));
     root = tmpDir;
     projectRoot = tmpDir;
-    originalConfigFileName = "next.config.js";
-    newConfigFileName = "next.config.original.js";
-    originalConfigPath = path.join(root, originalConfigFileName);
-    newConfigPath = path.join(root, newConfigFileName);
+    configFileName = "next.config.js";
+    preservedConfigFileName = "next.config.original.js";
+    preservedConfigFilePath = path.join(root, preservedConfigFileName);
 
     fs.mkdirSync(root, { recursive: true });
   });
@@ -355,25 +362,23 @@ describe("validateNextConfigOverride", () => {
     fs.rmSync(tmpDir, { recursive: true, force: true });
   });
 
-  it("should throw an error when new config file doesn't exist", async () => {
-    fs.writeFileSync(originalConfigPath, "module.exports = {}");
-
+  it("should throw an error if a next config file was not created because the user did not have one", async () => {
     const { validateNextConfigOverride } = await importOverrides;
 
     await assert.rejects(
-      async () => await validateNextConfigOverride(root, projectRoot, originalConfigFileName),
-      /New Next.js config file not found/,
+      async () => await validateNextConfigOverride(root, projectRoot, configFileName),
+      /Next.js config file not found/,
     );
   });
 
-  it("should throw an error when original config file doesn't exist", async () => {
-    fs.writeFileSync(newConfigPath, "module.exports = {}");
+  it("should throw an error when main config file doesn't exist", async () => {
+    fs.writeFileSync(preservedConfigFilePath, "module.exports = {}");
 
     const { validateNextConfigOverride } = await importOverrides;
 
     await assert.rejects(
-      async () => await validateNextConfigOverride(root, projectRoot, originalConfigFileName),
-      /Original Next.js config file not found/,
+      async () => await validateNextConfigOverride(root, projectRoot, configFileName),
+      /Next Config Override Failed: Next.js config file not found/,
     );
   });
 });
diff --git a/packages/@apphosting/adapter-nextjs/src/overrides.ts b/packages/@apphosting/adapter-nextjs/src/overrides.ts
index 42ff210a..66494cda 100644
--- a/packages/@apphosting/adapter-nextjs/src/overrides.ts
+++ b/packages/@apphosting/adapter-nextjs/src/overrides.ts
@@ -10,26 +10,38 @@ import {
 import { join, extname } from "path";
 import { rename as renamePromise } from "fs/promises";
 
+const DEFAULT_NEXT_CONFIG_FILE = "next.config.js";
+
 /**
  * Overrides the user's Next Config file (next.config.[ts|js|mjs]) to add configs
  * optimized for Firebase App Hosting.
  */
 export async function overrideNextConfig(projectRoot: string, nextConfigFileName: string) {
   console.log(`Overriding Next Config to add configs optmized for Firebase App Hosting`);
-  // Check if the file exists in the current working directory
-  const configPath = join(projectRoot, nextConfigFileName);
-
-  if (!(await exists(configPath))) {
-    console.log(`No Next.js config file found at ${configPath}`);
+  const userNextConfigExists = await exists(join(projectRoot, nextConfigFileName));
+  if (!userNextConfigExists) {
+    console.log(`No Next config file found, creating one with Firebase App Hosting overrides`);
+    try {
+      await writeFile(join(projectRoot, DEFAULT_NEXT_CONFIG_FILE), defaultNextConfigForFAH());
+      console.log(
+        `Successfully created ${DEFAULT_NEXT_CONFIG_FILE} with Firebase App Hosting overrides`,
+      );
+    } catch (error) {
+      console.error(`Error creating ${DEFAULT_NEXT_CONFIG_FILE}: ${error}`);
+      throw error;
+    }
     return;
   }
 
+  // A Next Config already exists in the user's project, so it needs to be overriden
+
   // Determine the file extension
   const fileExtension = extname(nextConfigFileName);
   const originalConfigName = `next.config.original${fileExtension}`;
 
   // Rename the original config file
   try {
+    const configPath = join(projectRoot, nextConfigFileName);
     const originalPath = join(projectRoot, originalConfigName);
     await renamePromise(configPath, originalPath);
 
@@ -104,30 +116,47 @@ function getCustomNextConfig(importStatement: string, fileExtension: string) {
 }
 
 /**
- * This function is used to validate the state of an app after running the
+ * Returns the default Next Config file that is created in the user's project
+ * if one does not exist already. This config ensures the Next.Js app is optimized
+ * for Firebase App Hosting.
+ */
+function defaultNextConfigForFAH() {
+  return `
+    // @ts-nocheck
+
+    /** @type {import('next').NextConfig} */
+    const nextConfig = {
+      images: {
+        unoptimized: true,
+      }
+    }
+
+    module.exports = nextConfig
+  `;
+}
+
+/**
+ * This function is used to validate the state of an app after running
  * overrideNextConfig. It validates that:
- *  1. original next config is preserved
- *  2. a new next config is created
- *  3. new next config can be loaded by NextJs without any issues.
+ *  1. if user has a next config it is preserved in a next.config.original.[js|ts|mjs] file
+ *  2. a next config exists (should be created with FAH overrides
+ *     even if user did not create one)
+ *  3. next config can be loaded by NextJs without any issues.
  */
 export async function validateNextConfigOverride(
   root: string,
   projectRoot: string,
-  originalConfigFileName: string,
+  configFileName: string,
 ) {
-  const originalConfigExtension = extname(originalConfigFileName);
-  const newConfigFileName = `next.config.original${originalConfigExtension}`;
-  const newConfigFilePath = join(root, newConfigFileName);
-  if (!(await exists(newConfigFilePath))) {
-    throw new Error(
-      `Next Config Override Failed: New Next.js config file not found at ${newConfigFilePath}`,
-    );
-  }
+  const userNextConfigExists = await exists(join(root, configFileName));
+  const configFilePath = join(
+    root,
+    userNextConfigExists ? configFileName : DEFAULT_NEXT_CONFIG_FILE,
+  );
 
-  const originalNextConfigFilePath = join(root, originalConfigFileName);
-  if (!(await exists(originalNextConfigFilePath))) {
+  if (!(await exists(configFilePath))) {
     throw new Error(
-      `Next Config Override Failed: Original Next.js config file not found at ${originalNextConfigFilePath}`,
+      `Next Config Override Failed: Next.js config file not found at ${configFilePath}`,
     );
   }