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.

Los clientes HTTP de terminal reciben el primer fotograma de una página como texto ANSI de color verdadero en lugar del documento HTML. No necesitas configurar nada.

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

Solicitudes que reciben un fotograma

Una solicitud recibe un fotograma cuando se cumplen todas estas condiciones:

  • el método es GET o HEAD;
  • el User-Agent empieza por curl/, Wget/, wget2/, HTTPie/ o xh/;
  • la cabecera Accept está ausente o no menciona text/html.

Los navegadores, los rastreadores y las vistas previas de enlaces reciben la página HTML. Para obtener el HTML con curl, solicítalo:

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

El fotograma se elige en el punto en que se serviría la página: después del middleware, de rewrites y de los manejadores de ruta, y nunca para archivos o rutas cuyo último segmento contiene un punto. Las redirecciones del middleware, los códigos 401, las cabeceras y las reescrituras se aplican a curl igual que a los navegadores. /api/health sigue ejecutando su manejador y /robots.txt sigue sirviendo el archivo.

Contenido del fotograma

El fotograma es el primer renderizado de la página, como en una estructura prerenderizada: cada límite <Suspense> que sigue esperando muestra su contenido alternativo. Los componentes de servidor asíncronos no se ejecutan y fetch() nunca se resuelve, por lo que los datos cargados en efectos permanecen en su estado de carga.

  • Tamaño: 80 × 24 celdas. Una app con un área de visualización fija (viewport.responsive: false) usa viewport.width × viewport.height en su lugar.
  • Colores: códigos de escape SGR de 24 bits en el viewport.theme de la app. Cada fila termina con un restablecimiento y el fotograma termina con un salto de línea.
  • Estado: 200, o 404 con la página de recurso no encontrado de la app cuando no hay ninguna página que coincida o la página llama a notFound(). Una página que llama a redirect() durante el renderizado sirve HTML.

Las respuestas son text/plain; charset=utf-8 con Vary: User-Agent, Accept y Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate, por lo que las cachés compartidas nunca almacenan un fotograma para después servirlo a un navegador. La página HTML de una ruta en la que curl recibe un fotograma incluye la misma cabecera Vary.

Dónde funciona

Entorno de alojamientoPáginas estáticasPáginas dinámicas, rutas desconocidas
text devRenderizadas bajo demandaRenderizadas bajo demanda
text start, bunPrerenderizadas por text buildRenderizadas bajo demanda
vercel, cloudflarePrerenderizadas por text buildPágina HTML
staticPágina HTMLPágina HTML

Las páginas renderizadas en el servidor necesitan text start o bun (consulta Despliegue).

Los alojamientos estáticos no pueden responder de forma distinta a cada cliente, por lo que el adaptador static no admite fotogramas. En Vercel y Cloudflare, los fotogramas de las páginas estáticas se incluyen en la compilación. Las páginas dinámicas ([id], force-dynamic) sirven HTML allí, porque los adaptadores vercel y cloudflare no despliegan un renderizador.

text start y bun dist/server.js renderizan las páginas restantes bajo demanda con .text/server/live.mjs y conservan los últimos 128 fotogramas durante 10 segundos. Cada servidor renderiza como máximo 20 páginas sin caché cada 10 segundos. Una vez superado ese límite, curl recibe la página HTML hasta que se renueva la cuota. Si no se puede cargar live.mjs en el servidor, por ejemplo porque un módulo de página lee window en el nivel superior, esas páginas sirven HTML.

text build informa de los fotogramas prerenderizados:

 ✓ Prerendering curl frames (5/5)

Configuración

Cambia el tamaño para toda la app o desactiva los fotogramas:

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

Una página puede cambiar su propio tamaño o servir HTML también a las terminales:

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

Los tamaños se limitan a 1–500 celdas. Con ansi: false en text.config.ts, se ignoran las exportaciones de las páginas.

HTTP sin cifrar

curl no sigue las redirecciones a menos que pases -L. Vercel redirige las solicitudes http:// a https://, al igual que Cloudflare con Usar siempre HTTPS activado, por lo que curl http://… imprime la redirección en lugar del fotograma. Comparte URL https://.

Servidores personalizados

@textjs/app/ansi exporta las funciones auxiliares de detección y respuesta para servidores y funciones que no ejecutan text start ni un 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) también acepta (method, headers) con Headers de la Web o IncomingHttpHeaders de Node. frameToAnsi(buffer, { theme }) codifica un CellBuffer renderizado del mismo modo que el framework.

Editar esta página en GitHub