Separate the native implementation from the TypeScript bindings. Keep
core on
the public bindings and keep the current native artifact packages and
release
workflows.
packages/native owns the Zig source, tests, benches, and vendor updates.
The
package is private and unpublished for now Core still packages the
@opentui/core-* artifacts. build:native, test:native, and bench:native
still
work from core and delegate to native.
Expose a Zig import root and a no-JS hello example for proof of concept,
not a focus point, just a smoke test.
Pack the dist artifacts, install them into a fresh Node project, and
import every public entrypoint to verify the published shape. Wire the
script into the keymap CI workflow and both npm release jobs so packed
consumers are validated before npm sees them.
Clarify the runtime split in the docs: import-only use is Node-safe,
while creating a native renderer still requires Node 26 with
--experimental-ffi.
The test suite was tightly coupled to Bun-specific APIs (bun:test,
Bun.sleep) making it impossible to validate behavior on other
runtimes. A module hook now rewrites bun:test imports for Node's
test runner, and fake clocks replace wall-clock delays so tests
run deterministically everywhere.
Fix FFI type mismatches and boolean normalization that caused
silent failures on non-Bun runtimes. Correct bundled asset
resolution so published packages load without a TypeScript loader.
Reorganize the example menu with themed sections, two-panel focus
management, and proper tree-sitter cleanup to prevent worker leaks.
Extract examples, assets, install.sh, and the standalone build script
into a new workspace so they consume the public package surface
(@opentui/core, @opentui/three, @opentui/keymap) instead of reaching
into sibling internals. This makes examples a consumer of
the published API.
Drop the inherited browser export condition that prevented jimp from
resolving its node entry, which broke the standalone build.
This addresses https://github.com/sst/opentui/issues/184 by defaulting
to terminal background if renderer alpha channel is 0.
The transparent background can be set by using
`renderer.setBackgroundColor("transparent")` for example in
`packages/react/examples/basic.tsx`.
```diff
import { bold, fg, italic, t, TextAttributes } from "@opentui/core"
import { render, useKeyboard, useRenderer } from "@opentui/react"
import { useCallback, useState } from "react"
export const App = () => {
const renderer = useRenderer()
+ renderer.setBackgroundColor("transparent")
const [username, setUsername] = useState("")
const [password, setPassword] = useState("")
```
Example in ghostty
<img width="852" height="670" alt="image"
src="https://github.com/user-attachments/assets/658703ad-77a6-4624-b07c-5a24bbf8447c"
/>
---------
Co-authored-by: Claude <noreply@anthropic.com>