Migrar para a Zenifra

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 NetlifyNa Zenifra
Site estático ou SPAProjeto HTTP com serve ou NGINX
_redirects, _headers e [[redirects]]serve.json ou nginx.conf; veja Redirects e headers
Netlify FunctionsRotas de um servidor HTTP; veja Functions
Scheduled FunctionsJobs agendados
Background FunctionsFilas com um worker, ou Jobs agendados
Edge FunctionsMiddleware do servidor da aplicação
Netlify FormsRota própria na aplicação; veja Forms
Next.js, Astro ou Nuxt com SSRServidor Node.js; veja Frameworks com servidor
Netlify BlobsArmazém ou Chave-Valor
Deploy PreviewsAmbientes 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 NetlifyPara que serve
Base directoryPasta onde a Netlify instala dependências e roda a build. Vazio é a raiz do repositório
Package directoryPasta do site em monorepos
Build commandComando de build, como npm run build
Publish directoryPasta publicada, como dist, build ou public
Functions directoryPasta 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.env

Variá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] do netlify.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çãoO que fazer na Zenifra
[build] base, command, publishUsar 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 NetlifyNo console da Zenifra
Versão do Node.jsRuntime 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 commandComando Build
Publish directoryPasta 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 variablesVariá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:

_redirects (Netlify)
/blog/*      /artigos/:splat   301
/antigo      /novo             302
_headers (Netlify)
/assets/*
  Cache-Control: public, max-age=31536000, immutable
public/serve.json (Zenifra)
{
  "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:

server.js
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 @hourly viram 0 * * * * e @daily vira 0 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:

FrameworkO que mudarComando BuildComando Start
Next.jsNada: o adaptador da Netlify não é usadonpm run buildnpx next start -H 0.0.0.0 -p 3000
Astro (SSR)Trocar o adaptador @astrojs/netlify pelo @astrojs/node em modo standalonenpm run buildnode ./dist/server/entry.mjs
Nuxt 3 (SSR)Remover o preset da Netlify, se houvernpm run buildnode .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

OrigemDestino na Zenifra
Netlify BlobsArmazém (arquivos) ou Chave-Valor (dados pequenos)
Envios do Netlify FormsSalve 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

  1. Abra a URL *.clients.zenifra.com do projeto e teste páginas, redirects, formulários e rotas de API.
  2. Confira em Logs de build e nos logs da aplicação se não há erros.
  3. Adicione o domínio na Zenifra e crie no seu DNS o CNAME e os registros TXT mostrados no console.
  4. 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.
  5. Mantenha o site da Netlify por alguns dias para rollback e só então o remova.

Problemas comuns

SintomaCausa provávelCorreção
Rota recarregada retorna 404Falta o fallback da SPAUse serve -s ou try_files ... /index.html no NGINX
Redirects antigos pararamA Zenifra não lê _redirects nem netlify.tomlTraduza para serve.json ou nginx.conf
/.netlify/functions/... retorna 404Função sem servidorRegistre a rota no servidor; veja Functions
Formulário não enviadata-netlify não tem efeito fora da NetlifyCrie uma rota própria; veja Forms
npm ci falhaSite usa pnpm ou Yarn, sem package-lock.jsonGere e versione um package-lock.json
Página em branco e 404 em .jsPasta errada no startUse a mesma pasta da Publish directory
E-mail do domínio parouRegistros MX não foram recriadosRecrie 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

Nessa página