Skip to main content

nexa (nexa-ui)

nexa (pip install nexa-ui) is a Python port of CUI—a lightweight, zero-dependency C99 immediate-mode desktop UI library with spring motion, Flexbox/Grid layout, and crisp SDF rendering.

nexa 1.1 Workbench Studio — Dockspace, TreeTable, CodeEditor, FlameGraph & Timeline

  • Sub-megabyte native core: 820 KB stripped shared library (libnexa_cui) including embedded Inter, Geist Mono, 168 Lucide icons, OpenGL 3.3 + multi-threaded CPU software rasterizer, PNG/JPEG loader, optional BiDi & Arabic OpenType text shaping (--rtl), and OS windowing (660 KB in minimal LTO builds).
  • Zero runtime Python dependencies: Pure Python standard library (ctypes ABI releasing the GIL on every native call, __slots__ value types, ~48 ms warm import).
  • 160+ components across 20 domains (synced with CUI v1.1): Flexbox & grid layouts, multi-split docking workspaces (dockspace), hierarchical tree_table & path_bar, rich CommonMark/GFM markdown, multi-line code_editor, side-by-side diff_view, hex_view, profiler flame_graph, curve_editor, OKLab gradient_editor, NLE timeline_editor, virtualized 1M-row lists & editable data grids, 16 chart types, Kanban/Gantt/week calendars, AI agent/chat widgets, media, motion text, property inspector, Bezier node editor, and custom vector canvas.
  • Value-returning Pythonic API with full control: Widgets accept and return plain Python values (str, bool, int, float, Color, Date) while exposing transition flags (changed, submitted, focused, blurred), hit rects, persistent state_buffer, custom Platform hooks, and CustomRenderer GPU callbacks.
  • Functional, Procedural, and OOP styles: Write concise scripts with import nexa as ui, modular procedural apps with ctx: ui.UI, or multi-screen architectures with Application, Router, View, Component, and Store.
  • First-class Concurrency, asyncio, & Networking: 0%-CPU idle sleep with OS-level cross-thread app.wake(), BackgroundRunner (submit, stream, fetch_json, fetch_bytes), MPSC Channel, cooperative await app.run_async(...), and threaded AsyncBridge.

Documentation & Step-by-Step Guides

Read the interactive documentation at x017.github.io/yapps or browse docs/:

  1. Zero to Hero: The Complete nexa Full Tutorial — Comprehensive 11-module masterclass taking you from your first 15-line native window through Flexbox/Grid layouts, forms & pickers, desktop chrome, 50k virtualized grids, code & diff editors, studio canvases, OOP architecture, OKLCH theming, async worker streams, headless pytest, and building Pulse Studio (examples/zero_to_hero.py).
  2. Getting Started & Core Mental Model — Installation, value-returning immediate mode, widget IDs & id_scope, conditional vs. unconditional with scopes, and transition flags.
  3. Tutorial: Functional & Procedural Coding — Top-level ui.run(draw), flexbox/grid sizing (FIT, FILL, GROW, PX, PCT), procedural helper decomposition, manual while app.frame(): loops, and a complete Budget Tracker project.
  4. Tutorial: Object-Oriented (OOP) Architecture — Application, reusable auto-ID-scoped Components, multi-view Router & View navigation, reactive Store[T], and a complete Incident Console project.
  5. Theming, Accents, Tones, Colors & Typography — All 8 built-in Accent palettes, 9 semantic Tones, custom OKLCH/hex Token overrides, .ttf font loading, and 168 Icon constants.
  6. Concurrency, Multithreading, asyncio, & Networking — BackgroundRunner, token streaming, Channel, LogBuffer, await app.run_async(...), and AsyncBridge.
  7. Complete 160+ Component Reference — Signatures and usage across all 20 widget domains.
  8. Custom Canvas, Headless Testing, Custom GPU & Packaging — Vector canvas, automated pytest UI testing, Vulkan/Metal/wgpu DrawData, minimal LTO builds, and PyInstaller/Nuitka freezing.

Installation

Install prebuilt wheels from PyPI (imported in Python as import nexa as ui):

pip install nexa-ui

Or install directly from a local git checkout:

pip install -e .

Only a C99 compiler (gcc, clang, or MSVC cl) is required when building from source—no python3-dev headers, CMake, or libx11-dev packages are needed (libX11.so.6 is loaded dynamically via dlopen on Linux, with automatic headless SoftwareRenderer fallback on CI/servers without a display).


Quickstart: Functional, OOP, & Headless Styles

Every snippet below is 100% standalone and runnable as-is.

1. Functional / Procedural Style

import nexa as ui

def main() -> None:
    count = 0
    name = "world"

    def draw() -> None:
        nonlocal count, name
        with ui.column(width=ui.FILL, height=ui.FILL, pad=24, gap=14, bg=ui.Color.BACKGROUND):
            ui.heading(f"Hello, {name or 'stranger'}!", level=1)
            name = ui.input("name", name, placeholder="Type your name...", clearable=True)
            with ui.row(gap=10, align=ui.Align.CENTER):
                if ui.button("Increment", variant=ui.ButtonVariant.PRIMARY, icon=ui.Icon.PLUS):
                    count += 1
                ui.badge(f"Count: {count}", tone=ui.Tone.ACCENT)

    ui.run(draw, title="Hello — nexa", width=560, height=340, accent=ui.Accent.BLUE)

if __name__ == "__main__":
    main()

2. Object-Oriented Style (Application, Router, View, Component, Store)

import nexa as ui

class CounterCard(ui.Component):
    def __init__(self, key: str, title: str) -> None:
        super().__init__(key)
        self.title = title
        self.count = 0

    def build(self, ctx: ui.UI) -> None:
        # Automatic ID-scope isolation: multiple instances never collide!
        with ctx.card(pad=18, gap=10, width=ui.GROW(1)):
            ctx.heading(self.title, level=4)
            if ctx.button("Increment", icon=ui.Icon.PLUS, variant=ui.ButtonVariant.PRIMARY):
                self.count += 1
            ctx.secondary(f"Value: {self.count}")

class DashboardApp(ui.Application):
    def __init__(self) -> None:
        super().__init__("OOP Demo", width=720, height=380, theme=ui.ThemeMode.DARK, accent=ui.Accent.GREEN)

    def setup(self) -> None:
        self.left = CounterCard("left", "Pipeline A")
        self.right = CounterCard("right", "Pipeline B")

    def build(self, ctx: ui.UI) -> None:
        with ctx.row(width=ui.FILL, height=ui.FILL, pad=24, gap=16, bg=ui.Color.BACKGROUND):
            self.left(ctx)
            self.right(ctx)

if __name__ == "__main__":
    DashboardApp().run()

3. Explicit Headless / Custom GPU Control

import nexa as ui

with ui.SoftwareRenderer(threads=4) as sw:
    with ui.UI(width=800, height=450, theme=ui.ThemeMode.DARK, accent=ui.Accent.VIOLET, renderer=sw) as ctx:
        with ctx.frame(dt=1 / 60):
            with ctx.column(width=ui.FILL, height=ui.FILL, pad=24, gap=12, bg=ui.Color.BACKGROUND):
                ctx.metric("Throughput", "124,800 req/s", delta=14.2, spark=[82, 91, 96, 110, 124])

        # Save directly to PNG or inspect raw 64-byte SDF vertices & draw commands
        ctx.render_to_png("snapshot.png")
        dd = ctx.draw_data()
        print(dd.vertex_count, dd.index_count, len(dd.commands()))

Built-In Theme Accents (ui.Accent)

nexa includes 8 perceptually balanced OKLCH accents (ThemeMode.LIGHT & ThemeMode.DARK):

Accent Enum Dark Hex Light Hex
ui.Accent.NEUTRAL #e8e8e8 #1d1d1d
ui.Accent.VIOLET #a78bff #7747ff
ui.Accent.BLUE (default) #6ba3ff #0562ef
ui.Accent.GREEN #53dca6 #00864b
ui.Accent.AMBER #ffcb62 #f3ad20
ui.Accent.ORANGE #ffad5e #c25300
ui.Accent.CORAL #ff9386 #d1403a
ui.Accent.ROSE #ff8bc5 #d23286

Need a custom hex or OKLCH brand accent? Set ctx.theme[ui.Token.ACCENT] = ui.Color.hex("#14b8a6") at any time—see Theming & Styling.


Concurrency, asyncio, & Background Streaming

Cooperative Single-Thread asyncio

import asyncio
import nexa as ui

async def main() -> None:
    status = "Connecting..."
    app = ui.App("Async Demo", width=640, height=320, theme=ui.ThemeMode.DARK, accent=ui.Accent.VIOLET)

    async def worker() -> None:
        nonlocal status
        await asyncio.sleep(0.2)
        status = "Live stream active"
        app.wake()

    task = asyncio.create_task(worker())
    try:
        await app.run_async(lambda ctx: ctx.heading(status, level=2))
    finally:
        task.cancel()
        app.close()

if __name__ == "__main__":
    asyncio.run(main())

Background Worker Pool & Token Streaming (BackgroundRunner)

import time
import nexa as ui

def main() -> None:
    app = ui.App("Streaming Demo", width=640, height=320, theme=ui.ThemeMode.DARK)
    runner = ui.BackgroundRunner.for_app(app)
    chunks: list[str] = []

    def generate_tokens():
        for word in ["Zero-bloat", "native", "UI", "streaming", "in", "Python!"]:
            time.sleep(0.05)
            yield word

    def draw(ctx: ui.UI) -> None:
        with ctx.column(width=ui.FILL, height=ui.FILL, pad=24, gap=14, bg=ui.Color.BACKGROUND):
            if ctx.button("Stream Response", icon=ui.Icon.SPARKLES, variant=ui.ButtonVariant.PRIMARY):
                chunks.clear()
                runner.stream(generate_tokens, on_item=chunks.append)
            ctx.text(" ".join(chunks) or "Click Stream Response to begin.")

    try:
        app.run(draw)
    finally:
        runner.close()
        app.close()

if __name__ == "__main__":
    main()

Examples & Tests

Run any of the 13 complete example apps in examples/:

Example Highlights
examples/zero_to_hero.py 0-to-Hero Capstone (Pulse Studio): OOP Application + Component + Store, dockspace, path_bar, tree_table, code_editor, diff_view, GFM markdown, line_chart, flame_graph, BackgroundRunner & command_palette
examples/workbench.py New in 1.1: Multi-split dockspace, path_bar, tree_table, code_editor, diff_view, markdown, flame_graph, curve_editor, gradient_editor, timeline_editor & hex_view
examples/hello.py Functional quickstart, input, switch, toast, theme_toggle
examples/notes.py Split-view notes editor, search, tags, dialog, command_palette (Ctrl+K)
examples/settings.py OOP Application + Router + View + Component + all 8 Accent presets
examples/dashboard.py KPI number_roll, sparkline, line_chart, donut_chart, 250-row data_grid
examples/assistant.py AI workspace + BackgroundRunner.stream, reasoning, tool_call, voice_orb
examples/tracker.py Drag-and-drop kanban board, gantt timeline, week_calendar, presence
examples/finance.py Live ticker, odometer counter, treemap, sankey, money_input
examples/mail.py swipe_item inbox, chip filters, comment, dropzone, slide-over sheet
examples/music.py carousel, now_playing transport, scrubbable waveform, reorder queue
examples/gallery.py IDE menu_bar/toolbar/doc_tabs, Bezier node_editor, canvas, inspector, LogBuffer
examples/async_network.py Cooperative await app.run_async + loopback HTTP server + Channel

Render headless screenshots on any machine or CI runner:

NEXA_HEADLESS=1 CUI_SCREENSHOT=dashboard.png CUI_SCREENSHOT_FRAMES=12 python3 examples/dashboard.py

Run the test suite:

pytest -v

License

MIT License. Bundled fonts (Inter, Geist Mono, Lucide) and single-header libraries (stb_*) are permissive open-source; see LICENSE, THIRD_PARTY.md, and RELEASING.md.

Metadata

Release files for nexa-ui 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for nexa-ui 1.1.0
File Interpreter ABI Platform Actions
nexa_ui-1.1.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details for nexa_ui-1.1.0-py3-none-musllinux_1_2_x86_64.whl
nexa_ui-1.1.0-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl Python 3 none Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 Details for nexa_ui-1.1.0-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Total release size: 1.3 MB

Release files / nexa_ui-1.1.0-py3-none-musllinux_1_2_x86_64.whl

Download URL nexa_ui-1.1.0-py3-none-musllinux_1_2_x86_64.whl
Size 654.2 kB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
e9b4b413a136cb790bfe5c517ef61cd8db9e71bcc23b996e0dd1698a62e5b0b4
BLAKE2b-256 checksum
How to use checksums
0c3a9601f353bf7460bb045b0a65e77ee507a9326ecb6c47d2af33a0971e1033
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.12

Release files / nexa_ui-1.1.0-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL nexa_ui-1.1.0-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 649.2 kB
Tags Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 Python 3
SHA-256 checksum
How to use checksums
c3696a72249f01258352de9ffbe025d53983f19b7b38aa6c967cf14e07c62662
BLAKE2b-256 checksum
How to use checksums
ebc7ac0713fc0700d9632adb2abb992a4fe986e6132f941bfe41f88ac9684d7e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.12

Security for nexa-ui 1.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page