gavmac00/nextjs-app-docs huggingface dataset:
TypeScript
Next.js provides a TypeScript-first development experience for building your React application.
It comes with built-in TypeScript support for automatically installing the necessary packages and configuring the proper settings.
As well as a TypeScript Plugin for your editor.
🎥 Watch: Learn about the built-in TypeScript plugin → YouTube (3 minutes)
New Projects
create-next-app now ships with TypeScript by default.
Terminal npx create-next-app@latest
Existing Projects
Add TypeScript to your project by renaming a file to .ts / .tsx. Run next dev and next build to automatically install the necessary dependencies and add a tsconfig.json file with the recommended config options.
If you already had a jsconfig.json file, copy the paths compiler option from the old jsconfig.json into the new tsconfig.json file, and delete the old jsconfig.json file.
TypeScript Plugin
TypeScript Plugin
Next.js includes a custom TypeScript plugin and type checker, which VSCode and other code editors can use for advanced type-checking and auto-completion.You can enable the plugin in VS Code by:
Opening the command palette (Ctrl/⌘ + Shift + P)
Searching for "TypeScript: Select TypeScript Version"
Selecting "Use Workspace Version"
Now, when editing files, the custom plugin will be enabled. When running next build, the custom type checker will be used.Plugin Features
The TypeScript plugin can help with:
Warning if the invalid values for segment config options are passed.
Showing available options and in-context documentation.
Ensuring the use client directive is used correctly.
Ensuring client hooks (like useState) are only used in Client Components.
Good to know: More features will be added in the future.
Minimum TypeScript Version
Good to know: More features will be added in the future.
Minimum TypeScript Version
It is highly recommended to be on at least v4.5.2 of TypeScript to get syntax features such as type modifiers on import names and performance improvements.
Statically Typed Links
Next.js can statically type links to prevent typos and other errors when using next/link, improving type safety when navigating between pages.To opt-into this feature, experimental.typedRoutes need to be enabled and the project needs to be using TypeScript.next.config.js /** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    typedRoutes: true,
  },
}
experimental: {
    typedRoutes: true,
  },
}
 
module.exports = nextConfigNext.js will generate a link definition in .next/types that contains information about all existing routes in your application, which TypeScript can then use to provide feedback in your editor about invalid links.Currently, experimental support includes any string literal, including dynamic segments. For non-literal strings, you currently need to manually cast the href with as Route: import type { Route } from 'next';
import Link from 'next/link'
 
// No TypeScript errors if href is a valid route
<Link href="/about" />
<Link href="/blog/nextjs" />
<Link href={`/blog/${slug}`} />
<Link href={('/blog' + slug) as Route} />
 
// TypeScript errors if href is not a valid route
// TypeScript errors if href is not a valid route
<Link href="/aboot" />To accept href in a custom component wrapping next/link, use a generic: import type { Route } from 'next'
import Link from 'next/link'
 
function Card<T extends string>({ href }: { href: Route<T> | URL }) {
  return (
    <Link href={href}>
      <div>My Card</div>
    </Link>
  )
}
How does it work?
When running next dev or next build, Next.js generates a hidden .d.ts file inside .next that contains information about all existing routes in your application (all valid routes as the href type of Link). This .d.ts file is included in tsconfig.json and the TypeScript compiler will check that .d.ts and provide feedback in your editor about invalid links.
End-to-End Type Safety
End-to-End Type Safety
Next.js 13 has enhanced type safety. This includes:
No serialization of data between fetching function and page: You can fetch directly in components, layouts, and pages on the server. This data does not need to be serialized (converted to a string) to be passed to the client side for consumption in React. Instead, since app uses Server Components by default, we can use values like Date, Map, Set, and more without any extra steps. Previously, you needed to manually type the boundary between server and client with Next.js-specific types.
Streamlined data flow between components: With the removal of _app in favor of root layouts, it is now easier to visualize the data flow between components and pages. Previously, data flowing between individual pages and _app were difficult to type and could introduce confusing bugs. With colocated data fetching in Next.js 13, this is no longer an issue.
Data Fetching in Next.js now provides as close to end-to-end type safety as possible without being prescriptive about your database or content provider selection.We're able to type the response data as you would expect with normal TypeScript. For example:app/page.tsx async function getData() {
  const res = await fetch('https://api.example.com/...')
  // The return value is *not* serialized
  // You can return Date, Map, Set, etc.
  return res.json()
}
 
export default async function Page() {
  const name = await getData()
 
  return '...'
}For complete end-to-end type safety, this also requires your database or content provider to support TypeScript. This could be through using an ORM or type-safe query builder.Async Server Component TypeScript Error
To use an async Server Component with TypeScript, ensure you are using TypeScript 5.1.3 or higher and @types/react 18.2.8 or higher.If you are using an older version of TypeScript, you may see a 'Promise<Element>' is not a valid JSX element type error. Updating to the latest version of TypeScript and @types/react should resolve this issue.Passing Data Between Server & Client Components
When passing data between a Server and Client Component through props, the data is still serialized (converted to a string) for use in the browser. However, it does not need a special type. It’s typed the same as passing any other props between components.Further, there is less code to be serialized, as un-rendered data does not cross between the server and client (it remains on the server). This is only now possible through support for Server Components.
Path aliases and baseUrl
Path aliases and baseUrl
Next.js automatically supports the tsconfig.json "paths" and "baseUrl" options.
You can learn more about this feature on the Module Path aliases documentation.
Type checking next.config.js
The next.config.js file must be a JavaScript file as it does not get parsed by Babel or TypeScript, however you can add some type checking in your IDE using JSDoc as below:
 // @ts-check
 
/**
 * @type {import('next').NextConfig}
 **/
const nextConfig = {
  /* config options here */
}
 
module.exports = nextConfig
Incremental type checking
Since v10.2.1 Next.js supports incremental type checking when enabled in your tsconfig.json, this can help speed up type checking in larger applications.
Ignoring TypeScript Errors
Next.js fails your production build (next build) when TypeScript errors are present in your project.
Next.js fails your production build (next build) when TypeScript errors are present in your project.
If you'd like Next.js to dangerously produce production code even when your application has errors, you can disable the built-in type checking step.
If disabled, be sure you are running type checks as part of your build or deploy process, otherwise this can be very dangerous.
Open next.config.js and enable the ignoreBuildErrors option in the typescript config:
next.config.js module.exports = {
  typescript: {
    // !! WARN !!
    // Dangerously allow production builds to successfully complete even if
    // your project has type errors.
    // !! WARN !!
    ignoreBuildErrors: true,
  },
}
Version Changes
ignoreBuildErrors: true,
  },
}
Version Changes
VersionChangesv13.2.0Statically typed links are available in beta.v12.0.0SWC is now used by default to compile TypeScript and TSX for faster builds.v10.2.1Incremental type checking support added when enabled in your tsconfig.json.
Environment Variables
Examples
Environment Variables
Next.js comes with built-in support for environment variables, which allows you to do the following:
Use .env.local to load environment variables
Bundle environment variables for the browser by prefixing with NEXT_PUBLIC_
Loading Environment Variables
Next.js has built-in support for loading environment variables from .env.local into process.env.
.env.local DB_HOST=localhost
DB_USER=myuser
DB_PASS=mypassword
This loads process.env.DB_HOST, process.env.DB_USER, and process.env.DB_PASS into the Node.js environment automatically allowing you to use them in Route Handlers.For example:app/api/route.js export async function GET() {
  const db = await myDB.connect({
    host: process.env.DB_HOST,
    username: process.env.DB_USER,
    password: process.env.DB_PASS,
  })
  // ...
}
Referencing Other Variables
})
  // ...
}
Referencing Other Variables
Next.js will automatically expand variables that use $ to reference other variables e.g. $VARIABLE inside of your .env* files. This allows you to reference other secrets. For example:
.env TWITTER_USER=nextjs
TWITTER_URL=https://twitter.com/$TWITTER_USER
In the above example, process.env.TWITTER_URL would be set to https://twitter.com/nextjs.
Good to know: If you need to use variable with a $ in the actual value, it needs to be escaped e.g. \$.
Bundling Environment Variables for the Browser
Non-NEXT_PUBLIC_ environment variables are only available in the Node.js environment, meaning they aren't accessible to the browser (the client runs in a different environment).
In order to make the value of an environment variable accessible in the browser, Next.js can "inline" a value, at build time, into the js bundle that is delivered to the client, replacing all references to process.env.[variable] with a hard-coded value. To tell it to do this, you just have to prefix the variable with NEXT_PUBLIC_. For example:
Terminal NEXT_PUBLIC_ANALYTICS_ID=abcdefghijk
This will tell Next.js to replace all references to process.env.NEXT_PUBLIC_ANALYTICS_ID in the Node.js environment with the value from the environment in which you run next build, allowing you to use it anywhere in your code. It will be inlined into any JavaScript sent to the browser.
Note: After being built, your app will no longer respond to changes to these environment variables. For instance, if you use a Heroku pipeline to promote slugs built in one environment to another environment, or if you build and deploy a single Docker image to multiple environments, all NEXT_PUBLIC_ variables will be frozen with the value evaluated at build time, so these values need to be set appropriately when the project is built. If you need access to runtime environment values, you'll have to setup your own API to provide them to the client (either on demand or during initialization).
pages/index.js import setupAnalyticsService from '../lib/my-analytics-service'
 
// 'NEXT_PUBLIC_ANALYTICS_ID' can be used here as it's prefixed by 'NEXT_PUBLIC_'.
// It will be transformed at build time to `setupAnalyticsService('abcdefghijk')`.
setupAnalyticsService(process.env.NEXT_PUBLIC_ANALYTICS_ID)
 
function HomePage() {
function HomePage() {
  return <h1>Hello World</h1>
}
 
export default HomePage
Note that dynamic lookups will not be inlined, such as:
 // This will NOT be inlined, because it uses a variable
const varName = 'NEXT_PUBLIC_ANALYTICS_ID'
setupAnalyticsService(process.env[varName])
 
// This will NOT be inlined, because it uses a variable
const env = process.env
setupAnalyticsService(env.NEXT_PUBLIC_ANALYTICS_ID)
Default Environment Variables
In general only one .env.local file is needed. However, sometimes you might want to add some defaults for the development (next dev) or production (next start) environment.
Next.js allows you to set defaults in .env (all environments), .env.development (development environment), and .env.production (production environment).
.env.local always overrides the defaults set.
.env.local always overrides the defaults set.
Good to know: .env, .env.development, and .env.production files should be included in your repository as they define defaults. .env*.local should be added to .gitignore, as those files are intended to be ignored. .env.local is where secrets can be stored.
Environment Variables on Vercel
When deploying your Next.js application to Vercel, Environment Variables can be configured in the Project Settings.
All types of Environment Variables should be configured there. Even Environment Variables used in Development – which can be downloaded onto your local device afterwards.
If you've configured Development Environment Variables you can pull them into a .env.local for usage on your local machine using the following command:
Terminal vercel env pull .env.local
Test Environment Variables
Terminal vercel env pull .env.local
Test Environment Variables
Apart from development and production environments, there is a 3rd option available: test. In the same way you can set defaults for development or production environments, you can do the same with a .env.test file for the testing environment (though this one is not as common as the previous two). Next.js will not load environment variables from .env.development or .env.production in the testing environment.
This one is useful when running tests with tools like jest or cypress where you need to set specific environment vars only for testing purposes. Test default values will be loaded if NODE_ENV is set to test, though you usually don't need to do this manually as testing tools will address it for you.
There is a small difference between test environment, and both development and production that you need to bear in mind: .env.local won't be loaded, as you expect tests to produce the same results for everyone. This way every test execution will use the same env defaults across different executions by ignoring your .env.local (which is intended to override the default set).
Good to know: similar to Default Environment Variables, .env.test file should be included in your repository, but .env.test.local shouldn't, as .env*.local are intended to be ignored through .gitignore.
While running unit tests you can make sure to load your environment variables the same way Next.js does by leveraging the loadEnvConfig function from the @next/env package.
 // The below can be used in a Jest global setup file or similar for your testing set-up
import { loadEnvConfig } from '@next/env'
 
export default async () => {
export default async () => {
  const projectDir = process.cwd()
  loadEnvConfig(projectDir)
}
Environment Variable Load Order
Environment variables are looked up in the following places, in order, stopping once the variable is found.
process.env
.env.$(NODE_ENV).local
.env.local (Not checked when NODE_ENV is test.)
.env.$(NODE_ENV)
.env
For example, if NODE_ENV is development and you define a variable in both .env.development.local and .env, the value in .env.development.local will be used.
Good to know: The allowed values for NODE_ENV are production, development and test.
Good to know
If you are using a /src directory, .env.* files should remain in the root of your project.
If the environment variable NODE_ENV is unassigned, Next.js automatically assigns development when running the next dev command, or production for all other commands.
Static Exports
Next.js enables starting as a static site or Single-Page Application (SPA), then later optionally upgrading to use features that require a server.
When running next build, Next.js generates an HTML file per route. By breaking a strict SPA into individual HTML files, Next.js can avoid loading unnecessary JavaScript code on the client-side, reducing the bundle size and enabling faster page loads.
Since Next.js supports this static export, it can be deployed and hosted on any web server that can serve HTML/CSS/JS static assets.
Configuration
To enable a static export, change the output mode inside next.config.js:
next.config.js /**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  output: 'export',
  // Optional: Add a trailing slash to all paths `/about` -> `/about/`
  // trailingSlash: true,
// trailingSlash: true,
  // Optional: Change the output directory `out` -> `dist`
  // distDir: 'dist',
}
 
module.exports = nextConfig
After running next build, Next.js will produce an out folder which contains the HTML/CSS/JS assets for your application.
Supported Features
The core of Next.js has been designed to support static exports.Server Components
When you run next build to generate a static export, Server Components consumed inside the app directory will run during the build, similar to traditional static-site generation.The resulting component will be rendered into static HTML for the initial page load and a static payload for client navigation between routes. No changes are required for your Server Components when using the static export, unless they consume dynamic server functions.app/page.tsx export default async function Page() {
  // This fetch will run on the server during `next build`
// This fetch will run on the server during `next build`
  const res = await fetch('https://api.example.com/...')
  const data = await res.json()
 
  return <main>...</main>
}Client Components
If you want to perform data fetching on the client, you can use a Client Component with SWR to deduplicate requests.app/other/page.tsx 'use client'
 
import useSWR from 'swr'
 
const fetcher = (url: string) => fetch(url).then((r) => r.json())
 
export default function Page() {
  const { data, error } = useSWR(
    `https://jsonplaceholder.typicode.com/posts/1`,
    fetcher
  )
  if (error) return 'Failed to load'
  if (!data) return 'Loading...'
 
  return data.title
if (!data) return 'Loading...'
 
  return data.title
}Since route transitions happen client-side, this behaves like a traditional SPA. For example, the following index route allows you to navigate to different posts on the client:app/page.tsx import Link from 'next/link'
 
export default function Page() {
  return (
    <>
      <h1>Index Page</h1>
      <hr />
      <ul>
        <li>
          <Link href="/post/1">Post 1</Link>
        </li>
        <li>
          <Link href="/post/2">Post 2</Link>
        </li>
      </ul>
    </>
  )
}
Image Optimization
</ul>
    </>
  )
}
Image Optimization
Image Optimization through next/image can be used with a static export by defining a custom image loader in next.config.js. For example, you can optimize images with a service like Cloudinary:
next.config.js /** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'export',
  images: {
    loader: 'custom',
    loaderFile: './app/image.ts',
  },
}
 
module.exports = nextConfig
This custom loader will define how to fetch images from a remote source. For example, the following loader will construct the URL for Cloudinary:
app/image.ts export default function cloudinaryLoader({
  src,
  width,
  quality,
}: {
  src: string
  width: number
  quality?: number
}) {
src: string
  width: number
  quality?: number
}) {
  const params = ['f_auto', 'c_limit', `w_${width}`, `q_${quality || 'auto'}`]
  return `https://res.cloudinary.com/demo/image/upload/${params.join(
    ','
  )}${src}`
}
You can then use next/image in your application, defining relative paths to the image in Cloudinary:
app/page.tsx import Image from 'next/image'
 
export default function Page() {
  return <Image alt="turtles" src="/turtles.jpg" width={300} height={300} />
}
Route Handlers
}
Route Handlers
Route Handlers will render a static response when running next build. Only the GET HTTP verb is supported. This can be used to generate static HTML, JSON, TXT, or other files from dynamic or static data. For example:app/data.json/route.ts import { NextResponse } from 'next/server'
 
export async function GET() {
  return NextResponse.json({ name: 'Lee' })
}The above file app/data.json/route.ts will render to a static file during next build, producing data.json containing { name: 'Lee' }.If you need to read dynamic values from the incoming request, you cannot use a static export.Browser APIs
Client Components are pre-rendered to HTML during next build. Because Web APIs like window, localStorage, and navigator are not available on the server, you need to safely access these APIs only when running in the browser. For example: 'use client';
import { useEffect } from 'react';
 
export default function ClientComponent() {
  useEffect(() => {
    // You now have access to `window`
    console.log(window.innerHeight);
  }, [])
 
  return ...;
}
Unsupported Features
After enabling the static export output mode, all routes inside app are opted-into the following Route Segment Config: export const dynamic = 'error'With this configuration, your application will produce an error if you try to use server functions like headers or cookies, since there is no runtime server. This ensures local development matches the same behavior as a static export. If you need to use server functions, you cannot use a static export.The following additional dynamic features are not supported with a static export:
rewrites in next.config.js
redirects in next.config.js
headers in next.config.js
Middleware
Incremental Static Regeneration
Deploying
headers in next.config.js
Middleware
Incremental Static Regeneration
Deploying
With a static export, Next.js can be deployed and hosted on any web server that can serve HTML/CSS/JS static assets.
When running next build, Next.js generates the static export into the out folder. Using next export is no longer needed. For example, let's say you have the following routes:
/
/blog/[id]
After running next build, Next.js will generate the following files:
/out/index.html
/out/404.html
/out/blog/post-1.html
/out/blog/post-2.html
If you are using a static host like Nginx, you can configure rewrites from incoming requests to the correct files:
nginx.conf server {
  listen 80;
  server_name acme.com;
 
  root /var/www;
 
  location / {
      try_files /out/index.html =404;
location / {
      try_files /out/index.html =404;
  }
 
  location /blog/ {
      rewrite ^/blog/(.*)$ /out/blog/$1.html break;
  }
 
  error_page 404 /out/404.html;
  location = /404.html {
      internal;
  }
}
Version History
VersionChangesv13.4.0App Router (Stable) adds enhanced static export support, including using React Server Components and Route Handlers.v13.3.0next export is deprecated and replaced with "output": "export"