curl and Terminal Clients

curl, Wget, HTTPie and xh get a page's first frame as truecolor ANSI text. Configure its size or turn it off.

Clientes HTTP de terminal recebem o primeiro quadro de uma página como texto ANSI truecolor em vez do documento HTML. Você não precisa configurar nada.

curl https://my-app.example.com/about

Quais requisições recebem um quadro

Uma requisição recebe um quadro quando todas estas condições são atendidas:

  • o método é GET ou HEAD;
  • o User-Agent começa com curl/, Wget/, wget2/, HTTPie/ ou xh/;
  • o cabeçalho Accept está ausente ou não menciona text/html.

Navegadores, rastreadores e prévias de links recebem a página HTML. Para receber o HTML pelo curl, solicite-o:

curl -H 'Accept: text/html' https://my-app.example.com/about

O quadro é escolhido no ponto em que a página seria servida: após middleware, rewrites e manipuladores de rota, e nunca para arquivos ou caminhos cujo último segmento contém um ponto. Redirecionamentos do middleware, respostas 401, cabeçalhos e reescritas se aplicam ao curl como aos navegadores. /api/health continua executando seu manipulador e /robots.txt continua servindo o arquivo.

Conteúdo do quadro

O quadro é a primeira renderização da página, como em uma estrutura pré-renderizada: cada limite de <Suspense> que ainda está aguardando exibe seu fallback. Componentes de servidor assíncronos não são executados, e fetch() nunca é resolvido, então os dados carregados em efeitos permanecem no estado de carregamento.

  • Tamanho: 80 × 24 células. Um app com viewport fixo (viewport.responsive: false) usa viewport.width × viewport.height em vez disso.
  • Cores: códigos de escape SGR de 24 bits no viewport.theme do app. Cada linha termina com uma redefinição, e o quadro termina com uma quebra de linha.
  • Status: 200, ou 404 com a página de não encontrado do app quando nenhuma página corresponde ou a página chama notFound(). Uma página que chama redirect() durante a renderização serve HTML.

As respostas são text/plain; charset=utf-8 com Vary: User-Agent, Accept e Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate, para que caches compartilhados nunca armazenem um quadro e o sirvam a um navegador. A página HTML em um caminho onde curl recebe um quadro inclui o mesmo cabeçalho Vary.

Onde funciona

HospedagemPáginas estáticasPáginas dinâmicas, caminhos desconhecidos
text devRenderizadas sob demandaRenderizadas sob demanda
text start, bunPré-renderizadas por text buildRenderizadas sob demanda
vercel, cloudflarePré-renderizadas por text buildPágina HTML
staticPágina HTMLPágina HTML

Páginas renderizadas no servidor precisam de text start ou bun (veja Fazer deploy).

Hospedagens estáticas não podem responder a um cliente de forma diferente de outro, então o adaptador static não oferece suporte a quadros. Na Vercel e na Cloudflare, os quadros de páginas estáticas são incluídos no build. Páginas dinâmicas ([id], force-dynamic) servem HTML nessas plataformas, porque os adaptadores vercel e cloudflare não fazem deploy de um renderizador.

text start e bun dist/server.js renderizam as páginas restantes sob demanda com .text/server/live.mjs e mantêm os últimos 128 quadros por 10 segundos. Cada servidor renderiza no máximo 20 páginas sem cache a cada 10 segundos. Acima desse limite, o curl recebe a página HTML até que a cota seja renovada. Se live.mjs não puder ser carregado no servidor, por exemplo porque um módulo de página lê window no nível superior, essas páginas servem HTML.

text build informa os quadros pré-renderizados:

 ✓ Prerendering curl frames (5/5)

Configuração

Altere o tamanho para todo o app ou desative os quadros:

text.config.tsts
import { defineConfig } from "@textjs/app";export default defineConfig({  ansi: { cols: 100, rows: 30 },  // ansi: false,});

Uma página pode alterar seu próprio tamanho ou servir HTML também para terminais:

app/dashboard/page.tsxtsx
export const ansi = { cols: 120, rows: 40 };// export const ansi = false;

Os tamanhos são limitados a 1–500 células. Com ansi: false em text.config.ts, as exportações das páginas são ignoradas.

HTTP sem criptografia

O curl não segue redirecionamentos a menos que você passe -L. A Vercel redireciona requisições http:// para https://, assim como a Cloudflare com Sempre usar HTTPS ativado, então curl http://… imprime o redirecionamento em vez do quadro. Compartilhe URLs https://.

Servidores personalizados

@textjs/app/ansi exporta as funções auxiliares de detecção e resposta para servidores e funções que não executam text start nem um adaptador:

import { ansiResponse, wantsAnsi } from "@textjs/app/ansi";import { frameToAnsi } from "@textjs/react";if (wantsAnsi(request)) return ansiResponse(frameToAnsi(buffer, { theme: "geistDark" }), request.method);

wantsAnsi(request) também aceita (method, headers) com Headers da Web ou IncomingHttpHeaders do Node. frameToAnsi(buffer, { theme }) codifica um CellBuffer renderizado da mesma forma que o framework.

Editar esta página no GitHub