Skip to content

Migrate from Vercel to Netlify with an AI agent

Migrating a Vercel project to Netlify typically involves manual configuration changes, runtime adjustments, and careful mapping of platform-specific features. An AI agent workflow can automate this process, handling everything from directory structure to runtime conversions.

This guide demonstrates how to use a specialized AI prompt to migrate Vercel projects to Netlify, automatically addressing Edge Function runtime differences, API route mappings, environment variable syntax, and build configuration.

Before starting the migration, ensure you have:

  • Netlify CLI installed and authenticated (installation guide)
  • Access to your Vercel project repository with read/write permissions
  • An AI coding assistant that supports custom prompts (such as Windsurf, Cursor, or GitHub Copilot)
  • Node.js and npm for dependency management

The AI agent handles comprehensive cross-platform conversions:

VercelNetlifyNotes
/apinetlify/functionsServerless functions with Node runtime
/edgenetlify/edge-functionsEdge runtime (Deno-based)
Vercel ISROn-Demand Builders or Edge FunctionsRevalidation patterns
Vercel KV/Blob@netlify/blobsKey-value and blob storage
Vercel ImagesNetlify Image CDNAutomatic image optimization
Vercel CronScheduled FunctionsBackground jobs

Critical distinction: Vercel Edge Functions run on the Node.js runtime, while Netlify Edge Functions use Deno. The agent automatically:

  • Rewrites process.env to Netlify.env.get()
  • Converts Node-specific imports to Deno-compatible syntax
  • Adds node: prefix for built-in modules or uses URL imports
  • Updates function signatures to match Netlify conventions
  • Converts functions to .mts (ESM TypeScript) format

The agent creates or updates your netlify.toml with proper build settings:

[build]
command = "npm run build"
publish = ".next" # or "dist" depending on framework
[build.environment]
NODE_VERSION = "20"
[functions]
directory = "netlify/functions"
[build.edge_functions]
directory = "netlify/edge-functions"

Use this specialized migration prompt with your AI coding assistant. The prompt enforces Netlify conventions and handles platform differences:

task: migrate_project
description: >
Convert existing Vercel project to fully functional Netlify deployment.
Ensure total compliance with Netlify conventions and runtime.
REQUIREMENTS:
- must_build_with: netlify build
- must_deploy_with: netlify deploy
- must_pass_local_test: netlify dev
- runtime_edge: Deno (no Node-only syntax)
- runtime_functions: ESM + TypeScript (.mts)
- use_env: Netlify.env.get()
- never_use: process.env
- ensure_latest_next: true
mappings:
vercel_edge → netlify/edge-functions
vercel_api → netlify/functions
vercel_isr → on-demand builders or edge
vercel_kv_blob → @netlify/blobs
vercel_image → Netlify Image CDN
vercel_cron → scheduled functions
env → Netlify dashboard/CLI
directories:
functions: netlify/functions
edge: netlify/edge-functions
ignore: .netlify
dependencies:
- "@netlify/functions@latest"
- "@netlify/edge-functions@latest"
- "@netlify/blobs@latest"
netlify_toml:
build.command: npm run build
build.publish: .next or dist
functions.directory: netlify/functions
build.edge_functions: netlify/edge-functions
verify:
- npm install success
- netlify dev success
- all routes respond
- no syntax errors
- env accessible
notes:
- Edge uses Deno; adapt imports accordingly
- prefer URL imports or node: prefix
- no global side effects
- update Next.js versions if build fails
- doc_ref: https://docs.netlify.com/ai-context/netlify-development.mdc
  1. Open your Next.js Vercel project directory in an AI-powered code editor or navigate to your project directory in your terminal if using an AI coding assistant there.
  2. Provide the migration prompt to the AI assistant with instructions to migrate the project
  3. Let the agent analyze your project structure, dependencies, and Vercel-specific configurations

The agent will:

  • Scan your repository for Vercel-specific patterns
  • Identify API routes in /api or /pages/api
  • Detect Edge Functions in /edge directories
  • Read your vercel.json configuration
  • Map environment variables and build settings

The AI agent will make several categories of changes:

Terminal window
# Before (Vercel structure)
api/
hello.js
users.js
edge/
geolocation.js
# After (Netlify structure)
netlify/
functions/
hello.mts
users.mts
edge-functions/
geolocation.ts
// Before (Vercel)
const apiKey = process.env.API_KEY;
// After (Netlify Edge Function)
import { Config } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
const apiKey = Netlify.env.get("API_KEY");
// ... function logic
};
export const config: Config = {
path: "/api/geolocation"
};
// Before (Node.js imports)
import { parse } from 'url';
import crypto from 'crypto';
// After (Deno-compatible)
import { parse } from 'node:url';
import crypto from 'node:crypto';
// Or use Deno's built-in URL API

If your project uses Next.js, the agent may update to version 13.5+ to ensure compatibility with Netlify’s zero-configuration Next.js support:

{
"dependencies": {
"next": "^14.0.0"
}
}

After the agent completes its changes, install the required Netlify packages:

Terminal window
npm install @netlify/functions @netlify/edge-functions @netlify/blobs

Verify the migration with Netlify’s local development server:

Terminal window
# Start local development environment
netlify dev

This command:

  • Runs your build command
  • Starts the Netlify Dev server
  • Emulates Edge Functions and serverless functions
  • Provides access to environment variables

Test your routes:

  • Navigate to previously working Vercel endpoints
  • Verify Edge Function responses (e.g., geolocation)
  • Check API route functionality
  • Test form submissions if applicable

Once local testing succeeds, deploy to Netlify:

Terminal window
# Build for production
netlify build
# Deploy to production
netlify deploy --prod

The agent ensures your netlify.toml is configured correctly, so the deployment should succeed without additional configuration.

Netlify Edge Functions run on Deno, not Node.js. Key differences:

Import requirements:

// Correct: Use node: prefix for built-in modules
import { Buffer } from "node:buffer";
// Correct: Use URL imports for Deno modules
import { serve } from "https://deno.land/std/http/server.ts";
// Incorrect: Node-style imports won't work
import { Buffer } from "buffer";

Environment variables:

// Correct: Netlify environment API
const dbUrl = Netlify.env.get("DATABASE_URL");
// Incorrect: process.env not available in Deno
const dbUrl = process.env.DATABASE_URL;

No global side effects: Edge Functions should not have top-level side effects. Initialize within the handler function.

Netlify serverless functions use Node.js and support CommonJS or ESM:

// netlify/functions/api.mts
import type { Config } from "@netlify/functions";
export default async (req: Request) => {
const data = await fetch("https://api.example.com/data");
return new Response(JSON.stringify(await data.json()), {
headers: { "Content-Type": "application/json" }
});
};
export const config: Config = {
path: "/api/data"
};
  1. Export from Vercel: Download your environment variables from the Vercel dashboard
  2. Import to Netlify: Use the Netlify UI or CLI:
Terminal window
# Set individual variables
netlify env:set API_KEY "your-key-value"
# Import from .env file
netlify env:import .env
  1. Update code references: The AI agent should handle this, but verify all process.env references in Edge Functions are converted to Netlify.env.get()

Configure environment variable scopes for different contexts:

  • Production: Live site environment variables
  • Deploy Previews: Variables for pull request previews
  • Branch deploys: Branch-specific configurations

After migration, confirm:

  • Build succeeds: netlify build completes without errors
  • Local dev works: netlify dev runs and serves all routes
  • Functions respond: All API endpoints return expected responses
  • Edge Functions execute: Test edge routes (check headers, geo data, etc.)
  • Environment variables accessible: Verify all env vars load correctly
  • Images optimize: Confirm Netlify Image CDN processes images
  • Redirects work: Test redirect rules from netlify.toml or _redirects
  • Forms submit: If using forms, verify submissions work
  • No console errors: Check browser console and build logs

Next.js version mismatch:

Terminal window
# Update to supported version
npm install next@latest

Missing dependencies:

Terminal window
npm install @netlify/functions @netlify/edge-functions

Cache and dependency conflicts: If you encounter persistent build or installation errors, clear the cache and update packages:

Terminal window
# Clear npm cache
npm cache clean --force
# Remove node_modules and lock file
rm -rf node_modules package-lock.json
# Reinstall with latest versions
npm install

Edge Function errors (Deno):

  • Verify imports use node: prefix or URL imports
  • Check that no Node-only packages are imported
  • Ensure environment variables use Netlify.env.get()

Function timeout: Netlify Functions have a 10-second timeout (26 seconds for Pro plans). For long-running tasks, consider:

  • Background Functions for tasks up to 15 minutes
  • Splitting work across multiple function calls
  • Using Netlify Queues for asynchronous processing

If variables aren’t accessible:

  1. Verify they’re set in the Netlify dashboard for the correct deploy context
  2. Check that Edge Functions use Netlify.env.get() instead of process.env
  3. Confirm variable names match exactly (case-sensitive)

Example: Geolocation Edge Function migration

Section titled “Example: Geolocation Edge Function migration”

Here’s a real-world example of migrating a Vercel Edge Function that returns visitor geolocation:

// edge/geolocation.js
export const config = { runtime: 'edge' };
export default async function handler(request) {
const country = request.geo.country || 'Unknown';
const city = request.geo.city || 'Unknown';
return new Response(JSON.stringify({ country, city }), {
headers: { 'content-type': 'application/json' }
});
}
// netlify/edge-functions/geolocation.ts
import type { Config, Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
const country = context.geo?.country?.name || "Unknown";
const city = context.geo?.city || "Unknown";
return new Response(JSON.stringify({ country, city }), {
headers: { "content-type": "application/json" }
});
};
export const config: Config = {
path: "/api/geolocation"
};

Key changes:

  • TypeScript types imported from @netlify/edge-functions
  • Geolocation accessed via context.geo instead of request.geo
  • Explicit Config export defines the route path
  • Uses Deno-compatible syntax