Migrar da Netlify para a Zenifra
Este guia mostra onde encontrar cada configuração de um projeto na Netlify e onde informar o mesmo valor no console da Zenifra. Ele cobre sites estáticos e SPAs, o netlify.toml, os arquivos _redirects e _headers, Netlify Functions, Forms, frameworks com renderização no servidor (Next.js, Astro, Nuxt) e a Netlify DNS. Para o roteiro geral, com cópia de dados e troca de DNS, veja Migrar para a Zenifra.
Mantenha o site da Netlify no ar enquanto você sobe e valida a aplicação na Zenifra. Só remova o site depois de trocar o DNS.
Antes de começar: o que o seu site usa
Um site que só tem build, pasta publicada, redirects e headers migra direto. Recursos de servidor da Netlify precisam de um equivalente:
| Na Netlify | Na Zenifra |
|---|---|
| Site estático ou SPA | Projeto HTTP com serve ou NGINX |
_redirects, _headers e [[redirects]] | serve.json ou nginx.conf; veja Redirects e headers |
| Netlify Functions | Rotas de um servidor HTTP; veja Functions |
| Scheduled Functions | Jobs agendados |
| Background Functions | Filas com um worker, ou Jobs agendados |
| Edge Functions | Middleware do servidor da aplicação |
| Netlify Forms | Rota própria na aplicação; veja Forms |
| Next.js, Astro ou Nuxt com SSR | Servidor Node.js; veja Frameworks com servidor |
| Netlify Blobs | Armazém ou Chave-Valor |
| Deploy Previews | Ambientes de Preview |
1. Copie as configurações na Netlify
No painel da Netlify, abra o projeto e entre em Project configuration.
Build settings
Em Project configuration › Developer settings › Continuous deployment › Build settings, anote:
| Campo na Netlify | Para que serve |
|---|---|
| Base directory | Pasta onde a Netlify instala dependências e roda a build. Vazio é a raiz do repositório |
| Package directory | Pasta do site em monorepos |
| Build command | Comando de build, como npm run build |
| Publish directory | Pasta publicada, como dist, build ou public |
| Functions directory | Pasta das Functions, por padrão netlify/functions |
Em Branches and deploy contexts, na mesma área, veja a branch de produção. Em Dependency management, veja a versão do Node.js. A versão também pode estar em um .nvmrc, em um .node-version ou na variável NODE_VERSION: se existir, vale a do repositório.
Variáveis de ambiente
As variáveis ficam em Project configuration › Environment variables. Cada uma pode ter valores por contexto, como production e deploy-preview. Para exportar as de produção pela CLI da Netlify:
netlify env:list --plain --context production > netlify.envVariáveis marcadas como secretas não podem ser lidas de volta, nem pela CLI. Pegue esses valores na origem, como o painel do serviço externo ou o gerenciador de senhas da equipe.
Confira também:
- variáveis do time em Team settings › Environment variables, que chegam ao projeto sem aparecer na lista dele
- a seção
[build.environment]donetlify.toml, que define variáveis direto no arquivo
netlify.toml
Se o repositório tem um netlify.toml, ele vale mais que o painel. Anote:
| Seção | O que fazer na Zenifra |
|---|---|
[build] base, command, publish | Usar nos campos do projeto; veja a etapa 2 |
[build.environment] | Cadastrar como variáveis do projeto |
[context.production] | Usar os valores de produção, que substituem os de [build] |
[[redirects]] e [[headers]] | Traduzir; veja Redirects e headers |
[functions] | Migrar as Functions; veja Functions |
[[edge_functions]] e [[plugins]] | Ver caso a caso |
Os arquivos _redirects e _headers ficam na pasta publicada, muitas vezes copiados de public/ durante a build.
Domínios e Netlify DNS
Em Domain management › Production domains, anote os domínios do projeto.
Se o domínio usa a Netlify DNS, abra DNS no menu do time, selecione o domínio e clique em Download records para baixar todos os registros em CSV. Você vai precisar deles, inclusive os de e-mail (MX e TXT), ao mudar os nameservers.
2. Crie o projeto na Zenifra
No console, clique em + Criar projeto, escolha Aplicação HTTP e o plano. Em Configurações Avançadas, escolha Repositório Git em Origem do Projeto, o Provedor Git GitHub (ou Forgejo), o mesmo repositório e a branch de produção.
Site estático ou SPA
| Na Netlify | No console da Zenifra |
|---|---|
| Versão do Node.js | Runtime Node.js e Versão igual (20, 22, 24 ou 26) |
| Base directory (ou Package directory, em monorepo) | Diretório raiz. Use . para a raiz |
| Build command | Comando Build |
| Publish directory | Pasta usada no Comando Start |
| — | Comando Start: npx serve -s dist -l tcp://0.0.0.0:3000, trocando dist pela Publish directory |
| — | Porta: 3000 |
| Environment variables | Variáveis de Ambiente |
Adicione o serve às dependências com npm install serve. O -s responde com o index.html em rotas desconhecidas, como o redirect /* /index.html 200 de uma SPA. Em sites com várias páginas HTML, como Hugo, Eleventy ou Astro estático, remova o -s.
Para gastar menos, publique a pasta com NGINX no plano Static; veja Sites estáticos e SPAs.
Geradores fora do Node.js
Sites feitos com Hugo, Jekyll ou outro gerador que não roda em Node.js são publicados como Imagem Docker: gere o site em um estágio do Dockerfile e copie a pasta para uma imagem do NGINX, como no exemplo de Sites estáticos e SPAs. A GitHub Action automatiza a build e o deploy a cada push.
pnpm, Yarn e Bun
A Zenifra instala dependências Node.js com npm ci e precisa de um package-lock.json versionado. Se o site usa pnpm ou Yarn, gere e versione um package-lock.json antes de migrar. Projetos com Bun podem usar o Runtime Bun. Veja Runtimes.
3. Ajuste o que muda entre as plataformas
Redirects e headers
A Zenifra não lê _redirects, _headers nem o netlify.toml. Com o serve, crie um serve.json dentro da pasta publicada. Uma forma simples é colocar o arquivo em public/, que a maioria dos frameworks copia para a pasta de build:
/blog/* /artigos/:splat 301
/antigo /novo 302/assets/*
Cache-Control: public, max-age=31536000, immutable{
"redirects": [
{ "source": "/blog/:slug", "destination": "/artigos/:slug", "type": 301 },
{ "source": "/antigo", "destination": "/novo", "type": 302 }
],
"headers": [
{
"source": "assets/**",
"headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }]
}
]
}No serve.json, type é o status do redirect (padrão 301), e rewrites faz o mesmo que um redirect 200 da Netlify. Um segmento como :slug cobre um nível do caminho: o :splat da Netlify, que cobre vários níveis, precisa de uma regra por nível ou de NGINX. Para regras mais complexas, como proxy para outro domínio (/api/* https://api.exemplo.com/:splat 200), use NGINX com proxy_pass ou trate a rota no servidor da aplicação.
Functions
Cada arquivo de netlify/functions é uma função que sobe sob demanda. Na Zenifra, a aplicação é um servidor contínuo, então as funções viram rotas de um servidor HTTP. Funções no formato atual da Netlify recebem um Request e devolvem um Response, o que combina com o Hono:
import { Hono } from 'hono'
import { serve } from '@hono/node-server'
import { serveStatic } from '@hono/node-server/serve-static'
import contato from './netlify/functions/contato.js'
const app = new Hono()
// Mesma rota que a função tinha na Netlify
app.all('/.netlify/functions/contato', (c) => contato(c.req.raw))
// Arquivos do site
app.use('/*', serveStatic({ root: './dist' }))
serve({ fetch: app.fetch, port: Number(process.env.PORT) || 3000, hostname: '0.0.0.0' })Configure Comando Start node server.js, Porta 3000 e a variável PORT=3000. Se a função usa o segundo argumento context da Netlify, troque o que ele fornecia por variáveis ou dados da requisição. Funções no formato antigo handler(event, context) precisam ser adaptadas para receber a requisição do servidor.
Se preferir, mantenha a URL antiga ou mude para /api/... e atualize as chamadas no frontend.
Scheduled e Background Functions
- Scheduled Functions viram Jobs agendados. Crie o Job com Origem da tarefa Repositório GitHub, Runtime Node.js e um Comando da tarefa que execute a lógica, como
node scripts/tarefa.mjs. A Expressão cron pode ser a mesma: as duas plataformas usam UTC. Atalhos como@hourlyviram0 * * * *e@dailyvira0 0 * * *. - Background Functions podem virar mensagens em uma fila, processadas por um projeto worker com Exposição Privado, ou um Job agendado, se a tarefa não precisa começar na hora.
Forms
A Netlify detecta formulários com data-netlify="true" e guarda os envios. Na Zenifra, o formulário precisa enviar para uma rota sua. Crie uma rota no servidor da aplicação que receba o POST, valide os campos e envie o conteúdo por e-mail ou grave em um banco de dados. Depois remova data-netlify e aponte o action do formulário para a nova rota.
Antes de desligar a Netlify, salve os envios já recebidos, que ficam no painel de Forms do projeto.
Image CDN
URLs com /.netlify/images não funcionam fora da Netlify. Use imagens já otimizadas na build, o otimizador do seu framework rodando no servidor, como o next/image, ou um serviço de imagens externo.
Variáveis da Netlify
Variáveis criadas pela Netlify na build, como URL, DEPLOY_URL, CONTEXT e NETLIFY, não existem na Zenifra. Se o código ou a build usa alguma delas, crie uma variável com o valor equivalente, como URL com o seu domínio.
Frameworks com servidor
Na Netlify, Next.js, Astro e Nuxt com renderização no servidor usam adaptadores que transformam a aplicação em funções. Na Zenifra, eles rodam como um servidor Node.js:
| Framework | O que mudar | Comando Build | Comando Start |
|---|---|---|---|
| Next.js | Nada: o adaptador da Netlify não é usado | npm run build | npx next start -H 0.0.0.0 -p 3000 |
| Astro (SSR) | Trocar o adaptador @astrojs/netlify pelo @astrojs/node em modo standalone | npm run build | node ./dist/server/entry.mjs |
| Nuxt 3 (SSR) | Remover o preset da Netlify, se houver | npm run build | node .output/server/index.mjs |
No Astro e no Nuxt, defina as variáveis HOST=0.0.0.0 e PORT=3000. Em todos, use Porta 3000. Veja o guia de Next.js para variáveis NEXT_PUBLIC_*, cache e várias instâncias.
4. Migre dados e arquivos
| Origem | Destino na Zenifra |
|---|---|
| Netlify Blobs | Armazém (arquivos) ou Chave-Valor (dados pequenos) |
| Envios do Netlify Forms | Salve pelo painel de Forms da Netlify antes de remover o projeto |
| Banco de dados externo (Supabase, Neon etc.) | Pode continuar onde está ou ir para o PostgreSQL gerenciado com pg_dump e pg_restore |
5. Valide e troque o DNS
- Abra a URL
*.clients.zenifra.comdo projeto e teste páginas, redirects, formulários e rotas de API. - Confira em Logs de build e nos logs da aplicação se não há erros.
- Adicione o domínio na Zenifra e crie no seu DNS o
CNAMEe os registrosTXTmostrados no console. - Se o domínio usa a Netlify DNS, recrie todos os registros do CSV no novo provedor de DNS, troque os nameservers no registrador e espere a propagação, que pode levar até um dia. Só então remova a zona DNS na Netlify.
- Mantenha o site da Netlify por alguns dias para rollback e só então o remova.
Problemas comuns
| Sintoma | Causa provável | Correção |
|---|---|---|
| Rota recarregada retorna 404 | Falta o fallback da SPA | Use serve -s ou try_files ... /index.html no NGINX |
| Redirects antigos pararam | A Zenifra não lê _redirects nem netlify.toml | Traduza para serve.json ou nginx.conf |
/.netlify/functions/... retorna 404 | Função sem servidor | Registre a rota no servidor; veja Functions |
| Formulário não envia | data-netlify não tem efeito fora da Netlify | Crie uma rota própria; veja Forms |
npm ci falha | Site usa pnpm ou Yarn, sem package-lock.json | Gere e versione um package-lock.json |
Página em branco e 404 em .js | Pasta errada no start | Use a mesma pasta da Publish directory |
| E-mail do domínio parou | Registros MX não foram recriados | Recrie os registros do CSV da Netlify DNS |
Precisa de ajuda?
Escreva para [email protected] com o seu netlify.toml ou fale pelo WhatsApp +55 (11) 5199-3013.
Última atualização em
Migrar do Heroku para a Zenifra
Passo a passo para trazer um app do Heroku para a Zenifra: como exportar Config Vars, traduzir Procfile, release phase, buildpacks e Heroku Scheduler, migrar Heroku Postgres e onde informar cada valor no console.
Migrar do Render para a Zenifra
Passo a passo para trazer um Web Service do Render para a Zenifra: onde copiar Build Command, Start Command, Root Directory e variáveis no Render e onde colar cada valor no console da Zenifra.