Skip to content

Introduction

JSVision is a TypeScript SDK for full-screen, event-driven applications rendered in terminal cells. Instead of printing a result and exiting, a JSVision program keeps a view tree alive, receives keyboard and mouse input, updates state, and paints new frames until the application quits.

This course gives you the map before the details. You will learn what the application owns, what the host runtime owns, run a small real application, and choose the next Guide course for your goal.

Who this course is for

Start here if you are comfortable reading a short TypeScript program but have not built a terminal UI before. There are no JSVision prerequisites. To run the Node example locally you need Node 22 or newer, an ESM project, and an interactive terminal; the next course walks through that setup.

By the end, you should be able to:

  • explain the difference between application code, the JSVision event loop, and a host runtime;
  • recognize the rendered terminal frame as output rather than application state;
  • run a first application and quit it cleanly; and
  • choose the next course without learning packages, layout, or reactivity out of order.

Mental model

Keep three responsibilities separate:

LayerOwnsDoes not own
ApplicationViews, state, commands, focus, and the decision to quitReading terminal bytes or restoring terminal modes
Host runtimeInput, resize events, capability-aware terminal setup, and frame deliveryYour feature state or screen structure
Terminal frameThe cells currently visible to the userThe durable source of truth for the application

The data moves in both directions:

text
keyboard · mouse · resize

host runtime → event loop → application views and state
          ↑                         ↓
          └──────── rendered terminal frame

createApplication() assembles the application shell and event loop. On Node, app.run() connects that loop to the terminal host, enters the interactive screen, forwards input and resizes, and writes rendered frames. When the quit command resolves—or startup or runtime work throws—the run path restores the terminal in its cleanup path.

The live examples on this site use a browser host instead of app.run(). They still mount a real application and drive its real event loop; the surrounding docs helper is not part of the public API you copy into a project.

Your first JSVision application

This is a complete application with one body view and one discoverable quit command:

ts
import { Commands, Text, createApplication, statusItem, statusLine } from '@jsvision/ui';

const app = createApplication({
  content: new Text('Hello from JSVision'),
  statusLine: statusLine([statusItem('~Alt-X~ Quit', Commands.quit, 'Alt+X')]),
});

const exitCode = await app.run();
process.exitCode = exitCode;

Important details:

  • content is the application body. Passing a body creates a full-screen content application; omitting it gives you the classic Desktop window manager.
  • statusItem() makes the quit action and its key chord visible instead of hiding them in code.
  • The first argument is the displayed label. ~Alt-X~ marks its emphasized segment, while the third argument binds the real Alt+X chord.
  • app.run() resolves with the exit code carried by the quit command. Setting process.exitCode lets normal JavaScript cleanup finish.

Menus, windows, layouts, and reactive state are deliberately absent. They are later lessons, not requirements for a first result.

Run the application

After completing Install & packages, save the snippet as src/main.ts and run it with the TypeScript runner configured by that course:

sh
npx tsx src/main.ts

The screen should show the text body and a status line. Press Alt+X to emit the standard quit command. A successful result is not merely “text appeared”: input reached the event loop, the application produced a frame, and the host restored the terminal after the loop ended.

The laboratory below makes those boundaries visible. Press Alt+N or activate Next stage to follow one frame from application construction, through the host runtime, to the terminal. Press Alt+R to reset the explanation.

Advance through application, host runtime, and terminal-frame stages to see what each layer owns.

Common first-run failures

SymptomLikely causeCorrectionEvidence
Node reports an unsupported module or require() errorThe project is not using the required ESM setupFollow the package and TypeScript configuration exactlyThe public import resolves before the app starts
Startup reports that terminal essentials are not metThe process has no interactive TTY, such as a redirected or CI runRun it in an interactive terminal; use a deliberate headless harness for testsThe app enters its interactive screen instead of failing before host setup
The process keeps running after the first frameA full-screen app is event-driven and waits for a quit commandKeep the visible quit status item and press Alt+Xapp.run() resolves and the normal shell returns
A browser example works but the copied program cannot import its helperThe docs shell is repository infrastructure, not consumer APIImport createApplication from @jsvision/uiTypeScript resolves only public package exports

Do not “fix” a missing TTY by disabling the runtime check in a production entry point. The requireTty: false option exists for a controlled headless harness with injected input and output, not for making an unusable interactive process appear healthy.

Best practices

  • Keep the application model host-neutral. Put feature state and commands in the application; later Node and browser hosts can drive the same model without owning it.
  • Give every important action a visible path. A status or menu hint makes quit and recovery discoverable to keyboard users.
  • Treat the rendered frame as evidence, not state. Tests may inspect frames, but business state belongs in signals and models so it remains explainable and reusable.
  • Let run() own the terminal lifecycle. Bypassing its cleanup path risks leaving raw mode or the alternate screen active after an error.

Choose your next course

Your goalContinue withWhy
Run the snippet locally or choose packagesInstall & packagesEstablish Node 22+, ESM, TypeScript, and supported imports first
Arrange views into a responsive screenLayoutLearn terminal-cell geometry and size negotiation
Connect changing data to the interfaceReactive stateLearn signals, derived state, effects, and ownership
Use JSVision through CodexCodex pluginInstall the supported integration and understand its canonical sources

After those foundations, The application shell teaches menus, desktops, windows, status composition, and the complete lifecycle.

Practice

  1. Before running the lab, predict which layer owns keyboard decoding and which owns the quit command. Advance the stages and check your answer.
  2. Change the greeting text in the snippet. Explain why this changes application state and the resulting frame but not the host runtime.
  3. As a reading exercise, temporarily remove the visible status item. Notice that this also removes the snippet's Alt+X binding: registering Commands.quit does not create an input path by itself. Restore the item before running the application.

Learning path

The Guide is a curriculum, not a symbol index. Follow it in order when you are new, or enter at a course whose prerequisites you already understand. Complete courses meet the current course and live-lab directive. If future Upgrade or Planned entries appear, they remain visible here while incomplete pages stay out of the sidebar.

Getting started

CourseStagePurpose
IntroductionCompleteUnderstand the product, run the live shell, and choose a learning path.
Install & packagesCompleteChoose packages and configure a Node 22+ ESM project.
Codex pluginCompleteUse the supported agent integration and canonical JSVision guidance.

Core concepts

CourseStagePurpose
LayoutCompleteCompose responsive cell layouts, overlays, and exact placement.
Reactive stateCompleteModel state, derived values, bindings, effects, and lifetimes.
Views & focusCompleteUnderstand retained trees, mounting, invalidation, tab order, and focus restoration.
Events, commands & keymapsCompleteRoute input and design discoverable command systems.
Keyboard & clipboardCompleteUse editing chords and authorized clipboard adapters.
Text, Unicode & terminal cellsCompleteHandle graphemes, wide glyphs, wrapping, clipping, and ASCII-safe fallbacks.
Scrolling, lists & large contentCompleteDesign viewports, selection, scrolling, and bounded rendering.

Building applications

CourseStagePurpose
The application shellCompleteBuild and run menus, status, commands, desktops, and windows.
Dialogs & modalityCompleteBuild validated, cancellable, focus-safe modal workflows.
Async work, cancellation & progressCompleteKeep input responsive while handling progress, cancellation, cleanup, and stale results.
FormsCompleteBuild typed field state, validation, async submission, and reset.
Files & the FileSystem seamCompleteRun the same file workflows over native, virtual, and custom hosts.
InternationalizationCompleteAuthor, load, validate, switch, format, and test locales.
Screens & routingCompleteBuild typed screen stacks with history, parameters, shared chrome, and focus.
Theming & colour depthCompleteAuthor semantic themes that preserve meaning as color capabilities degrade.

Extending and integrating

CourseStagePurpose
Running in the browserCompleteMount unchanged applications through the browser host and virtual seams.
Writing your own widgetCompleteImplement measurement, drawing, focus, input, reactivity, and cleanup.
Testing headlesslyCompleteDrive views, input, dialogs, resize, and failures without a real terminal.
Application architecture & best practicesCompleteOrganize state, services, commands, screens, ownership, and feature boundaries.

Specialist courses

CourseStagePurpose
Data Grid courseCompleteProgress from typed sources and columns through editing, scaling, and personalization.
Code Editor courseCompleteBuild editor experiences from documents through languages, LSP, safety, and recovery.

Operating a real app

CourseStagePurpose
DebuggingCompleteDiagnose layout, focus, commands, rendering, capabilities, and lifecycle failures.
Crash safety & terminal restoreCompleteUnderstand restore guarantees, signals, essentials, and degradations.
Displaying untrusted text safelyCompletePrevent terminal injection and redact sensitive diagnostics.
Accessibility & resilient interactionCompleteDesign keyboard-complete, non-color-dependent, reduced-geometry interfaces.
Terminal capabilities & portabilityCompleteAdapt honestly across color, mouse, glyph, SSH, tmux, Windows, and browser environments.
In productionCompletePackage, deploy, observe, support, and set evidence-based expectations.
Build a complete applicationCompleteApply the complete curriculum in one beginner-to-production release workflow.

Where to next

  • Components — every widget, with a live example you can drive on each page.
  • Apps — complete sample applications, running in the browser.
  • Keyboard & clipboard — the selection and clipboard chords every editable widget gets for free.
  • API reference — the generated reference for every public symbol.