콘솔 프레임워크

console.log 안에 렌더링되는 풀스택 React 앱을 만드세요.

시작하기

이 페이지는 콘솔에서 실행 중이에요. ⌘⌥JCtrl+Shift+J⌘⌥KCtrl+Shift+K⌘⌥C로 열고 (먼저 개발자 기능을 켜세요), 아래 미리보기를 클릭한 다음 ↑ ↓를 누르세요.

1import { useState } from "react";2import { AsciiFont, Box, Text, useInput } from "@textjs/app";34export default function Page() {5  const [count, setCount] = useState(0);6  useInput((e) => {7    if (e.key === "up") setCount((c) => c + 1);8    if (e.key === "down") setCount((c) => c - 1);9  });1011  return (12    <Box className="flex-col gap-1 p-2">13      <AsciiFont text="▼ TEXT.JS" />14      <Text color="muted">React 19 in console.log</Text>15      <Text bold color="accent">count = {count}</Text>16    </Box>17  );18}
viewport:3

React 19

Text.js는 동시 렌더링, Suspense, 에러 바운더리를 지원해요.

App Router

app/의 폴더는 라우트와 레이아웃이 되고, 뒤로 가기, 앞으로 가기, 딥 링크가 작동해요.

반응형 그리드

페이지 확대 비율에 관계없이 그리드가 도킹된 DevTools 패널에 맞춰져요.

키보드 입력

키 입력, 붙여넣기, IME 조합이 숨겨진 <textarea> 하나로 앱에 전달돼요.

표, 차트, 폼과 단축키

실시간
preview://table:1
↑ ↓ 이동 · s 정렬 · Space 선택
문서
레이아웃
  • <Box>
  • <Stack>
  • <Grid>
  • <SplitPane>
  • <ScrollBox>
  • <Center>
데이터
  • <List>
  • <Table>
  • <Tree>
  • <Markdown>
  • <Code>
  • <Diff>
차트
  • <LineChart>
  • <BarChart>
  • <Sparkline>
  • <ProgressBar>
  • <Gradient>
  • <Image>
컨트롤
  • <Input>
  • <Select>
  • <Checkbox>
  • <Switch>
  • <Slider>
  • <Dialog>
키보드
  • useKeymap
  • <KeyHelp>
  • <KeyHints>
  • <CommandPalette>
  • <StatusBar>
  • useFocus

변경된 프레임마다 console.log 호출 1회

셀을 바꾸지 않는 커밋은 콘솔에 도달하지 않아요.

  1. React 19

    01커밋

    React는 커스텀 리컨실러로 커밋해요.

  2. Yoga

    02레이아웃

    Yoga는 박스를 정수 단위 셀에 배치해요.

  3. CellBuffer

    03그리기

    손상된 행만 다시 그려요.

  4. 행 해시

    04변경 감지 게이트

    변경 없는 프레임은 여기서 멈춰요.

  5. RLE

    05인코딩

    셀 3,200개가 %c 스팬 149개로 바뀌어요.

  6. console.log

    06출력

    프레임은 최소 66ms 간격으로 덧붙여요.

변경된 프레임 변경 없는 프레임, 호출 0회

덧붙인 프레임

프레임마다 콘솔을 지우면 DevTools가 다음 프레임을 그릴 때까지 빈 화면이 보여요. Turbolog는 각 프레임을 덧붙여요.

글 읽기
clear() + log()70.6% 빈 화면
log(), appended1.0% 빈 화면
0.163ms전체 다시 그리기(레이아웃, 그리기, 인코딩)
0.011ms키 입력 등에 따른 한 행 수정
0회 호출유휴 프레임
149개 스팬셀 3,200개에 쓰는 %c 인수
100×32 대시보드, 1,000프레임 평균 · Apple M5 Pro · Bun 1.4.4Turbolog 엔진 문서

서버에서 라우트 렌더링

라우트와 비동기 컴포넌트를 서버에서 렌더링하려면 runtime = "server"를 내보내세요. 브라우저는 앱 대신 21kB(gzip) 프레임 플레이어를 로드해요.

1import { Suspense } from "react";2import { Box, Text } from "@textjs/app";3import { db } from "@/lib/db";45export const runtime = "server";67async function Deploys() {8  const rows = await db.deploys.latest(5);9  return rows.map((d) => (10    <Text key={d.id}>{`${d.state}  ${d.branch}`}</Text>11  ));12}1314export default function Page() {15  return (16    <Box className="flex-col p-1">17      <Text bold>Deployments</Text>18      <Suspense fallback={<Text color="muted">Loading…</Text>}>19        <Deploys />20      </Suspense>21    </Box>22  );23}

DevTools에서 OpenCode로 코딩

OpenCode Lite는 브라우저 콘솔에서 실행되도록 Text.js로 다시 만든 OpenCode TUI예요.

샌드박스

설치 없이 스크립트 기반 에이전트가 모든 프롬프트에 답해요.

명령어 하나

bunx @textjs/opencode@latest proxy를 실행하고 출력된 코드를 입력하세요. 페이지가 로컬 컴퓨터의 OpenCode에 연결돼요.

모델과 세션

/models로 서버에 설정된 모델을 선택하세요. 세션, 에이전트, 모델은 OpenCode 서버에서 가져와요.