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.
Les clients HTTP en terminal reçoivent la première frame d’une page sous forme de texte ANSI en couleurs vraies au lieu du document HTML. Vous n’avez rien à configurer.
curl https://my-app.example.com/aboutRequêtes recevant une frame
Une requête reçoit une frame lorsque toutes ces conditions sont réunies :
- la méthode est
GETouHEAD; - le
User-Agentcommence parcurl/,Wget/,wget2/,HTTPie/ouxh/; - l’en-tête
Acceptest absent ou ne mentionne pastext/html.
Les navigateurs, les robots d’indexation et les aperçus de liens reçoivent la page HTML. Pour obtenir le HTML avec curl, demandez-le :
curl -H 'Accept: text/html' https://my-app.example.com/aboutLa frame est choisie au moment où la page serait servie : après les middlewares, les rewrites et les gestionnaires de route, et jamais pour les fichiers ou les chemins dont le dernier segment contient un point. Les redirections des middlewares, les réponses 401, les en-têtes et les réécritures s’appliquent à curl comme aux navigateurs. /api/health exécute toujours son gestionnaire et /robots.txt sert toujours le fichier.
Contenu de la frame
La frame est le premier rendu de la page, comme dans une coquille prérendue : chaque limite <Suspense> encore en attente affiche son contenu de repli. Les composants serveur asynchrones ne s’exécutent pas et fetch() ne se résout jamais, donc les données chargées dans les effets restent dans leur état de chargement.
- Taille : 80 × 24 cellules. Une application avec une zone d’affichage fixe (
viewport.responsive: false) utilise plutôtviewport.width × viewport.height. - Couleurs : codes d’échappement SGR sur 24 bits dans le
viewport.themede l’application. Chaque ligne se termine par une réinitialisation, et la frame se termine par un saut de ligne. - Statut :
200, ou404avec la page introuvable de l’application lorsqu’aucune page ne correspond ou que la page appellenotFound(). Une page qui appelleredirect()pendant le rendu sert du HTML.
Les réponses sont de type text/plain; charset=utf-8 avec les en-têtes Vary: User-Agent, Accept et Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate, afin que les caches partagés ne stockent jamais une frame pour la servir à un navigateur. La page HTML à un chemin où curl reçoit une frame porte le même en-tête Vary.
Environnements compatibles
| Hébergement | Pages statiques | Pages dynamiques, chemins inconnus |
|---|---|---|
text dev | Rendu à la demande | Rendu à la demande |
text start, bun | Prérendu par text build | Rendu à la demande |
vercel, cloudflare | Prérendu par text build | Page HTML |
static | Page HTML | Page HTML |
Les pages avec rendu côté serveur nécessitent text start ou bun (voir Déploiement).
Les hébergements statiques ne peuvent pas répondre différemment selon le client, donc l’adaptateur static ne prend pas en charge les frames. Sur Vercel et Cloudflare, les frames des pages statiques sont livrées avec le build. Les pages dynamiques ([id], force-dynamic) y servent du HTML, car les adaptateurs vercel et cloudflare ne déploient pas de moteur de rendu.
text start et bun dist/server.js rendent les pages restantes à la demande avec .text/server/live.mjs et conservent les 128 dernières frames pendant 10 secondes. Chaque serveur rend au maximum 20 pages non mises en cache par tranche de 10 secondes. Au-delà, curl reçoit la page HTML jusqu’à ce que le quota se renouvelle. Si live.mjs ne peut pas être chargé sur le serveur, par exemple parce qu’un module de page lit window au niveau supérieur, ces pages servent du HTML.
text build indique les frames prérendues :
✓ Prerendering curl frames (5/5)Configuration
Modifiez la taille pour toute l’application ou désactivez les frames :
import { defineConfig } from "@textjs/app";export default defineConfig({ ansi: { cols: 100, rows: 30 }, // ansi: false,});Une page peut modifier sa propre taille ou servir du HTML aux terminaux également :
export const ansi = { cols: 120, rows: 40 };// export const ansi = false;Les tailles sont limitées à 1–500 cellules. Avec ansi: false dans text.config.ts, les exports des pages sont ignorés.
HTTP en clair
curl ne suit pas les redirections à moins que vous ne passiez -L. Vercel redirige les requêtes http:// vers https://, tout comme Cloudflare lorsque l’option Always Use HTTPS est activée, donc curl http://… affiche la redirection au lieu de la frame. Partagez des URL https://.
Serveurs personnalisés
@textjs/app/ansi exporte les fonctions utilitaires de détection et de réponse pour les serveurs et les fonctions qui n’exécutent ni text start ni un adaptateur :
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) accepte aussi (method, headers) avec les Headers de l’API Web ou les IncomingHttpHeaders de Node. frameToAnsi(buffer, { theme }) encode un CellBuffer rendu de la même manière que le framework.