Fazer deploy

Faça deploy com text build --adapter static, bun, vercel ou cloudflare, ou execute text start atrás de um proxy.

text build produz um dist/ portátil. Um adaptador o transforma na saída que a plataforma espera.

Adaptadores

text build --adapter <name>
AdaptadorSaídaExecução
(nenhum)dist/ + dist/.text/servertext start (Node)
staticdist/Qualquer hospedagem estática
bundist/server.jsbun dist/server.js
vercel.vercel/outputVercel (Build Output API v3)
cloudflaredist/ + _worker.jsCloudflare Pages

O adaptador também pode vir de TEXTJS_ADAPTER. Quando text build é executado na Vercel (VERCEL=1) ou no Cloudflare Pages (CF_PAGES=1), o adaptador correspondente é selecionado automaticamente.

Os adaptadores de servidor (bun, vercel e cloudflare) executam o mesmo pipeline de text start: middleware, rewrites, manipuladores de rota com o cache de rotas, arquivos estáticos e, por fim, o documento do console para URLs de páginas. Clientes de terminal como curl recebem o primeiro quadro da página como texto ANSI. Em vercel e cloudflare, isso abrange apenas páginas estáticas (veja curl e clientes de terminal). Os adaptadores de servidor servem arquivos com hash em /assets/ com Cache-Control: public, max-age=31536000, immutable.

Estático

text build --adapter static

Use em hospedagens sem servidor, como GitHub Pages, S3 ou uma CDN. Manipuladores de rota GET com dynamic = "force-static" ou revalidate passam por pré-renderização em arquivos: app/api/feed.json/route.ts se torna dist/api/feed.json. Uma cópia de index.html é gravada em 404.html para que links diretos abram o app do console. Hospedagens estáticas não conseguem distinguir curl de um navegador, então curl recebe a página HTML.

O build falha, listando todos os motivos, se o app precisar de um servidor: middleware.ts, rotas renderizadas no servidor, manipuladores de rota dinâmicos, manipuladores de rota com segmentos dinâmicos ou métodos diferentes de GET. Configure rewrites na hospedagem.

Bun

text build --adapter bunPORT=8080 bun dist/server.js

O adaptador bun grava um único servidor autocontido que não precisa de node_modules em tempo de execução. Ele lê PORT (padrão 3000) e HOSTNAME (padrão 0.0.0.0) e nunca serve server.js ou .text/. É um processo de longa duração, então também hospeda rotas renderizadas no servidor (export const runtime = "server") e suas sessões ativas, como text start. Use em um contêiner:

Dockerfiletext
FROM oven/bun:1COPY dist /appCMD ["bun", "/app/server.js"]

Vercel

text build --adapter vercelvercel deploy --prebuilt

Ou envie para um repositório Git conectado à Vercel: o build executa text build, detecta a Vercel e grava .vercel/output.

SaídaConteúdo
static/O build do cliente (sob basePath)
functions/_textjs/server.funcUma função Node.js 22 que atende todos os manipuladores de rota, com streaming
functions/_middleware.funcMiddleware de roteamento Edge: middleware.ts e caminhos canônicos para todos os apps
config.jsonCabeçalhos de arquivos estáticos, matchers de middleware, reescritas, rotas de manipuladores e o documento do console

O middleware edge usa o protocolo x-middleware-next / x-middleware-rewrite, então substituições de cabeçalhos e reescritas acontecem no roteador da Vercel antes de chegar à função ou à CDN. Todos os matchers compartilham um padrão de rota src. Requisições que nenhum matcher cobre pulam o middleware, a menos que seu caminho possa não estar na forma canônica (escapes percentuais, caracteres que um parser de URL codifica, //, segmentos . ou .., uma barra final). O middleware então compara o caminho canônico, verifica has / missing e reescreve a requisição para esse caminho, para que a Vercel a roteie da mesma maneira. Apps sem middleware.ts recebem a mesma função edge, que apenas faz a reescrita. Como todo build inclui uma função Edge, faça deploy com uma conta da Vercel autenticada: deploys anônimos (vercel deploy --temporary) não aceitam funções Edge.

A função do manipulador é interna. Cada rota de manipulador passa o caminho correspondente para ela no cabeçalho de requisição x-textjs-path. Esse cabeçalho é removido de toda requisição antes e depois do middleware, e o middleware edge nunca encaminha um (do cliente ou de middleware.ts), então apenas as rotas de manipuladores podem defini-lo. Requisições para /_textjs/* retornam 404 sem executar a função, antes e depois do middleware e das reescritas. As rotas geradas diferenciam maiúsculas de minúsculas, como os matchers e as reescritas em todas as outras hospedagens.

Os testes do adaptador executam essa saída contra uma emulação local do roteador da Vercel. Seu comportamento para correspondência de src, capturas de dest, transformações de cabeçalhos e rotas de status foi verificado em deploys reais; o middleware Edge não foi, porque não é possível fazer deploy dele anonimamente.

Cloudflare Pages

text build --adapter cloudflarebunx wrangler pages dev dist --compatibility-flags=nodejs_compatbunx wrangler pages deploy dist

A saída usa o modo avançado do Pages:

ArquivoFinalidade
_worker.jsMiddleware, reescritas, manipuladores de rota e o documento do console
_routes.jsonEnvia toda requisição ao worker. Sem middleware ou um basePath, /assets/* permanece na CDN estática do Pages
_headersCache imutável para /assets/* (anexado ao seu)
404.htmlFaz o Pages responder a arquivos ausentes com 404 em vez do app (mantido se você já tiver um)

.text/ (bundles do servidor e manifestos de build) é removido de dist/, pois o Pages publica o diretório como está.

Ative a flag de compatibilidade nodejs_compat no projeto do Pages (Configurações → Runtime) ou em wrangler.toml; o cache de dados usa AsyncLocalStorage. Arquivos estáticos são servidos pelo binding ASSETS, e a revalidação em segundo plano usa ctx.waitUntil().

Com middleware, toda requisição executa o worker, incluindo arquivos com hash, para que o middleware veja todos os caminhos pelos quais um arquivo pode ser acessado. Cada requisição que executa o worker é uma invocação de Functions e conta na sua cota de requisições do Workers. Para um carregamento de página, isso inclui o documento mais cada arquivo que ele busca (2 para um pequeno app de teste com um bundle JavaScript; mais para apps com mais arquivos). No plano Workers Free, o Pages serve arquivos estáticos sem o worker quando a cota diária acaba, pulando o middleware. Se o middleware proteger algo em dist/, defina Configurações → Runtime → Falhar aberto / fechado como Falhar fechado.

wrangler.tomltoml
name = "my-console"pages_build_output_dir = "dist"compatibility_date = "2025-01-01"compatibility_flags = ["nodejs_compat"]

Atualização

As correções de segurança em @textjs/app só chegam a um deploy depois que você refaz o build e faz deploy novamente:

  • Vercel: faça deploy do novo .vercel/output.
  • Cloudflare Pages: faça deploy do novo dist/, com _worker.js e _routes.json.
  • Bun: faça deploy de todo o novo dist/ (server.js, arquivos estáticos e bundles de sessões ativas) e reinicie o servidor.
  • text start: execute text build e reinicie.

Deploys antigos continuam acessíveis em suas próprias URLs (URLs de prévia da Vercel e do Cloudflare Pages, por exemplo). Exclua-os ou coloque-os sob a proteção de acesso da plataforma.

Rotas renderizadas no servidor

Rotas renderizadas no servidor mantêm uma sessão por aba aberta, então precisam de um servidor de longa duração: text start ou o adaptador bun. Os adaptadores static, vercel e cloudflare fazem o build falhar com TX030 quando uma página exporta runtime = "server".

Atrás de um proxy

text start se vincula a 127.0.0.1 e, enquanto vinculado ao loopback, responde apenas a localhost, *.localhost e hosts com endereço IP (proteção contra DNS rebinding). Outros hosts recebem um 403 com TX028. Coloque as configurações públicas em text.config.ts:

text.config.tsts
import { defineConfig } from "@textjs/app";export default defineConfig({  server: {    origin: "https://console.example.com", // request.url always uses it (or TEXTJS_ORIGIN)    trustProxy: true, // read X-Forwarded-Host / -Proto from your proxy (or TRUST_PROXY=1)    allowedHosts: [".example.com"],  },});

Sem origin ou trustProxy, request.url é construído a partir do cabeçalho Host validado, usando http.

Ressalvas

  • proxy em text.config.ts só é executado em text dev e text start; os adaptadores não o incluem. Use rewrites, compatível com todos os adaptadores de servidor.
  • Cada instância serverless tem seu próprio cache em memória. Veja Cache.
  • rewrites que usam grupos brutos de expressões regulares são convertidos em rotas da Vercel na medida do possível; parâmetros nomeados (:slug, :path*) são exatos.
Editar esta página no GitHub