VS Code

Live Preview of the console frame beside your code, App Router scaffolding, snippets and TX error links.

The Text.js extension for VS Code shows your console frame next to the code. It mirrors the app running under text dev, or renders the open file itself when nothing is running. It also adds App Router scaffolding, snippets and links for TX### error codes.

Install

The extension isn't on the Marketplace yet. Build the .vsix from the repository and install it:

cd packages/vscode-textjsbun run packagecode --install-extension vscode-textjs-1.0.0.vsix

It activates in any folder that contains a Text.js app: a text.config.ts, or a package that depends on @textjs/next and has an app/ directory. Monorepos with several apps work too.

Live Preview

Open a page.tsx, layout.tsx or component and run Text.js: Open Preview (⌘K V), or click the preview button in the editor title bar. The panel draws the frame in the same DevTools chrome and Menlo cells as your browser console.

The preview gets its frames from one of two sources. The badge in the toolbar shows which one is active:

SourceWhenWhat you see
Livetext dev is running and a browser tab has the app openThe real app, with its state, data and grid size
HeadlessNo dev server, or no tab openThe open file, rendered by the extension at the panel's size

auto (the default) uses Live when it can and Headless otherwise. Pin either one from the badge or with textjs.preview.mode.

Keyboard

Click the console to send keys to the app: arrows, Tab, shortcuts, typing and paste all work, like in the browser. Click outside the console to stop. Editor shortcuts such as ⌘P and ⌘⇧P still go to VS Code. Scrolling over the console sends wheel events.

In the address field you can type a route, such as /deployments/dpl_a1, to navigate either source.

Live mode

While a preview is open, the dev server asks connected tabs to stream their frames. Tabs send only the rows that changed, and stop sending when the preview closes, so an app with no preview open pays nothing. Saving a file goes through Fast Refresh, and the preview updates with the tab.

Turn on Follow (textjs.preview.followEditor) to move the browser tab to the route of the page.tsx you're editing.

Background tabs get no animation frames, so they normally hold their frames until they become visible again. While a preview is watching, a background tab draws a frame as soon as input arrives, so typing in the preview still updates. Animations in a background tab update about once per second. Put the app in its own window to keep them smooth.

Headless mode

The extension starts a small runner in your project. It loads route files through the project's own Vite and @textjs/next, so aliases, TypeScript and JSX behave the same as in text dev. It mounts the App Router at the route of the open file, with its layouts, using an in-memory history:

FilePreview
app/page.tsx/
app/(shop)/items/[id]/page.tsx/items/id (dynamic segments use their name)
app/blog/[[...slug]]/layout.tsx/blog
components/Card.tsxThe default export, or the first PascalCase export, with no props

Same-origin fetch("/api/...") calls run your route.ts handlers in-process, as with text run. The grid follows the panel's size, and saving any file in the app renders it again. Errors show above the frame, with links to their TX### pages.

Commands

CommandDescription
Text.js: Start Dev ServerRuns your dev script (or text dev) in a terminal
Text.js: Stop Dev ServerStops a dev server started from VS Code
Text.js: Open PreviewOpens the Live Preview for the active file
Text.js: Open in Browser ConsoleOpens the current route on the dev server. Then press ⌘⌥J
Text.js: New Pageapp/<route>/page.tsx with metadata and typed params
Text.js: New Layoutapp/<route>/layout.tsx
Text.js: New Route Handlerapp/<route>/route.ts with GET and POST
Text.js: New Loading UI / Error Boundary / Not Found Pageloading.tsx, error.tsx, not-found.tsx

The scaffolding commands are also in the Explorer context menu for folders. They accept App Router segments such as settings, blog/[slug], docs/[...path] and (marketing)/about, and refuse to put a page and a route.ts in the same segment. JavaScript projects (no tsconfig.json) get .jsx and .js files.

Snippets

PrefixInserts
txpage, txlayout, txloading, txerrorRoute files, named after their folder
txcA console component named after the file
txroute, txroutepRoute handlers, with or without params
box, boxb, text, scrollbox, link, spinnerComponents
input, select, tabsInteractive components
useInput, useKeymap, useFocus, useTheme, useViewport, useRouter, useIntervalHooks
metadata, txconfigRoute metadata and text.config.ts

Error codes

Hover a TX### code anywhere: in source, logs, the Output panel or a pasted stack trace. The hover shows its title, message and package, with a link to its page on textjs.org. Each code is also a link (⌘-click).

Status bar

The ▼ item shows the dev server state and the console grid size, for example ▼ :3000 120×36. Tabs report their size to the dev server whenever it changes, even with no preview open. Click the item for the main commands.

Settings

SettingDefaultDescription
textjs.preview.modeautoauto, live or headless
textjs.preview.followEditorfalseLive mode: follow the edited route
textjs.preview.fontSize12Cell font size (DevTools uses 12)
textjs.preview.runtimeNode.js binary for headless previews (default: the one bundled with VS Code)
textjs.devServer.urlDev server URL (default: discover on ports 3000–3010). Only http:// loopback addresses are used
textjs.devServer.commandCommand for Start Dev Server

Workspace Trust

The preview and the dev server run your project's code (its Vite config, text.config.* and components). In Restricted Mode the extension only offers snippets, scaffolding and error links, and ignores textjs.preview.runtime, textjs.devServer.command and textjs.devServer.url from workspace settings. Trust the workspace to turn the preview on. Files outside your workspace folders are never previewed.

How it works

text dev serves three endpoints for editors. They answer only to loopback connections addressed to a loopback host (localhost, 127.0.0.1, [::1]), and only to requests with no Origin or the dev server's own origin. Browsers' cross-site and no-cors requests are rejected:

Endpoint
GET /__textjs/statusProject root, connected tabs, grid size and current route
GET /__textjs/framesServer-sent events: one frame event per change, encoded as row deltas
POST /__textjs/inputA key, paste, wheel or navigation for the tab. Requires JSON and the x-textjs-mirror: 1 header, so other sites can't send keystrokes

Tabs send frames to the dev server over Vite's HMR socket, which requires a per-server token. The wire format is exported from @textjs/next/frame-protocol (FrameEncoder, FrameDecoder, parseInputMessage) if you want to build your own viewer. None of this exists in text build output.