From Vercel to Netlify: Migrating Our Frontend Projects

From Vercel to Netlify: Migrating Our Frontend Projects
by Zelkulon15 March 20261 min read

We migrated zelkulon.com and all client projects from Vercel to Netlify – not due to technical shortcomings, but a conscious decision. Here's what really happened, including all the pitfalls.

Why we switched

Vercel made no technical mistakes. No outages, no poor support, no performance issues. Nevertheless, we at Zelkulon UG decided to migrate all our projects to Netlify.

The reason: Vercel Free is prohibited for commercial use. Anyone hosting client projects with their agency must start directly with Vercel Pro – $20 per team member. Netlify Free allows commercial use without restrictions. On top of that, Vercel is increasingly under VC pressure with more aggressive pricing changes. Netlify operates more independently.

Step 1 – Setting up Netlify

Getting started is straightforward: create a Netlify account, link your GitHub repo, enter build settings. Note for Angular: the old command ng build --prod no longer works since Angular 12.

Next.js
  Build command:     npm run build
  Publish directory: .next

Angular (ab Version 12+)
  Build command:     ng build --configuration production
  Publish directory: dist/<projektname>/browser

Environment variables from Vercel can be transferred manually. Vercel doesn't export them directly – so just enter the values one by one or transfer them via CLI.

# Vercel-Variablen lokal auflisten
vercel env pull .env.vercel

# Dann per Netlify CLI ΓΌbertragen (oder manuell in der UI):
netlify env:set NEXT_PUBLIC_API_URL https://api.beispiel.de
netlify env:set DATABASE_URL postgres://...

Step 2 – The CORS error (almost missed)

This was the most expensive mistake in time. Our Railway services had CORS_ORIGINS configured only with *.vercel.app. Netlify uses a different domain – the Spring Boot CORS filter silently blocked all requests from the new URL.

Richtige Reihenfolge:

1. Netlify-Domain zu CORS hinzufΓΌgen – Vercel NOCH NICHT entfernen
   CORS_ORIGINS=https://zelkulon.vercel.app,
               https://zelkulon.netlify.app,
               https://zelkulon.com

2. Railway-Service neu deployen

3. Netlify-Deployment testen β†’ CORS funktioniert

4. Erst jetzt: vercel.app aus CORS entfernen
   CORS_ORIGINS=https://zelkulon.com

Anyone who reverses the order – first disabling Vercel and then adding the Netlify domain to CORS – will have a broken production site for the duration of the Railway redeploy.

# application-prod.yml (Spring Boot Beispiel)
cors:
  allowed-origins:
    - https://zelkulon.com
    - https://zelkulon.netlify.app   # wΓ€hrend der Migration

# Nach abgeschlossener Migration:
cors:
  allowed-origins:
    - https://zelkulon.com

Step 3 – Updating DNS at Strato

Strato does not support ALIAS or ANAME records. This is a well-known issue with apex domains. Netlify solves this with a fixed load balancer IP.

# Apex-Domain (zelkulon.com)
Typ:  A
Name: @
Wert: 75.2.60.5

# www-Subdomain
Typ:  CNAME
Name: www
Wert: apex-loadbalancer.netlify.com

# Diese Records NICHT anfassen:
MX    β†’  Google Mail
TXT   β†’  SPF-Record (v=spf1 ...)
TXT   β†’  DKIM (_domainkey)
TXT   β†’  DMARC (_dmarc)

Existing DNS records for email (Google MX, SPF, DKIM, DMARC) remain unchanged. DNS propagation takes between 10 minutes and a few hours depending on TTL.

Step 4 – SSL provisioning fails

⚠ SSL certificate provisioning fails

Problem: Netlify cannot issue a Let's Encrypt certificate – the www CNAME record was missing.

Fix: Add CNAME for www, wait for DNS propagation, then click 'Retry TLS certificate' in Netlify.

  • Add CNAME for www in Strato (apex-loadbalancer.netlify.com)
  • Wait for DNS propagation (check status in Netlify Domain Management)
  • In Netlify: Domain management β†’ HTTPS β†’ Retry TLS certificate

Step 5 – Angular build problems

For a client project with Angular 14, Netlify aborted the build with several errors.

⚠ Peer dependency conflicts

Problem: Angular 14 + @angular/cdk 12 generate npm dependency errors during the Netlify build.

Fix: Set NPM_FLAGS = --legacy-peer-deps as a Netlify environment variable, or use npm ci --legacy-peer-deps in netlify.toml.

# Als Netlify Environment Variable:
NPM_FLAGS = --legacy-peer-deps
# Oder in netlify.toml:
[build]
  command = "npm ci --legacy-peer-deps && ng build --configuration production"
  publish = "dist/projektname/browser"

⚠ Cannot find module 'webpack'

Problem: Inconsistent node_modules state leads to a missing webpack module.

Fix: Use npm ci instead of npm install – forces a clean install based on package-lock.json.

[build]
  command = "npm ci --legacy-peer-deps && ng build --configuration production"

Step 6 – Secrets in the code

Netlify raised an alert during the build: secrets found in source code. This is a protection feature – Vercel doesn't have this check.

# Netlify blockiert den Build wenn Secrets im Code gefunden werden:
# Build blocked: potential secret detected in source code
# SMTP_USER, SMTP_PASS found in src/environments/environment.ts

Remove values from the code and enter them as Netlify environment variables. If credentials are already in the Git history: regenerate them immediately.

# Falls Credentials bereits in der Git-History stehen:
# Sofort neu generieren/Γ€ndern – History bereinigen:
git filter-branch --tree-filter   'sed -i "s/echtes_passwort/ENTFERNT/g" src/environments/environment.ts' HEAD
git push origin --force

Step 7 – Cancelling Vercel

Only after a successful test on Netlify, never before. Pre-cancellation checklist:

  • All projects live and stable on Netlify
  • Domains pointing to Netlify (DNS verified)
  • SSL certificates valid
  • CORS on Railway updated (Vercel domains removed)
  • Clients informed (if client projects are affected)

Vercel Pro: downgrade to Free takes effect immediately, prorated refund is automatic. When downgrading, all team members except the owner are removed from the team.

Netlify vs. Vercel – The honest comparison

FeatureVercelNetlify
Free Plan commercial use❌ Verbotenβœ… Erlaubt
StrengthNext.js / Full-StackJAMstack, Multi-Framework
Native Postgresβœ…βœ…
Built-in formsβŒβœ… (100/Monat gratis)
A/B testingβŒβœ…
Pro price$20/Mitglied$20/Mitglied

On Netlify's credit system: the Free plan provides 300 credits/month. Credits are consumed by deploys (15/deploy), bandwidth (10/GB) and serverless functions (5/GB-hr). All projects in a team share the same pool – when the pool is empty, all projects go offline.

Conclusion

The migration itself is technically straightforward. Anyone who knows the pitfalls can finish in under an hour. The concrete stumbling blocks:

  • CORS order: add Netlify domain first, remove Vercel domain last
  • DNS at Strato: A-Record + CNAME for www, no ALIAS/ANAME available
  • SSL: fails without www CNAME – Retry works immediately after DNS update
  • Angular build flags: don't forget --configuration production and --legacy-peer-deps
  • Secrets in code: Netlify detects them and blocks the build – good, but surprising

For agencies and freelancers who want to run multiple projects on the free plan without being in a legal grey zone, switching is worthwhile. Anyone primarily using Next.js and already paying for Vercel Pro has no compelling technical reason to switch – but there's no reason not to either.

From Vercel to Netlify: Migrating Our Frontend Projects