Next.js build output folder

User
react nex js productio build not generating output folder now
Assistant
Gotcha—quick sanity check first: **Next.js doesn’t create an “output” folder by default.**
– `next build` → creates a **`.next/`** folder for server/runtime deployment.
– If you want a static site folder (often named **`out/`**), you must **export**.

Here are the common cases + fixes:

# 1) You actually want `.next/` (server deploy)
Run:

NODE_ENV=production next build

You should see a `.next/` directory at the project root. If you want a different name:

// next.config.js (or next.config.mjs)
export default {
  distDir: 'build', // replaces ".next" with "build"
};

# 2) You need a static folder like `out/`
Two ways:

### A) Modern way (App Router friendly)
In **Next 13+/14+**, set:

// next.config.js or next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'export',           // makes `next build` generate `out/`
  images: { unoptimized: true } // needed for static export if you use next/image
};
export default nextConfig;

Then:

next build   # generates ./out

### B) Legacy command

next build && next export  # creates ./out

# 3) App Router static-export gotchas (why `out/` may not appear)
Static export only works if **all routes are fully static**. These things force “dynamic” and block export:
– `fetch()` without `cache: 'force-cache'` or `next: { revalidate: … }` (i.e., default dynamic fetch)
– Route handlers, server actions, or `dynamic = 'force-dynamic'`
– `cookies()`, `headers()`, or reading request data at runtime

**How to fix** (per route/page in `app/`):

// Make a route fully static:
export const dynamic = 'force-static';           // or
export const revalidate = 60;                    // ISR is exportable
// and make fetches cacheable
await fetch(url, { next: { revalidate: 60 } });  // or cache: 'force-cache'

# 4) Docker/CI notes (common reasons nothing appears)
– Run build **inside the container** where `node_modules` exist:

# inside container
  npm ci
  npm run build

– Ensure your volume mounts aren’t masking the build folder (bind mounts can hide `.next/` or `out/`).
– Check you’re in the **project root** (where `package.json` lives).
– If using a monorepo, ensure the correct `workdir` and that the app has access to its dependencies.
– Don’t `rm -rf` the workspace after build; copy out the folder before cleaning.

# 5) Scripts to keep it simple
In `package.json`:

{
  "scripts": {
    "build": "next build",
    "build:static": "next build && next export",
    "start": "next start -p 3000",
    "serve:static": "npx serve out -p 3000"
  }
}

# 6) Quick checklist if it still “does nothing”
– Run `next build` and **read the logs**: any “dynamic server usage” warnings mean export won’t happen.
– Confirm `next.config.*` is being picked up (add a harmless console.log).
– Delete caches and rebuild:

rm -rf .next out node_modules
  npm ci
  npm run build

– Verify Node version matches Next’s requirements.
– If you expect `out/` but only see `.next/`, you didn’t set `output: 'export'` or run `next export`.

If you paste your `next.config.*`, your folder structure (app/ vs pages/), and the exact build command/log tail, I’ll pinpoint the exact reason fast.

User
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
/* config options here */
};

export default nextConfig;

Assistant
Thanks for the snippet! Right now your config is empty, so **`next build` will only create `.next/`**. If you want an **`out/`** folder (static export), add the `output: 'export'` option and (usually) disable Next/Image optimization.

Here are two ready‑to‑paste options—pick one.

# If you want the default server build (`.next/`)
`next.config.ts`

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  // Optional: change output dir name from ".next" to "build"
  // distDir: "build",
};

export default nextConfig;

Build:

npm run build  # or: next build
# You'll get .next/ (or build/ if you set distDir)

# If you want a static folder (`out/`)
`next.config.ts`

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  output: "export",            // makes `next build` generate ./out
  images: { unoptimized: true } // required if you use next/image during export
  // Optional if you deploy to a subpath:
  // basePath: "/your-subpath",
  // assetPrefix: "/your-subpath/",
  // Optional to avoid mixed slash behavior on some hosts:
  // trailingSlash: true,
};

export default nextConfig;

Build:

npm run build  # or: next build
# You'll get ./out

## Common “no `out/` generated” causes (App Router)
If using `app/`, any dynamic behavior prevents export. Make routes static:

– Avoid `cookies()`, `headers()`, or `dynamic = 'force-dynamic'`.
– Make data fetching cacheable/ISR:

export const revalidate = 60;               // or
  // export const dynamic = 'force-static';
  await fetch(url, { next: { revalidate: 60 } });

– If you see “dynamic server usage” in build logs, that route can’t be exported.

## Quick checks
– Using **TypeScript config** (`next.config.ts`) is fine in Next 13.4+.
– Delete caches and rebuild if in doubt:

rm -rf .next out node_modules
  npm ci
  npm run build

– If you’re targeting server deploy (Node/Edge), don’t set `output: 'export'`.

If you tell me whether you want **server** or **static** and whether you’re on **`app/`** or **`pages/`**, I’ll tailor the exact config + fixes for your project.

User
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
output: "export", // makes `next build` generate ./out
images: { unoptimized: true } // required if you use next/image during export
// Optional if you deploy to a subpath:
// basePath: "/your-subpath",
// assetPrefix: "/your-subpath/",
// Optional to avoid mixed slash behavior on some hosts:
// trailingSlash: true,
};

export default nextConfig;
It works fine but css not coming correct apk i think its not taken

Assistant
Got it — the build works, but **styles are missing after `output: 'export'`**. That’s almost always an **asset path** issue in static export.

First, figure out *where* you’re opening the exported site:

## A) Hosting at a subpath on the web (e.g., `https://domain.com/myapp/`)
You must tell Next the subpath so it points CSS/JS to the right place:

// next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  output: "export",
  images: { unoptimized: true },
  basePath: "/myapp",       // <— your real subpath
  assetPrefix: "/myapp",    // <— match basePath
  trailingSlash: true,      // safer for static hosting
};

export default nextConfig;

Re-build:

rm -rf .next out && npm run build

Upload the **entire** `out/` folder to `/myapp/` on your server.

## B) Bundled in an APK / opened via `file://` (Cordova/Capacitor/WebView)
When loading `out/index.html` directly from the filesystem, absolute URLs like `/_next/static/…` won’t resolve. Use **relative assets**:

// next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  output: "export",
  images: { unoptimized: true },
  assetPrefix: "./",        // <— use relative paths for CSS/JS
  // DO NOT set basePath here
  trailingSlash: true,      // makes relative links safer (index.html in folders)
};

export default nextConfig;

Re-build and package the whole `out/` folder into your APK assets (keep `_next/**` intact).

## Quick checks that usually catch the issue fast

1. **Open `out/index.html`** in a browser and view source.
Do the “ URLs start with `/_next/…`?
– If yes and you’re on **file://** or a subpath → you need the config above.

2. **Make sure `_next/` is present** in your deployed files.
If your server or APK packaging omitted or renamed `out/_next/**`, CSS/JS won’t load.

3. **Tailwind?** Ensure `tailwind.config.js` `content` globs include your `app/**` or `pages/**`. Otherwise CSS may purge out most styles in production.

4. **Custom rewrites/headers?** Don’t block `/_next/*`. Some servers (or CSP) can block static assets.

5. **Fonts (`next/font`)** are fine with static export; they’re in `/_next/`. So again, paths must resolve (use the right `assetPrefix`).

## Minimal working templates

### Subpath deploy (web)

const nextConfig = {
  output: "export",
  images: { unoptimized: true },
  basePath: "/myapp",
  assetPrefix: "/myapp",
  trailingSlash: true,
};
export default nextConfig;

### APK / file:// deploy

const nextConfig = {
  output: "export",
  images: { unoptimized: true },
  assetPrefix: "./",
  trailingSlash: true,
};
export default nextConfig;

If you tell me whether you’re serving from a **subfolder** on a domain or bundling into an **APK/WebView**, I’ll lock in the exact config (and any server rules) for your setup.

User
Not in subfolder

<script>

</script>
<script>

</script>
<script>

</script>
<script>

</script>
<script>

</script>
<script>

</script>

Create Next App

<script>

</script>

Get started by editing src/app/page.tsx.Save and see your changes instantly.Deploy nowRead our docsLearnExamplesGo to nextjs.org →

<script>

</script>
<script>
(self.__next_f=self.__next_f||[]).push([0])
</script>
<script>
self.__next_f.push([1,"1:"$Sreact.fragment"n2:I[39756,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/7dd66bdf8a7e5707.js"],"default"]n3:I[37457,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/7dd66bdf8a7e5707.js"],"default"]n4:I[5500,["/_next/static/chunks/4fcaf8c2a7d2dfb4.js"],"Image"]n5:I[97367,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/7dd66bdf8a7e5707.js"],"OutletBoundary"]n7:I[11533,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/7dd66bdf8a7e5707.js"],"AsyncMetadataOutlet"]n9:I[97367,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/7dd66bdf8a7e5707.js"],"ViewportBoundary"]nb:I[97367,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/7dd66bdf8a7e5707.js"],"MetadataBoundary"]nc:"$Sreact.suspense"ne:I[68027,[],"default"]n:HL["/_next/static/chunks/c488c4f98c6ae379.css","style"]n:HL["/_next/static/media/797e433ab948586e-s.p.dbea232f.woff2","font",{"crossOrigin":"","type":"font/woff2"}]n:HL["/_next/static/media/caa3a2e1cccd8315-s.p.6435ea53.woff2","font",{"crossOrigin":"","type":"font/woff2"}]n:HL["/_next/static/chunks/f560a0e155787fad.css","style"]n"])
</script>
<script>
self.__next_f.push([1,"0:{"P":null,"b":"ytIOM6rww47JWVOE9q67s","p":"","c":["",""],"i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/c488c4f98c6ae379.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"className":"geist_a71539c9-module__T19VSG__variable geist_mono_8d43a2aa-module__8Li5zG__variable","children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","div",null,{"className":"page-module___8aEwW__page","children":[["$","main",null,{"className":"page-module___8aEwW__main","children":[["$","$L4",null,{"className":"page-module___8aEwW__logo","src":"/next.svg","alt":"Next.js logo","width":180,"height":38,"priority":true}],["$","ol",null,{"children":[["$","li",null,{"children":["Get started by editing ",["$","code",null,{"children":"src/app/page.tsx"}],"."]}],["$","li",null,{"children":"Save and see your changes instantly."}]]}],["$","div",null,{"className":"page-module___8aEwW__ctas","children":[["$","a",null,{"className":"page-module___8aEwW__primary","href":"https://vercel.com/new?utm_source=create-next-appu0026utm_medium=appdir-templateu0026utm_campaign=create-next-app","target":"_blank","rel":"noopener noreferrer","children":[["$","$L4",null,{"className":"page-module___8aEwW__logo","src":"/vercel.svg","alt":"Vercel logomark","width":20,"height":20}],"Deploy now"]}],["$","a",null,{"href":"https://nextjs.org/docs?utm_source=create-next-appu0026utm_medium=appdir-templateu0026utm_campaign=create-next-app","target":"_blank","rel":"noopener noreferrer","className":"page-module___8aEwW__secondary","children":"Read our docs"}]]}]]}],["$","footer",null,{"className":"page-module___8aEwW__footer","children":[["$","a",null,{"href":"https://nextjs.org/learn?utm_source=create-next-appu0026utm_medium=appdir-templateu0026utm_campaign=create-next-app","target":"_blank","rel":"noopener noreferrer","children":[["$","$L4",null,{"aria-hidden":true,"src":"/file.svg","alt":"File icon","width":16,"height":16}],"Learn"]}],["$","a",null,{"href":"https://vercel.com/templates?framework=next.jsu0026utm_source=create-next-appu0026utm_medium=appdir-templateu0026utm_campaign=create-next-app","target":"_blank","rel":"noopener noreferrer","children":[["$","$L4",null,{"aria-hidden":true,"src":"/window.svg","alt":"Window icon","width":16,"height":16}],"Examples"]}],["$","a",null,{"href":"https://nextjs.org?utm_source=create-next-appu0026utm_medium=appdir-templateu0026utm_campaign=create-next-app","target":"_blank","rel":"noopener noreferrer","children":[["$","$L4",null,{"aria-hidden":true,"src":"/globe.svg","alt":"Globe icon","width":16,"height":16}],"Go to nextjs.org →"]}]]}]]}],[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/f560a0e155787fad.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/4fcaf8c2a7d2dfb4.js","async":true,"nonce":"$undefined"}]],["$","$L5",null,{"children":["$L6",["$","$L7",null,{"promise":"$@8"}]]}]]}],{},null,false]},null,false],["$","$1","h",{"children":[null,[["$","$L9",null,{"children":"$La"}],["$","meta",null,{"name":"next-size-adjust","content":""}]],["$","$Lb",null,{"children":["$","div",null,{"hidden":true,"children":["$","$c",null,{"fallback":null,"children":"$Ld"}]}]}]]}],false]],"m":"$undefined","G":["$e",["$Lf"]],"s":false,"S":true}n"])
</script>
<script>
self.__next_f.push([1,"f:["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/c488c4f98c6ae379.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]n"])
</script>
<script>
self.__next_f.push([1,"a:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]n6:nulln"])
</script>
<script>
self.__next_f.push([1,"10:I[27201,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/7dd66bdf8a7e5707.js"],"IconMark"]n8:{"metadata":[["$","title","0",{"children":"Create Next App"}],["$","meta","1",{"name":"description","content":"Generated by create next app"}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.0b3bf435.ico","sizes":"256x256","type":"image/x-icon"}],["$","$L10","3",{}]],"error":null,"digest":"$undefined"}n"])
</script>
<script>
self.__next_f.push([1,"d:"$8:metadata"n"])
</script>
Assistant
Thanks for the HTML dump—that explains it. Your page is using **absolute URLs** like `href="/_next/…css"` and `src="/next.svg"`. That works on a real domain (root `/` exists), but **fails inside an APK/WebView (file://)** because there’s no site root.

You have two clean options. Pick one:

# Option A — No web server in the app (make assets relative)
1) Use this Next config:

// next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  output: "export",
  images: { unoptimized: true },
  assetPrefix: "./",      // make Next’s CSS/JS/font paths relative
  trailingSlash: true,    // generates folder/index.html (works better with relative links)
};
export default nextConfig;

2) Fix **public assets** you reference yourself (Next won’t rewrite these):
– Change `src="/next.svg"` → `src="next.svg"`
– Change `src="/vercel.svg"` → `src="vercel.svg"`
– Change `href="/favicon.ico"` → `href="favicon.ico"`
– Any other `/something.ext` → `something.ext` (remove the leading slash)

3) Prefer `next/image` with imports for anything in `public/`:

import logo from "@/public/next.svg";
import Image from "next/image";
<Image src={logo} alt="Next.js" width={180} height={38} />

^ This ensures build-time URLs that respect `assetPrefix`.

4) Rebuild fresh:

rm -rf .next out && npm run build

Package the **entire** `out/` including the `_next/` folder into the APK.

# Option B — Keep absolute URLs, run a tiny local server in the app
If you’d rather not touch paths, start a local HTTP server (e.g., `http://localhost:8080/`) inside the app and serve the `out/` folder. Then absolute paths like `/_next/…` and `/next.svg` work as-is.

– Capacitor: use `@ionic-enterprise/cordova-httpd` or similar local server plugin.
– Cordova: `cordova-plugin-httpd` or any embedded server.
– Point your WebView to `http://localhost:8080/index.html`.

## Quick sanity checks for your case
– In your HTML, I see:
– “ (absolute → fix via `assetPrefix: "./"`)
– “, “, “ (absolute → remove leading `/`)
– Ensure the `_next/` directory isn’t accidentally excluded during APK packaging.

If you tell me which route you prefer (relative paths vs. local server), I’ll give you the exact file edits for your project (e.g., how to change links in `app/layout.tsx` and `public/*` usage).

Leave a Comment

Your email address will not be published. Required fields are marked *