---
title: "Migrate to Netlify from Vercel"
description: "Move a site from Vercel to Netlify, including build settings, environment variables, redirects, headers, functions, and DNS cutover."
source: "https://www.netlify.com/knowledge-base/migrate-to-netlify-from-vercel/"
last_updated: "2026-07-24T12:54:38.000Z"
---
Most of a Vercel project maps onto Netlify with small, mechanical changes: build settings move to `netlify.toml`, `vercel.json` redirects become `_redirects` rules, and functions keep the same Web `Request`/`Response` handler you already wrote. This guide walks through each piece in the order you should tackle it, gathering the config from Vercel first and setting it up on Netlify second.

There is no one-click importer. You can translate the configuration by hand, or ask an AI coding agent to do it for you. For a typical site that takes a couple of hours; for a large app with custom middleware and dozens of functions, plan a day and test on a preview URL before you move DNS.

Work through the sections in this order:

1.  [Create the Netlify site](#1-create-the-netlify-site)
2.  [Build settings](#2-build-settings)
3.  [Environment variables](#3-environment-variables)
4.  [Redirects and rewrites](#4-redirects-and-rewrites)
5.  [Custom headers](#5-custom-headers)
6.  [Functions](#6-functions)
7.  [Middleware and edge functions](#7-middleware-and-edge-functions)
8.  [Next.js specifics](#8-nextjs-specifics)
9.  [Custom domains and DNS cutover](#9-custom-domains-and-dns-cutover)

## 1\. Create the Netlify site

Connect your Git repository first, before you touch any configuration. In Netlify, choose **Add new site**, then **Import an existing project**, and pick your repo. Netlify connects to GitHub, GitLab, Bitbucket, and Azure DevOps ([Git workflows](https://docs.netlify.com/build/git-workflows/overview/)).

Netlify detects most frameworks and pre-fills the build command and publish directory. You will confirm those in the next step. Every push now builds a deploy, and every pull request gets its own [Deploy Preview](https://docs.netlify.com/deploy/deploy-types/deploy-previews/), the same way Vercel’s preview deployments work.

## 2\. Build settings

**Gather from Vercel.** In your Vercel project settings, note the Build Command, Output Directory, and Root Directory. If you keep a `vercel.json`, check it for a `buildCommand` and `outputDirectory`.

**Set up on Netlify.** Put the equivalent in a `netlify.toml` file at the repository root ([file-based configuration](https://docs.netlify.com/build/configure-builds/file-based-configuration/)):

```
[build]  base = ""            # Root Directory, if your app lives in a subfolder  command = "npm run build"  publish = "dist"     # Vercel's Output Directory
```

Vercel’s Output Directory maps to Netlify’s `publish`. For a monorepo, set `base` to the app’s subfolder.

## 3\. Environment variables

**Gather from Vercel.** Export your variables from the Vercel project’s Environment Variables page. Note which values are scoped to Production, Preview, or Development.

**Set up on Netlify.** Add them in the UI under **Site configuration**, then **Environment variables**, or import a `.env` file with the CLI:

```
netlify env:import .env
```

Netlify scopes variables by [deploy context](https://docs.netlify.com/build/environment-variables/overview/): production, deploy previews, and branch deploys (including wildcards like `release/*`). Map Vercel’s Preview scope to Netlify’s deploy-preview context. Set secrets and runtime values in the UI or CLI, where you can scope them by context; `netlify.toml` values apply at build time, so keep non-secret build defaults there.

## 4\. Redirects and rewrites

**Gather from Vercel.** Collect the `redirects` and `rewrites` arrays from `vercel.json` (or the `redirects()`/`rewrites()` functions in `next.config.js`). Each entry has a `source`, a `destination`, and, for redirects, a `permanent` flag.

**Set up on Netlify.** Netlify uses one mechanism for both. A rule with status `301` redirects; a rule with status `200` rewrites, keeping the URL in the bar while serving different content ([redirects overview](https://docs.netlify.com/manage/routing/redirects/overview/)). Add them to `netlify.toml`:

```
[[redirects]]  from = "/old-path"  to = "/new-path"  status = 301        # permanent redirect (Vercel's permanent: true)
[[redirects]]  from = "/api/*"  to = "/.netlify/functions/:splat"  status = 200        # rewrite (Vercel's rewrites)
```

Wildcards (`*`) and named parameters (`:slug`) work the way splats and dynamic segments do on Vercel. Netlify processes a `_redirects` file before `netlify.toml`, and the first matching rule wins.

## 5\. Custom headers

**Gather from Vercel.** Copy the `headers` array from `vercel.json` (or `next.config.js`), including any `source` path matching.

**Set up on Netlify.** Use `[[headers]]` tables in `netlify.toml` or a `_headers` file ([headers docs](https://docs.netlify.com/manage/routing/headers/)):

```
[[headers]]  for = "/*"  [headers.values]    X-Frame-Options = "DENY"    Cache-Control = "public, max-age=0, must-revalidate"
```

## 6\. Functions

Your handler code ports with little change. Both platforms now use standard Web `Request` and `Response` objects.

**Gather from Vercel.** Vercel functions live in an `api/` directory. Note the runtime each one targets.

**Set up on Netlify.** Move them to `netlify/functions/` ([Functions overview](https://docs.netlify.com/build/functions/overview/)). A modern Netlify function looks like this:

```
import type { Config, Context } from '@netlify/functions';
export default async (req: Request, context: Context) => {  return new Response('Hello from Netlify');};
export const config: Config = {  path: '/api/hello',};
```

The handler body is the same Web-standard code you would write on Vercel. The `config` export with a `path` replaces Vercel’s file-path routing and lets you serve the function at a clean URL. Netlify Functions run JavaScript/TypeScript and Go; Edge Functions (next section) run on Deno.

## 7\. Middleware and edge functions

**Gather from Vercel.** Vercel puts middleware in a single `middleware.ts` at the project root, with an exported `config.matcher`.

**Set up on Netlify.** Netlify edge functions serve the same role: they intercept and transform requests at the edge on a Deno runtime ([Edge Functions overview](https://docs.netlify.com/build/edge-functions/overview/)). Place them in `netlify/edge-functions/`:

```
import type { Config, Context } from '@netlify/edge-functions';
export default async (request: Request, context: Context) => {  // rewrite, redirect, or add headers at the edge  return context.next();};
export const config: Config = { path: '/*' };
```

The `path` in `config` replaces Vercel’s `matcher`.

## 8\. Next.js specifics

Netlify runs Next.js on the [OpenNext adapter](https://opennext.js.org/netlify), an open-source runtime that Netlify co-maintains ([Next.js on Netlify](https://docs.netlify.com/build/frameworks/framework-setup-guides/nextjs/overview/)). Because the adapter is open source, your Next.js app does not depend on a single vendor’s proprietary runtime to deploy and run.

What carries over:

-   **App Router and Pages Router** both work, no config needed. Netlify supports Next.js 13.5 and up on the OpenNext adapter and detects it automatically; older versions fall back to the legacy runtime.
-   **Incremental Static Regeneration** is supported, including on-demand, time-based, tag-based, and path-based revalidation.
-   **`next/image`** optimization runs through the [Netlify Image CDN](https://docs.netlify.com/build/image-cdn/overview/) by default.
-   **Middleware** runs as an edge function.

A few honest limitations to check before you cut over: rewrites cannot target files in `public/`, Node middleware does not expose C++ addons or the filesystem API, and Netlify Forms needs extra wiring with Next.js. Vercel remains the reference implementation for the newest Next.js edge features, so test any bleeding-edge feature on a Netlify preview first.

## 9\. Custom domains and DNS cutover

Do this last, once the site builds and works on its `netlify.app` URL and a Deploy Preview. This keeps downtime near zero.

1.  In Netlify, add your custom domain under [domain management](https://docs.netlify.com/manage/domains/get-started-with-domains/).
2.  Keep your DNS where it is and point records at Netlify ([external DNS](https://docs.netlify.com/manage/domains/configure-domains/configure-external-dns/)):
    -   Apex domain: an `ALIAS`, `ANAME`, or flattened `CNAME` to `apex-loadbalancer.netlify.com`, or an `A` record to `75.2.60.5`.
    -   Subdomain (like `www`): a `CNAME` to `your-site.netlify.app`.
3.  Netlify provisions a free [Let’s Encrypt](https://letsencrypt.org/) TLS certificate automatically once DNS validates. HTTPS needs no manual setup.

DNS propagation can take up to 48 hours, though most records update within an hour. Because Vercel still serves the old records until propagation completes, visitors reach one platform or the other throughout, never an error page. Once traffic has shifted and you have watched it for a day, remove the domain from Vercel.

## What you gain, and what to weigh

Netlify’s genuine advantages after a move:

-   **No framework lock-in.** Next.js runs on the open-source OpenNext adapter, and functions use Web-standard handlers, so your code stays portable.
-   **Deploy Previews on four Git providers**, not just GitHub.
-   **Commercial use allowed on the free plan**, where Vercel’s Hobby tier is personal, non-commercial use only.

Weigh these fairly against the tradeoffs. Netlify moved to [credit-based pricing](https://www.netlify.com/pricing/) (the Free plan includes 300 credits per month), which some teams find harder to forecast than flat tiers, and Vercel ships the newest Next.js edge features first. Test your specific app on a preview before you commit.

## Resources

-   [netlify.toml file-based configuration](https://docs.netlify.com/build/configure-builds/file-based-configuration/)
-   [Redirects and rewrites](https://docs.netlify.com/manage/routing/redirects/overview/)
-   [Functions overview](https://docs.netlify.com/build/functions/overview/)
-   [Next.js on Netlify](https://docs.netlify.com/build/frameworks/framework-setup-guides/nextjs/overview/)
-   [Netlify CLI](https://cli.netlify.com/)