Show HN: Coi – A compiled-reactive language for high-performance WASM apps

Hi HN,

I’ve been working on Coi, a component-based language designed to make writing high-performance WebAssembly apps feel like writing modern web components.

The Concept: Coi transpiles to C++ and uses a custom toolchain I built called WebCC to handle the final compilation to WASM, JS, and HTML. While WebCC provides the high-speed bridge and browser API framework, Coi performs the static analysis to map state variables to DOM handles. This "bakes" the reactive logic into the generated code, enabling O(1) updates without a Virtual DOM or runtime "diffing" step.

Benchmarks (Rendering 10k rectangles (Canvas2D)): I compared the WebCC-backed Coi output against a standard Emscripten build. By minimizing the WASM-to-JS bridge overhead, I saw:

- Binary Size: 11KB WASM (WebCC) vs 154KB WASM (Emscripten)

- Performance: 100 FPS vs 40 FPS

- Memory: 9MB vs 24MB

Key Features: - Type-Safe with References: Strictly typed state and props. Use & for seamless, type-safe two-way binding between parent and child components. - Component Lifecycle: Dedicated blocks for every stage: init {} for state, mount {} for DOM access, and tick(dt) {} for frame-based animations/physics. - Declarative View & Styling: Write standard HTML and scoped CSS directly inside components. Use <if> and <for> tags for control flow without leaving the view. - The Command Buffer: Bypasses the WASM-JS bridge bottleneck by flushing updates in binary "bursts" through a shared command buffer provided by WebCC.Schema-Driven APIs: Coi leverages the WebCC schema.def to auto-generate its standard library (Canvas, WebGL, WebGPU, Audio, etc.) with full type-safety and VS Code LSP support.

Example Code:

component Counter(string label, mut int& value) {

    def add(int i) : void {
        value += i;
    }

    style {
        .counter {
            display: flex;
            gap: 12px;
            align-items: center;
        }
        button {
            padding: 8px 16px;
            cursor: pointer;
        }
    }

    view {
        <div class="counter">
            <span>{label}: {value}</span>
            <button onclick={add(1)}>+</button>
            <button onclick={add(-1)}>-</button>
        </div>
    }
}

component App {

    mut int score;
    mut string message;

    init {
        score = 0;
        message = "Keep going!";
    }

    style {
        .app {
            padding: 24px;
            font-family: system-ui;
        }
        h1 {
            color: #1a73e8;
        }
        .win {
            color: #34a853;
            font-weight: bold;
        }
    }

    view {
        <div class="app">
            <h1>Score: {score}</h1>
            <Counter label="Player" &value={score} />
            <if score >= 10>
                <p class="win">You win!</p>
            <else>
                <p>{message}</p>
            </else>
            </if>
        </div>
    }
}

app { root = App; }

Repo: https://github.com/io-eric/coi

WebCC(The underlying toolchain): https://github.com/io-eric/webcc

Demo: https://io-eric.github.io/coi

Would love to get your feedback! Still very much a work in progress :D

2 points | by io_eric 3 hours ago

0 comments