Moving from Netlify
Move a Netlify site to Deplane with one command. deplane import netlify reads the site on Netlify and the netlify.toml in your code, and shows what moves and what stays. It then creates the Deplane app with its production variables and deploys your code. Netlify keeps serving your users until you switch.
The command runs on your own computer with your Netlify token, which never leaves it. It only reads Netlify: nothing there is changed. The command and its flags are in the CLI reference, and every error has a fix in Troubleshooting and error codes. It works like Moving from Heroku.
Before you start
- Install the Deplane CLI and run
deplane login. - Have the site's code in a folder: a checkout of the repository Netlify builds, at the commit it runs. If Netlify builds a subfolder (its Base directory), pass that folder with
--source. - Create a personal access token in Netlify: User settings → Applications → Personal access tokens → New access token, with a short expiration.
The Netlify token. A personal access token can do everything your account can; there are no read-only tokens. The CLI only reads with it (GET requests to api.netlify.com). Delete it when the import is done.
Give the token to Deplane in one of three ways, never as a flag:
- run
deplane import netlify my-site --checkin a terminal and paste it at the hidden prompt; - set it for one command:
NETLIFY_AUTH_TOKEN=nfp_... deplane import netlify my-site --check(it lands in your shell history; the prompt does not); - or pipe it in from a password manager:
op read op://Private/netlify/token | deplane import netlify my-site --check.
A token piped on stdin wins over NETLIFY_AUTH_TOKEN. The CLI says which one it used, never the token itself. It is never written to disk, never printed, left out of --debug, and never sent to Deplane.
Secret variables
Netlify gives the values of secret variables only to code running on Netlify: the dashboard, API and CLI show none of them, except a local development value. The import lists them by name, copies the others, and creates the app without deploying it, since it would start without them. The next steps show what to set before you deploy:
deplane secrets set API_KEY=... --app my-site
deplane secrets set --build API_KEY=... --app my-site # if the build reads it
cd my-site && deplane launch --app my-site # deploys the app and writes deplane.toml
Variables shared by your Netlify team (Team settings → Environment variables) may not be listed for the site: check them there, and set the ones the site needs.
Check first
$ deplane import netlify shop --check
Netlify site shop (framework astro, team acme, repo github.com/acme/shop@main, commit 1a2b3c4) → Deplane app shop
Code
✓ Deploys /home/me/shop with Railpack: Detected Astro 5, Node 22, port 8080.
✓ Your folder is at commit 1a2b3c4, the one Netlify runs.
⚠ Netlify builds with `npm run build` and publishes dist. Railpack detects the build itself ...
⚠ Netlify applies 2 redirect rule(s) (_redirects, netlify.toml) and 0 header rule(s) itself; Deplane does not. ...
⚠ Netlify serves the site from its global CDN; Deplane serves it from one region, in Europe. ...
Processes
✓ web: Netlify serves the site from its CDN → 1 small instance. Set more with `deplane scale`.
Config vars
✓ 2 copied as secrets: PUBLIC_API_URL, SITE_ENV.
✓ 2 also set as build secrets, since Netlify gives them to the build ...
Domains
⚠ www.shop.example points at Netlify (shop.netlify.app). It moves when you switch ...
Plan
✓ Fits your Free plan: after the import the team uses 1 of 2 instances and 512 MB of 1 GB memory.
Nothing was changed (--check). Run the command again without --check to import.
✓ is what moves as it is, ⚠ is what you should know or do yourself, and ✗ is what stops the import. --check --json prints the same report as one JSON document. Then run the command again without --check (in a terminal it asks first; from a script, add --yes).
What moves
| On Netlify | On Deplane |
|---|---|
| A static site (Astro, Vite, Hugo, Eleventy, Gatsby ...) | An app that Railpack builds and serves as files. |
| A Next.js site | An app that Railpack builds and runs with next start. |
| Production variables (the production value, else the one for all contexts) | Secrets. Those Netlify gives to builds are build secrets too, since a static site's variables are built into its files. netlify.toml's [build.environment] and [context.production.environment] apply to builds only, so they become build secrets only (over the site's value for the build). Not copied: Netlify's own variables, and variables without a production value. |
| Secret variables | Listed by name, not copied: see Secret variables. |
| The custom domain and domain aliases | Listed, and moved at the switch. *.netlify.app stays with Netlify. |
| Databases you connected (Netlify DB, Neon, Supabase ...) | Their URLs are copied as they are, and the site keeps using them. To move a Postgres database later, use deplane db import. |
| The code | Your folder, built by Railpack, or by your Dockerfile if it has one. |
Instances: Netlify has none to map. The app starts with one small instance (0.5 CPU, 512 MB).
What does not move
- Netlify Functions, scheduled functions and Edge Functions do not run on Deplane: the report lists them. Serve those routes from your app's own server, and run scheduled work as a cron job.
- Redirects and headers (
_redirects,netlify.toml) are applied by Netlify's CDN, not by Deplane: the report counts them. Move them into your framework's config or your server. - Netlify Forms are listed and not moved: submissions need a form handler of your own. Export the submissions you keep first.
- Netlify Identity, Blobs, Image CDN, split testing, prerendering and build plugins are Netlify services.
- Netlify DNS: if Netlify hosts your domain's DNS, make the changes there, or move the zone first.
- Netlify serves from a global CDN; Deplane serves from one region, in Europe. Put a CDN in front of the app if your users are far away.
Switch over
- Set the secret variables and deploy, if the import listed any. Test the app at its Deplane address.
- Before the day: run
deplane domains add HOSTNAME --app APPfor each custom domain and add the TXT record it shows. - Switch DNS to the target
deplane domains addshowed, and wait for the certificate (deplane domains check HOSTNAME --app APP). - Remove the domains from the Netlify site, and delete it once the app has run well on Deplane.
- Delete the Netlify token in User settings → Applications.
Limits
The Heroku import's limits apply. Secret variables, functions and forms are not moved. The import is built on Netlify's public API; tell support@deplane.io if Netlify answers something the CLI does not expect.
This page is also available as Markdown. AI agents can start at /llms.txt.