Skip to content

Commit 5f8bd07

Browse files
authored
docs: add Next.js Deno build troubleshooting (#3395)
1 parent 318ecce commit 5f8bd07

2 files changed

Lines changed: 84 additions & 5 deletions

File tree

deploy/reference/frameworks.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
last_modified: 2026-02-11
2+
last_modified: 2026-07-07
33
title: Frameworks
44
description: "Detailed guide to supported JavaScript and TypeScript frameworks in Deno Deploy, including Next.js, Astro, Nuxt, SvelteKit, and more."
55
---
@@ -40,6 +40,50 @@ Next.js on Deno Deploy always builds in standalone mode.
4040
Tracing is supported out of the box, and Next.js automatically emits some spans
4141
for incoming requests, routing, rendering, and other operations.
4242

43+
#### Deno compatibility notes
44+
45+
Next.js projects run on Deno Deploy through Deno's Node and npm compatibility
46+
layer. Most Next.js apps work without extra changes, but the following issues
47+
can show up in projects generated by scaffolding tools or coding agents:
48+
49+
- Prefer `next.config.mjs` with `export default` for the broadest Next.js
50+
version compatibility. If you are using Next.js 15 or newer, `next.config.ts`
51+
with `export default` is also supported. Deno's `detect-cjs` option helps
52+
CommonJS `next.config.js` files, but some Next.js versions and loaders can
53+
still report a "module is not defined" error when a config is loaded as ESM.
54+
Using an ESM config avoids that ambiguity.
55+
- Some Next.js versions can crash during the lint/type-check phase under Deno
56+
with `Cannot read properties of undefined (reading 'bold')`. Until this is
57+
fixed upstream, you can unblock the build by setting
58+
`typescript.ignoreBuildErrors` and `eslint.ignoreDuringBuilds` in your Next.js
59+
config. Because this skips Next.js's build-time checks, keep running type
60+
checking and linting separately in CI.
61+
- App Router pages are still prerendered at build time when Next.js decides they
62+
are static. If a client component calls browser-only hooks or APIs, defer that
63+
code until after the component mounts, such as in `useEffect`. If you need to
64+
disable SSR with `next/dynamic` and `{ ssr: false }`, put the dynamic import
65+
in a Client Component wrapper; Server Components cannot use `{ ssr: false }`
66+
directly. Marking the route dynamic is not enough: dynamic routes still render
67+
on the server, where browser globals are undefined.
68+
69+
Example `next.config.mjs`:
70+
71+
```js title="next.config.mjs"
72+
/** @type {import('next').NextConfig} */
73+
const nextConfig = {
74+
typescript: {
75+
// Workaround for known Next.js-on-Deno build-time type-check crashes.
76+
ignoreBuildErrors: true,
77+
},
78+
eslint: {
79+
// Keep linting in CI while allowing `next build` to complete on Deno.
80+
ignoreDuringBuilds: true,
81+
},
82+
};
83+
84+
export default nextConfig;
85+
```
86+
4387
### Astro (`astro`)
4488

4589
Astro is a web framework for building content-driven websites like blogs,

examples/tutorials/next.md

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
last_modified: 2026-06-16
2+
last_modified: 2026-07-07
33
title: "Build a Next.js App"
44
description: "Walkthrough guide to building a Next.js application with Deno. Learn how to set up a project, create API routes, implement server-side rendering, and build a full-stack TypeScript application."
55
url: /examples/next_tutorial/
@@ -57,6 +57,23 @@ compatibility, update your `deno.json` file with the following configuration:
5757
}
5858
```
5959

60+
Next.js reads `next.config.*` during local and Deploy builds. With Deno, prefer
61+
an ESM config file named `next.config.mjs`. Current Next.js releases also
62+
support `next.config.ts` with the same `export default` shape:
63+
64+
```js title="next.config.mjs"
65+
/** @type {import('next').NextConfig} */
66+
const nextConfig = {};
67+
68+
export default nextConfig;
69+
```
70+
71+
If you started from a scaffold that generated `next.config.js` with
72+
`module.exports`, Deno's `detect-cjs` option usually lets that CommonJS config
73+
work. If you still see `module is not defined`, or if a tool loads the config as
74+
an ES module, rename it to `next.config.mjs` and use `export default` as shown
75+
above.
76+
6077
Now install the dependencies found in the package.json:
6178

6279
```sh
@@ -178,9 +195,9 @@ export type Dino = { name: string; description: string };
178195
We'll update the `page.tsx` file in the `app` directory to fetch the dinosaur
179196
data from our API and display it as a list of links.
180197

181-
To execute client-side code in Next.js we need to use the `use Client` directive
182-
at the top of the file. Then we'll import the modules that we'll need in this
183-
page and export the default function that will render the page:
198+
To execute client-side code in Next.js we need to use the `"use client"`
199+
directive at the top of the file. Then we'll import the modules that we'll need
200+
in this page and export the default function that will render the page:
184201

185202
```tsx title="page.tsx"
186203
"use client";
@@ -302,6 +319,24 @@ details!
302319
Now that you have your working Next.js app, you can deploy it to the web with
303320
Deno Deploy.
304321

322+
:::tip Build troubleshooting
323+
324+
If `next build` fails on Deno with
325+
`Cannot read properties of undefined (reading 'bold')`, the failure is in
326+
Next.js's build-time lint/type-check pass. A temporary workaround is to add
327+
`typescript.ignoreBuildErrors` and `eslint.ignoreDuringBuilds` to
328+
`next.config.mjs`, then run type checking and linting separately in CI.
329+
330+
If a client component uses browser-only hooks or APIs, Next.js may still try to
331+
render it on the server during prerendering or SSR. Defer that code until after
332+
the component mounts, such as in `useEffect`. If you need to disable SSR with
333+
`next/dynamic` and `{ ssr: false }`, put the dynamic import in a Client
334+
Component wrapper; Server Components cannot use `{ ssr: false }` directly.
335+
Marking the route dynamic alone is not enough because dynamic routes still
336+
render on the server, where browser globals are undefined.
337+
338+
:::
339+
305340
For the best experience, you can deploy your app directly from GitHub, which
306341
will set up automated deployments. Create a GitHub repository and push your app
307342
there.

0 commit comments

Comments
 (0)