Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Studio

brink-studio is the reference web authoring app for ink — a browser IDE built on the Web & WASM bindings. It’s both a usable editor and a worked example of how to assemble a full client: editor, live preview, project navigation, and screenplay mode, all driven by @brink-lang/web.

What it does

  • Multi-file ink editor (CodeMirror 6) with diagnostics, semantic highlighting, completions, hover, go-to-definition, find-references, rename, code actions, folding, signature help, and inlay hints — every EditorSession query wired to the editor.
  • Live player — step through the compiled story with choice selection; playback state persists to localStorage and replays on reload.
  • Screenplay dialect — character cues (@Name: line) render with hidden sigils, name coloring, and depth indicators. This is the configurable dialogue dialect, defaulting to the @Name: convention; it’s editor tooling and never reaches the runtime.
  • Project navigation — a binder tree of knots and stitches (function knots marked with a distinct icon) with drag-to-reorder and structural edits, plus file tabs (pinned/unpinned) and symbol tabs.
  • Activity-bar sidebar — a VS Code-style icon column that swaps the left dock between views; the binder is the first view, the state view the second.
  • State view — a read-only runtime debugger that renders the structured, name-resolved DebugState snapshot: status, current location, globals (with changed values highlighted), call stack, visit counts, and pending choices, refreshed as the story advances.
  • Line-element switching — convert a line between narrative, choice, sticky choice, gather, and divert via keyboard or UI.
  • Auto-fix — one-click and batch fixes for diagnostics, from the Problems panel, the editor, and the command palette, plus a fix-on-save setting.

Architecture

The studio is a pnpm workspace of focused packages. The app shell is thin; the capability lives in libraries, each independently testable.

PackageResponsibility
@brink-lang/studioapp shell + entry point (Vite)
@brink/studio-uiReact components: layout, activity bar, binder, state view, player, tabs, status bar
@brink/studio-storeZustand store — editor / compile / documents / binder / session / search / conflict / output / symbol-menu slices
@brink-lang/editorthe CodeMirror 6 editor, IDE extensions, and the dialogue dialect
@brink/ink-operationspure line-editing functions (no CM6, React, or wasm)
@brink-lang/webergonomic wrappers over the brink-web FFI
@brink/wasm-typesshared TypeScript interfaces (zero runtime) — decouples everything from the FFI

The dependency flow is one-directional: @brink/wasm-types is depended on by all; @brink-lang/web wraps the raw brink-web module; @brink-lang/editor consumes @brink-lang/web + @brink/ink-operations; @brink/studio-store orchestrates editor, compile, and player state; @brink-lang/studio assembles the lot.

Running it

The WASM packages must exist first — @brink-lang/web resolves brink-web through a file: path to crates/brink-web/www/pkg, and the studio resolves brink-prose (the prose checker, loaded on demand) the same way to crates/brink-prose/www/pkg. pnpm install:checked refuses to install until both are built:

# 1. build the wasm packages (see Web & WASM)
wasm-pack build crates/brink-web --target web --out-dir www/pkg
wasm-pack build crates/brink-prose --target web --out-dir www/pkg

# 2. install + run the studio
pnpm install:checked
pnpm dev            # Vite dev server on http://localhost:5180
CommandPurpose
pnpm devdev server (port 5180)
pnpm buildproduction build
pnpm typecheckTypeScript, no emit
pnpm testVitest unit tests (jsdom)
pnpm test:e2ePlaywright end-to-end suite

Tech stack

React 19 · TypeScript 5.7 · Vite 6 · Zustand 5 · CodeMirror 6 · react-resizable-panels for layout · Vitest + Playwright for tests. The editor talks to the toolchain entirely through @brink-lang/web, so it stays a pure front-end with the compiler and runtime living in the WASM module.