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.

Terminal-HTTP-Clients erhalten den ersten Frame einer Seite als Truecolor-ANSI-Text statt des HTML-Dokuments. Du musst nichts konfigurieren.

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

Anfragen, die einen Frame erhalten

Eine Anfrage erhält einen Frame, wenn alle folgenden Bedingungen erfüllt sind:

  • Die Methode ist GET oder HEAD;
  • der User-Agent beginnt mit curl/, Wget/, wget2/, HTTPie/ oder xh/;
  • der Accept-Header fehlt oder enthält kein text/html.

Browser, Crawler und Linkvorschauen erhalten die HTML-Seite. Um mit curl das HTML zu erhalten, fordere es an:

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

Der Frame wird an der Stelle ausgewählt, an der die Seite ausgeliefert würde: nach Middleware, rewrites und Route-Handlern, und niemals für Dateien oder Pfade, deren letztes Segment einen Punkt enthält. Middleware-Weiterleitungen, 401-Antworten, Header und Rewrites gelten für curl genauso wie für Browser. /api/health führt weiterhin seinen Handler aus und /robots.txt liefert weiterhin die Datei aus.

Inhalt des Frames

Der Frame ist das erste Rendering der Seite, wie bei einer vorgerenderten Shell: Jede <Suspense>-Grenze, die noch wartet, zeigt ihren Fallback. Asynchrone Server-Komponenten werden nicht ausgeführt und fetch() wird nie aufgelöst, sodass Daten, die in Effekten geladen werden, im Ladezustand bleiben.

  • Größe: 80 × 24 Zellen. Eine App mit festem Viewport (viewport.responsive: false) verwendet stattdessen viewport.width × viewport.height.
  • Farben: 24-Bit-SGR-Escape-Codes im viewport.theme der App. Jede Zeile endet mit einem Reset und der Frame endet mit einem Zeilenumbruch.
  • Status: 200 oder 404 mit der Nicht-gefunden-Seite der App, wenn keine Seite passt oder die Seite notFound() aufruft. Eine Seite, die beim Rendern redirect() aufruft, liefert HTML aus.

Antworten haben den Typ text/plain; charset=utf-8 mit Vary: User-Agent, Accept und Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate, damit gemeinsam genutzte Caches niemals einen Frame speichern und an einen Browser ausliefern. Die HTML-Seite unter einem Pfad, an dem curl einen Frame erhält, enthält denselben Vary-Header.

Unterstützte Umgebungen

HostStatische SeitenDynamische Seiten, unbekannte Pfade
text devBei Anfrage gerendertBei Anfrage gerendert
text start, bunDurch text build vorgerendertBei Anfrage gerendert
vercel, cloudflareDurch text build vorgerendertHTML-Seite
staticHTML-SeiteHTML-Seite

Serverseitig gerenderte Seiten benötigen text start oder bun (siehe Deployen).

Statische Hosts können einem Client nicht anders antworten als einem anderen, deshalb unterstützt der static-Adapter keine Frames. Auf Vercel und Cloudflare werden Frames für statische Seiten mit dem Build ausgeliefert. Dynamische Seiten ([id], force-dynamic) liefern dort HTML aus, weil die Adapter vercel und cloudflare keinen Renderer deployen.

text start und bun dist/server.js rendern die übrigen Seiten bei Anfrage mit .text/server/live.mjs und halten die letzten 128 Frames für 10 Sekunden vor. Jeder Server rendert höchstens 20 nicht gecachte Seiten pro 10 Sekunden. Danach erhält curl die HTML-Seite, bis das Budget wieder aufgefüllt ist. Wenn live.mjs auf dem Server nicht geladen werden kann, etwa weil ein Seitenmodul auf oberster Ebene auf window zugreift, liefern diese Seiten HTML aus.

text build meldet die vorgerenderten Frames:

 ✓ Prerendering curl frames (5/5)

Konfiguration

Ändere die Größe für die gesamte App oder schalte Frames aus:

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

Eine Seite kann ihre eigene Größe ändern oder auch an Terminals HTML ausliefern:

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

Größen werden auf 1–500 Zellen begrenzt. Mit ansi: false in text.config.ts werden Seitenexporte ignoriert.

Unverschlüsseltes HTTP

curl folgt Weiterleitungen nur, wenn du -L übergibst. Vercel leitet http://-Anfragen auf https:// um, ebenso Cloudflare bei aktiviertem Immer HTTPS verwenden, sodass curl http://… die Weiterleitung statt des Frames ausgibt. Teile https://-URLs.

Eigene Server

@textjs/app/ansi exportiert Hilfsfunktionen zur Erkennung und für Antworten, für Server und Funktionen, die weder text start noch einen Adapter ausführen:

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) akzeptiert auch (method, headers) mit Web-Headers oder Nodes IncomingHttpHeaders. frameToAnsi(buffer, { theme }) kodiert einen gerenderten CellBuffer genauso wie das Framework.

Diese Seite auf GitHub bearbeiten