Skip to main content
OpenTUI is built on a high-performance native core written in Zig, providing the foundation for fast terminal rendering and text manipulation. This guide covers the architecture, building from source, and working with the FFI layer.

Architecture Overview

OpenTUI’s architecture consists of three main layers:

TypeScript Layer

  • High-level components and APIs
  • Event handling and state management
  • React/Solid bindings
  • Application logic

FFI Layer

  • Bun’s native FFI for zero-overhead calls
  • Type-safe bindings with bun-ffi-structs
  • Efficient data transfer between layers

Zig Core

  • Low-level rendering primitives
  • Optimized buffer management
  • UTF-8 and grapheme processing
  • Text buffer and rope data structures
  • ANSI escape sequence generation

Core Components

The Zig core provides several key modules:

Renderer (renderer.zig)

Core rendering engine that manages:
  • Frame buffer operations
  • Diff-based rendering
  • ANSI sequence generation
  • Cursor management
  • Terminal state

Buffer (buffer.zig)

Optimized buffer management:
  • Zero-copy operations
  • Efficient memory layout
  • Color and attribute storage
  • Character-level manipulation

Text Buffer (text-buffer.zig)

High-performance text editing:
  • Line-based text storage
  • Efficient insertions/deletions
  • Selection handling
  • Syntax highlighting support
  • Viewport management

Rope (rope.zig)

Efficient string data structure:
  • Fast insertions at any position
  • Memory-efficient for large texts
  • Supports markers and ranges
  • Used by text buffer internally

UTF-8 Processing (utf8.zig)

  • Unicode grapheme clustering
  • Width calculation (wcwidth)
  • ZWJ (Zero Width Joiner) handling
  • Emoji support
  • East Asian width detection

Native Span Feed (native-span-feed.zig)

Stream-based rendering:
  • Efficient ANSI processing
  • Chunk-based data flow
  • Zero-copy where possible
  • Async-friendly

Building from Source

Prerequisites

Bun Install Bun (JavaScript runtime):
Zig Install Zig 0.15.2 (exact version required):
OpenTUI requires exactly Zig 0.15.2. Other versions will not work due to language changes.

Clone Repository

Build Native Core

Build the Zig native libraries:
This compiles:
  • Native Zig code to shared libraries
  • For your current platform (x64/arm64, Linux/macOS/Windows)
  • Optimized for release by default

Build for Development

Development builds include debug symbols:

Build for All Platforms

Cross-compile for all supported platforms:
Supported targets:
  • x86_64-linux
  • aarch64-linux
  • x86_64-macos (Intel)
  • aarch64-macos (Apple Silicon)
  • x86_64-windows
  • aarch64-windows

Build Specific Platform

Build System (build.zig)

OpenTUI uses Zig’s build system:

Build Options

Build Steps

Filter Tests

TypeScript-Only Changes

When changing TypeScript code, you don’t need to rebuild! The native core only needs rebuilding when Zig code changes.

FFI Layer

The FFI layer uses Bun’s native FFI for calling Zig functions from TypeScript.

Loading the Library

FFI Function Signature

Passing Structures

Use bun-ffi-structs for complex data:

Calling Native Functions

Memory Management

The native core manages its own memory:
Always destroy native objects when done to prevent memory leaks.

Development Workflow

1. Changing TypeScript Code

2. Changing Zig Code

3. Running Tests

4. Benchmarking

Local Development Linking

Link your local OpenTUI to another project:

Options

The script links:
  • @opentui/core
  • @opentui/react or @opentui/solid (if specified)
  • Peer dependencies (yoga-layout, react, solid-js, etc.)
  • Subdependencies like opentui-spinner (with —subdeps)

Debugging Native Code

Enable FFI Debug Logging

Use Debug Build

Debug with LLDB/GDB

Memory Debugging

Enable GPA safety checks:
This tracks:
  • Memory allocations
  • Leaks
  • Double-frees
  • Use-after-free

Key Zig Modules

The native core includes:
  • lib.zig - Main FFI exports
  • renderer.zig - Core rendering engine
  • buffer.zig - Frame buffer management
  • text-buffer.zig - Text editor buffer
  • rope.zig - Rope data structure
  • utf8.zig - UTF-8 and grapheme processing
  • terminal.zig - Terminal capabilities
  • ansi.zig - ANSI escape sequences
  • grapheme.zig - Grapheme boundary detection
  • editor-view.zig - Editor viewport
  • edit-buffer.zig - Edit operations
  • syntax-style.zig - Syntax highlighting
  • event-bus.zig - Native event system
  • logger.zig - Native logging
  • native-span-feed.zig - Stream rendering

Dependencies

The Zig core uses:
  • uucode - Unicode data (grapheme breaks, widths, emoji)
  • std - Zig standard library
Configured in build.zig.zon:

Performance Considerations

Zero-Copy Operations

The FFI layer uses pointers to avoid copying:

Batch Operations

Batch FFI calls to reduce overhead:

Memory Pooling

The native core uses memory pools for:
  • Render buffers
  • Text segments
  • Rope nodes
  • Event objects

Contributing to Native Core

When contributing Zig code:
  1. Follow style guide
    • Use Zig fmt: zig fmt src/
    • Follow existing naming conventions
    • Add tests for new features
  2. Write tests
  3. Benchmark performance
  4. Update FFI bindings
    • Export new functions in lib.zig
    • Add TypeScript bindings
    • Update type definitions
  5. Document behavior
    • Add comments for public APIs
    • Update relevant docs

Next Steps

Performance

Learn performance optimization

Testing

Test your TUI applications