Sign in

Dominic Gannaway

@trueadm.dev
2.4K followers 130 following 267 posts

I'm a software engineer at OpenAI. Author of Inferno, Lexical, Ripple and Octane. Former React core team engineer, and core maintainer of Svelte.

PostsRepliesMedia
Dominic Gannaway @trueadm.dev · 27/07/2026
Happy to announce Octane – the successor to Inferno. React’s programming model, compiled. Hooks, Suspense and Actions, compiled ahead of time. No virtual DOM. No Rules of Hooks. No manually maintained dependency arrays. The compiler understands what your code. octanejs.dev
// Counter.tsrx — hooks next to output, no rules of hooks
import { useState, useEffect } from 'octane';

export function Counter(props) @{
	const [count, setCount] = useState(0);

	// A hook behind a condition is fine — slots are
	// assigned by call site, not call order.
	if (!props.paused) {
		useEffect(() => {
			console.log('count is now', count);
		}); // the compiler infers [count]
	}

	<button onClick={() => setCount(count + 1)}>{'Count: ' + count}</button>
}
814319
Dominic Gannaway @trueadm.dev · 30/04/2026
TSRX now supports Vue Vapor! Plus we've extended the runtimes support to include Preact. We will soon have an MCP server for TSRX so you can plug it into your favorite AI agent. TSRX is still alpha, so we're looking for early feedback from the Vue community tsrx.dev/getting-star...
Vue + Vite
Install the Vue compiler, its Vite plugin, the Vue runtime, and the Vapor JSX plugin:

 pnpm install @tsrx/vue @tsrx/vite-plugin-vue vue vue-jsx-vapor
Then wire both plugins into your Vite config (order matters — tsrxVue first):

 import { defineConfig } from 'vite';
 import tsrxVue from '@tsrx/vite-plugin-vue';
 import vueJsxVapor from 'vue-jsx-vapor/vite';

 export default defineConfig({
   plugins: [
     tsrxVue(),
     vueJsxVapor({
       macros: true,
       compiler: { runtimeModuleName: 'vue-jsx-vapor' },
     }),
   ],
 });
@tsrx/vite-plugin-vue compiles .tsrx modules into Vue-flavoured TSX, and vue-jsx-vapor/vite performs the downstream Vapor JSX transform. For editor typechecking, set jsxImportSource: "vue-jsx-vapor" in your tsconfig.json.
3336
Dominic Gannaway @trueadm.dev · 21/04/2026
Happy to announce TSRX. Think of it as the spiritual successor to JSX. We extracted it from Ripple, and made it framework agnostic. It can compile to React, Ripple and Solid, other frameworks to come soon. tsrx.dev
 export component Greeting({ name }: { name?: string }) {
   <div class="card">
     if (name) {
       <p>{`Hello, ${name}`}</p>
     } else {
       <p>{'Hello, stranger'}</p>
     }
   </div>

   <style>
     .card { padding: 1rem; }
   </style>
 }
1620730
Dominic Gannaway @trueadm.dev · 01/10/2025
RippleJS has improved quite a bit! 🔥 - new reactivity syntax that uses `track` and @ - support for index and keyed for loops - `clsx` built in to class attributes - #[] and #{} shorthand for TrackedArray and TrackedObject - <head> support - many, many bug fixes
export component App() {
  // This is a tracked array using #[] syntax
  let cities = #['London', 'New York', 'Tokyo', 'Sydney'];

  // index and key syntax has shipped
  for (const city of cities; index i) {
    <div>{i + ' - ' + city}</div>
  }

  <button onClick={() => {
    cities.push(randomCity());
  }}>{"Add random city"}</button>

  <head>
    <title>{"You can also update the title!"}</title>
  </head>
}
3380
Dominic Gannaway @trueadm.dev · 29/05/2025
Shows the code:

```js
export component App() {
  let $show = true;

  <div class="container">
    <h1>{"Inferno X"}</h1>

    let $count = 0;
    let $double = $count * 2;

    <button onClick={() => {
      $count += 1;
    }}>{'Count: ' + $count}</button>

    <span>{'Double: ' + $double}</span>

    if ($show) {
      <div>{"Showing"}</div>
    }

    <button onClick={() => {
      $show = !$show;
    }}>{$show ? 'Hide' : 'Show'}</button>
  </div>
}
```
5120