Getting Started - rahulpandita/react-term GitHub Wiki
This guide covers installing react-term, configuring cross-origin isolation for SharedArrayBuffer, and connecting the terminal to a PTY or WebSocket.
Prerequisites
- Node.js ≥ 18 (for development in the monorepo; no Node.js runtime requirement in the browser)
- pnpm ≥ 8 for the monorepo:
npm install -g pnpm - Cross-origin isolation — required to enable SharedArrayBuffer and full off-main-thread mode. The page must be served with
Cross-Origin-Opener-Policy: same-originandCross-Origin-Embedder-Policy: require-corp - WebGL2 — required for hardware-accelerated rendering; falls back to Canvas 2D automatically when unavailable
Installation
For a React (web) project:
npm install `@next_term/react` `@next_term/web`
# or
pnpm add `@next_term/react` `@next_term/web`
# or
yarn add `@next_term/react` `@next_term/web`
For a React Native project:
npm install `@next_term/native` `@next_term/core`
# Peer dependencies:
npm install `@shopify/react-native-skia` react-native-gesture-handler
Configuration
SharedArrayBuffer requires cross-origin isolation. Without these headers, react-term automatically falls back to main-thread parsing and Canvas 2D rendering.
Express
app.use((req, res, next) => {
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
next();
});
Vite
// vite.config.ts
export default {
server: {
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
},
};
Next.js
// next.config.js
module.exports = {
async headers() {
return [{
source: '/(.*)',
headers: [
{ key: 'Cross-Origin-Opener-Policy', value: 'same-origin' },
{ key: 'Cross-Origin-Embedder-Policy', value: 'require-corp' },
],
}];
},
};
Note:
require-corpblocks cross-origin resources that lack aCross-Origin-Resource-Policyheader. CDN-hosted fonts and images may needcrossorigin="anonymous"and a CORP header on the server.
Rendering Strategies
react-term selects the best strategy automatically at runtime:
| Strategy | Condition | Benefit |
|---|---|---|
| Full Worker | SAB + OffscreenCanvas available | Zero main-thread parser and render work |
| Parser Worker | SAB available, no OffscreenCanvas | Parser off-thread; rendering on main thread |
| Main Thread | Neither available | Universal fallback via Canvas 2D |
The renderMode prop on Terminal can override the automatic selection to force 'webgl' or 'canvas2d'.
Connecting to a PTY or WebSocket
The onData callback fires whenever the user types or pastes. Forward the data to your PTY process or WebSocket, then write responses back with ref.current?.write().
import { useRef, useEffect } from 'react';
import { Terminal, type TerminalHandle } from '`@next_term/react`';
function PtyTerminal() {
const ref = useRef(TerminalHandle)(null);
const socket = useRef(WebSocket)();
useEffect(() => {
socket.current = new WebSocket('wss://yourserver/pty');
socket.current.binaryType = 'arraybuffer';
socket.current.onmessage = (e) => {
ref.current?.write(
e.data instanceof ArrayBuffer ? new Uint8Array(e.data) : e.data,
);
};
return () => socket.current?.close();
}, []);
return (
(Terminal
cols={80}
rows={24}
autoFit={true}
onData={(data) =) socket.current?.send(data)}
onResize={(cols, rows) => {
socket.current?.send(JSON.stringify({ type: 'resize', cols, rows }));
}}
ref={ref}
/>
);
}