Text.js framework renders full React apps inside console.log
Text.js calls itself "the Console Framework" and promises to "build full-stack React apps that render inside console.log". The project's landing page is itself the demo: it says it is running in your console, which you open with the browser's DevTools shortcut, then click the preview and press the up and down arrows. The sample component on the page is a short React file that imports Box, Text, AsciiFont and useInput from "@textjs/app" and shows a count that changes on arrow keys.
The page says Text.js supports React 19 concurrent rendering, Suspense and error boundaries. It uses an App Router model: folders in app/ become routes and layouts, and Back, Forward and deep links work. The grid is responsive and fits the docked DevTools panel at any page zoom. Keys, paste and IME composition reach the app through one hidden textarea, and the page lists tables, charts, forms and shortcuts as things the console UI can show.
The rendering pipeline has six steps. React commits through a custom reconciler; Yoga lays out boxes on whole cells; a CellBuffer repaints only damaged rows; a row hash acts as a dirty gate that stops unchanged frames; run-length encoding turns 3,200 cells into 149 %c spans; and the frame is emitted with console.log, with frames appended at least 66ms apart. Every changed frame is one console.log call, and a commit that changes no cells never reaches the console.
The central trick is the appended frames, which the page calls Turbolog. Clearing the console before each frame leaves it blank until DevTools paints the next one, so Text.js appends each frame instead. The page's comparison shows 70.6% blank for clear() + log() against 1.0% blank for log(), appended.
On the server side, a route that exports runtime = "server" renders, along with its async components, on the server, and the browser loads a 21 kB (gzip) frame player instead of the app. The sample shows an async component reading the latest five deploys from a database inside Suspense. Every static route's first frame ships inside its HTML, so the console paints before JavaScript loads (the page calls this Partial Prerendering). It also lists middleware (middleware.ts with NextRequest, NextResponse and config.matcher) and caching (revalidate, unstable_cache and revalidateTag, with stale-while-revalidate). The deploy adapter, run with text build --adapter, targets static, bun, vercel or cloudflare; server-rendered routes need bun or text start.
The same app runs in three places. In DevTools it starts with text dev. In a terminal, text run renders the same App Router app in truecolor ANSI and runs route handlers in-process. For coding agents, text mcp lets them navigate routes, press keys and read each frame as plain text over MCP.
A showcase is OpenCode Lite, the OpenCode TUI rebuilt with Text.js to run in the browser console. A sandbox offers a scripted agent that answers any prompt with nothing to install. To connect it to real models, run bunx @textjs/opencode@latest proxy and enter the code it prints; the page then connects to OpenCode on your machine, and sessions, agents and models come from your OpenCode server (any model the server has configured can be picked with /models).
Tooling is part of the package: a DevTools extension with a component tree, frame inspector and per-frame timeline; a VS Code extension that previews the frame next to your code and scaffolds App Router files; an ESLint plugin (eslint-plugin-textjs) that catches DOM tags in console components, boxes inside text and glyphs Menlo does not have; and offscreen testing where you press keys and assert on lastFrame() in any test runner. Errors and warnings carry a TX code linking to a page that explains the fix, and a console REPL (window.text) can pause, resize, wireframe and copy the running app. Right-to-left text uses an implementation of the Unicode Bidirectional Algorithm that passes all 770,241 BidiTest.txt cases, and the FIGlet font parser reads .flf files and matches 273 outputs recorded from the figlet binary. A free course, "Build a deploy dashboard in your console", has 10 chapters and takes about 65 minutes.
Key facts
- Text.js renders React 19 apps (concurrent rendering, Suspense, error boundaries) inside the browser DevTools console through console.log, with an App Router style folder-based routing model.
- Each changed frame is one console.log call of %c spans: a 3,200-cell frame is run-length encoded into 149 spans, and frames are appended at least 66ms apart.
- Appending frames instead of clearing the console is the key trick; the page's comparison lists 70.6% blank for clear() + log() versus 1.0% blank for appended frames.
- Routes can render on the server with runtime = "server"; the browser then loads a 21 kB (gzip) frame player, and the deploy adapter targets static, bun, vercel or cloudflare.
- The same app also runs in a terminal with text run (truecolor ANSI) and is exposed to coding agents over MCP with text mcp; OpenCode Lite is the showcase app.
Why it matters
Most web tooling treats the console as a place for logs. Text.js treats it as a rendering surface and builds a whole React stack on it: routing, layouts, server rendering, middleware, caching and deployment adapters. The notable engineering idea is on the page itself: clearing the console before each frame leaves it blank until DevTools repaints, so frames are appended and only changed ones are emitted. The same component model also targets a terminal and an MCP interface for coding agents, so one app can serve a person in DevTools, a person in a shell and an agent.
Who it affects
React developers who want to build developer tools, dashboards or small apps that live in DevTools or a terminal, and people building tooling for coding agents. The OpenCode Lite demo points at users of OpenCode, since it rebuilds that TUI to run in the browser console and connects to an OpenCode server on the user's own machine.
How to use it
The quickest try is the landing page: open the DevTools console, click the preview and press the up and down arrows. In a project, text dev runs the app in DevTools, text run renders it in a terminal, and text mcp exposes it to agents. Folders in app/ become routes, and runtime = "server" moves a route to the server. Deployment goes through text build --adapter with static, bun, vercel or cloudflare targets; server-rendered routes need bun or text start. To try OpenCode Lite against real models, run bunx @textjs/opencode@latest proxy and enter the code it prints. The page also offers a free course of 10 chapters, about 65 minutes, and a DevTools extension, a VS Code extension, an ESLint plugin and offscreen testing helpers.
How solid is it
Everything here comes from the project's own landing page, which doubles as a live demo. The numbers (70.6% versus 1.0% blank, 3,200 cells to 149 spans, 21 kB gzip, 770,241 BidiTest.txt cases, 273 figlet outputs) are the project's claims. No author, company, maintainer or license is named on the page. No release date, version number or pricing is given. The page gives no measurement method, hardware or browser for the 70.6% and 1.0% figures. No independent benchmarks, user numbers or third-party reactions are given.
Risks and caveats
The feature list is large and unverified by anyone outside the project. Because no maintainer, license, version or roadmap is stated on the page, it is unclear how stable or supported the framework is. The ESLint plugin's mention of glyphs Menlo does not have hints that rendering depends on the console's font, and the page does not say which browsers beyond those implied by the DevTools shortcuts are supported. Server-rendered routes also need bun or text start, so they do not run on every static host.
“Build full-stack React apps that render inside console.log.”
— textjs.org, the project's landing page