> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ohmyho.st/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> For account actions, read https://ohmyho.st/skills/ohmyhost-get-started/SKILL.md and use the authenticated ohmyho.st CLI or local product MCP. Mintlify search only reads documentation. Preserve the customer’s selected project, environment and authentication provider.

# Host a Next.js app

> Deploy ordinary Next.js routes with the capabilities your app uses.

Run `ohmyhost init --dry-run --json` in the Next.js project. Keep an exact package-manager version and one matching lockfile; resolve the concrete inspection output before planning a deployment.

## Supported versions and build

The admitted versions are Next.js `15.5.26` and newer patches in `15.5.x`, or `16.3.6–16.3.7`. The verified fixtures use `15.5.26` and `16.3.7`; other admitted versions are experimental. A `^` or `~` declaration is experimental, and its base and frozen installed version must be inside the admitted window. Pin exact `react` and `react-dom` versions and commit the matching package-manager lockfile.

Keep `scripts.build` as `next build`. The service supplies OpenNext `1.20.7` and adds `--webpack` for Next.js 16; Next.js 15 uses its normal build without that flag. Next.js 16 also accepts `next build --webpack`. Use one default-exported `next.config.js`, `.mjs` or `.ts`; do not set `output: standalone`, `output: export`, `cacheComponents: true` or a non-root `basePath` or `assetPrefix`.

The service-owned Next.js bundle uses `keep_names: false` to prevent injected name helpers from breaking browser scripts serialized by libraries. This setting is supplied by the platform; no customer Wrangler override is needed.

## Build-time static pages and cache limits

Pages and route responses prerendered during the build use an immutable cache carried with that deployment. Ordinary request-time rendering and route handlers remain available. A new deployment refreshes the cache. Time-based ISR, on-demand revalidation and Cache Components are unsupported; keep existing static pages when addressing a packaging error.

The private cache defaults to **32 MiB**. With CLI/MCP **0.1.28 or later**, add `build.ssg_cache_max_mib` to `ohmyhost.yaml` to select an integer from **1 to 64**. Keep your existing build settings, for example:

```yaml theme={null}
build:
  install: pnpm install --frozen-lockfile --ignore-scripts
  command: pnpm run build
  output: .open-next/assets
  ssg_cache_max_mib: 48
```

Use your repository's package manager and commands. Commit and push the change, then plan and deploy that commit.

* Ordinary public assets retain their separate **25 MiB** allowance.
* Each public asset or cache file is at most **10 MiB**; the combined asset inventory has at most **1,000 files**.
* The complete deployment archive is at most **30 MiB compressed** and **64 MiB expanded**, including cache, public files, Worker modules, migrations and archive metadata.

Selecting 64 MiB of cache capacity leaves those combined limits in place. Leave space for the rest of the deployment. Increase this setting only when the error names the private cache limit; an expanded-archive or public-asset error requires reducing that output.

Cache storage costs **0 credits per 100 MB-month**: its provider storage cost is zero, so cost plus 50% remains zero. Unused capacity is not charged. Normal build and Worker request/CPU charges still apply, including when a cached page executes Worker code. [Pricing](/pricing)

The cache payloads are private. Direct requests to their reserved paths must return 404; the application serves the rendered pages through their normal URLs.

## Keep the app portable

Use ordinary Next.js routes and configuration. The hosting service supplies its build adapter; do not create a customer Wrangler project merely to make deployment work. Private auth credentials and database access belong in the server runtime, not `NEXT_PUBLIC_` values.

Keep existing authentication unless you choose to replace it. Configure exact callback and logout URLs for the environment you are testing. [Application authentication](/application-auth) · [Runtime secrets](/secrets).

Hosted server code reads private bindings through `getCloudflareContext({ async: true }).env`. A localhost-only runtime factory is a test adapter, not a production backend. Preserve ordinary route handlers and use the [application database client](/database) and [private file client](/files) from that context.

For a library that uses WebAssembly, prefer a runtime-specific package export: a `workerd` entry can statically import the pinned `.wasm` modules, while a separate Node entry loads the same bytes locally. Preserve the library's license and real validation. The shared build pipeline carries validated Workers-compatible JavaScript, MJS and WASM modules for Next.js, TanStack Start edge, Vite edge companions and plain functions Workers. Auxiliary modules are at most 5 MiB each; the Worker and artifact budgets still apply. The immutable artifact keeps those modules together; a successful Node build alone does not prove the Worker module can start.

Scheduled work is declared as `functions.crons` and runs `scheduled` from the default export of `src/ohmyhost/worker.ts`, a module the platform bundles outside the Next.js build; see [Functions and cron](/functions).

Next.js SSR receives a fresh nonce on every rendered script/style tag; style attributes, event handlers and later client-created unnonced tags remain blocked. External connections/resources/frames/workers need explicit [browser declarations](/browser-security); media/microphone needs the server HTML opt-in.

## Images and themes under CSP

A nonce permits a script or style tag; it does not permit an inline `style` attribute. If an already unoptimized `next/image` component emits blocked inline styles, use a native image with the same URL, dimensions, classes and alternative text. Keep its loading behavior and put styling in the stylesheet:

```tsx theme={null}
<img
  src="/images/portrait.png"
  alt="Profile portrait"
  width={800}
  height={800}
  className="profile-portrait"
  loading="lazy"
  decoding="async"
/>
```

For an image that previously had priority loading, preserve that with `loading="eager"` and `fetchPriority="high"` instead of lazy loading.

Libraries that insert styles after hydration must use the trusted response nonce from `meta[property="csp-nonce"]`. For `next-themes` 0.4.6, read it before the provider's first client effect:

```tsx theme={null}
"use client";

import { useState } from "react";
import { ThemeProvider as NextThemesProvider } from "next-themes";
import type { ThemeProviderProps } from "next-themes";

export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
  const [documentNonce] = useState<string | undefined>(() => {
    if (typeof document === "undefined") return undefined;
    return document.head.querySelector<HTMLMetaElement>(
      'meta[property="csp-nonce"]',
    )?.content || undefined;
  });

  return (
    <NextThemesProvider {...props} nonce={props.nonce ?? documentNonce}>
      {children}
    </NextThemesProvider>
  );
}
```

Keep the app's system-theme, transition and native color-scheme settings. Waiting until an effect to supply the nonce can miss the library's first inserted style. Verify the initial theme, Light/Dark/System changes, client navigation and reloads without CSP or hydration errors. Keep the CSP strict; these adaptations require no `unsafe-inline` allowance.

## Files read by server code

The platform includes non-executable files recorded in Next.js output-file traces (`.nft.json`) as read-only data modules in the Worker. Use ordinary Node filesystem reads for those deployed files and keep them inside the application root. When Next cannot infer a dynamic filename, declare the required files with its normal `outputFileTracingIncludes` configuration. Missing or invalid traced files fail packaging, and data modules count toward the Worker size limits.

These runtime files receive no public URL from this mechanism. Files intentionally placed in `public/` still follow Next.js public-asset behavior. Do not bundle secrets as content; use [runtime secrets](/secrets). Runtime filesystem writes do not persist application data: use [files](/files) or the [database](/database).

## Compile MDX during the build

Workers does not support runtime code generation with `eval` or `new Function`. An MDX library that evaluates compiled strings at request time therefore needs a build-time integration, even if the same code works under local Node.js.

Compile MDX with `@mdx-js/mdx` using `outputFormat: "program"`, write ordinary ES modules and import them through a static component registry. Invoke the deterministic generator from the Next configuration so the build script stays `next build`. Keep the source JSON or MDX as the canonical content and preserve the application's component mapping, GFM plugins, links and embedded markup. Routes render the generated components without a runtime evaluator. The generator must also work in a fresh checkout.

## Verify after deployment

Check the landing page and every content route, including direct reloads, unknown URLs, images, feeds and sitemap where present. Check server behavior, application login and a real data operation where used, then inspect the browser for hydration or content-security errors and missing content. An admitted or successful build does not prove every Next.js feature. The inspection response distinguishes verified, experimental and unsupported capabilities.

Use the [portable-app Skill](https://ohmyho.st/skills/ohmyhost-build-portable-app/SKILL.md) for required source changes, then follow [your first deployment](/quickstart).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.