True AOT: Compiling Lisp Shaders directly to Wasm-GC
In our quest to build a pure, high-performance Lisp ecosystem for the browser, we’ve hit a monumental milestone. Today, we’re showing off our new Infinity 999Hz WebGL application, and more importantly, how it’s completely Ahead-of-Time (AOT) compiled into a native Wasm-GC binary.

As you can see in the screenshot above, the app features a mesmerizing, audio-reactive particle swarm with dynamic magenta and cyan hues, complete with a reactive UI slider to control the color frequency. But the real magic isn’t just on the screen—it’s how the screen is being drawn.
The Magic of Compile-Time Macros
Previously, we introduced the defshader macro, which allowed us to write WebGL GLSL shaders in pure Coni Lisp syntax. It was a massive quality-of-life improvement, allowing us to use structural editing (like Paredit) for our GPU math. But there was a catch: interpreting those macros to generate GLSL strings at runtime inside the browser was computationally expensive.
We’ve completely eliminated that overhead.
When you run coni compile-wasm now, the compiler performs true AOT macro expansion. It spins up its internal interpreter during the build step, processes the entire Clojure-like defshader tree, runs the emit-glsl logic, and generates the massive raw GLSL string in memory on your host machine.
Burning Shaders into Wasm-GC
Once that GLSL string is generated at compile time, it is injected directly into the Abstract Syntax Tree as a constant string literal. The Coni WASM backend then emits it straight into the .wat (WebAssembly Text) file as a native Wasm-GC byte array!
There is zero macro expansion happening at runtime. When the browser loads the page, there is no Coni interpreter running at all. The browser simply boots up the tiny, blazingly fast app.wasm binary, grabs the pre-computed GLSL strings from WASM memory, and sends them straight to the WebGL driver.
Take a look at the fragment shader logic for the particle coloring in the Infinity 999Hz app:
(set float r (dot p p))
(if (< 1.0 r)
(discard))
(set float alpha (* (- 1.0 r) 1.5 v_depth))
(set float hue (/ (mod (+ u_hue_offset (+ 260.0 (* 60.0 (sin (+ v_nt u_time))))) 360.0) 360.0))
;; hsl to rgb inline conversion entirely in Lisp!
(set vec3 c (vec3 hue 1.0 0.75))
(set vec4 K (vec4 1.0 0.666666 0.333333 3.0))
(set vec3 p_c (abs (- (* (fract (+ (vec3 (.-x c) (.-x c) (.-x c)) (vec3 (.-x K) (.-y K) (.-z K)))) 6.0) (vec3 (.-w K) (.-w K) (.-w K)))))
(set vec3 rgb (+ (.-z c) (* (.-y c) (* (- (clamp (- p_c (vec3 (.-x K) (.-x K) (.-x K))) 0.0 1.0) 0.5) (- 1.0 (abs (- (* 2.0 (.-z c)) 1.0)))))))
(set gl_FragColor (vec4 (* rgb alpha) alpha))))
Notice how the complex HSL to RGB conversion math is perfectly structured as S-expressions. The u_hue_offset is a uniform bound directly to the HTML slider (seen in the bottom left of the screenshot). Coni’s reactivity framework instantly bridges the DOM slider value to the WebGL shader context seamlessly.
This beautiful Lisp syntax is structurally edited, statically analyzed by our linter, and then vaporized into pure native Wasm assembly instructions and raw GLSL before it ever touches a web browser.
Native performance. Pure Lisp aesthetics. The best of both worlds.