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 · 15/09/2026
As we prepare TSRX for 1.0, we’ve decided to remove “lazy destructuring”. This reflects the direction we want to take TSRX: an extension of JSX, rather than an entirely new language. We’ve written more about the reasoning behind the change here: tsrx.dev/blog/removin...
071
Dominic Gannaway @trueadm.dev · 26/08/2026
TSRX finally has its own Github repo: github.com/tsrx-org/tsrx It started off as something that lived in the Ripple repo, as we broke it apart from Ripple itself. It's now far outgrown Ripple alone though so it's made sense for it to have its own trajectory.
github.com
GitHub - tsrx-org/tsrx: TSRX language, compilers, tooling, and editor integrations
TSRX language, compilers, tooling, and editor integrations - tsrx-org/tsrx
0311
Dominic Gannaway @trueadm.dev · 28/07/2026
See github.com/octanejs/oct... on ideas where we can evolve this further
github.com
feat(octane): cross-module hook fact extraction (opt-in) by trueadm · Pull Request #321 · octanejs/octane
Summary A spike proving that a single-module compile can answer a question about an import by reading it instead of assuming. Opt-in via crossModuleHookFacts: true on the Vite or Rspack plugin. Off...
030
Dominic Gannaway @trueadm.dev · 28/07/2026
Yeah or between module
110
Dominic Gannaway @trueadm.dev · 28/07/2026
Ripple is still its own project that has a team around it
100
Dominic Gannaway @trueadm.dev · 28/07/2026
We’ll get on that straight away
010
Dominic Gannaway @trueadm.dev · 28/07/2026
An evolution of React/Inferno
110
Dominic Gannaway @trueadm.dev · 28/07/2026
It’s kind of similar to how Svelte worked before, but far more extensive. There are no signals involved
020
Dominic Gannaway @trueadm.dev · 28/07/2026
If you check the website you can see we offer OctaneCompat for exactly that reason
011
Dominic Gannaway @trueadm.dev · 27/07/2026
Feel free to play around with it on the website playground octanejs.dev/playground :)
130
Dominic Gannaway @trueadm.dev · 27/07/2026
Yes in that case the `useEffect` teardown will fire as its conditional.
130
Dominic Gannaway @trueadm.dev · 27/07/2026
No to either. useState will persist, and useEffect will only trigger it's cleanup if it's to run again, or the component unmounts
110
Dominic Gannaway @trueadm.dev · 27/07/2026
You can continue to write manual deps if you want, it's just that the eslint rule isn't smart enough to know what is stable and what is not in many cases.
140
Dominic Gannaway @trueadm.dev · 27/07/2026
Octane offers a universal renderer for such integrations. As you can tell from the demos, time slicing isn’t needed
010
Dominic Gannaway @trueadm.dev · 27/07/2026
It does infer usage based off a few things. There's likely more wiggle room here. You can always opt to put them in manually if you want too. Any feedback on how we can make them better is highly valued as a github issue. :)
100
Dominic Gannaway @trueadm.dev · 27/07/2026
Octane supports TSX and JSX, along with TSRX for even better DX and performance. It includes integrations for libraries such as TanStack, React Three Fiber, Lynx and StyleX, plus a compatibility layer for using Octane components inside existing React apps.
1120
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 · 24/07/2026
We’re currently in stealth mode. We’ll be announcing Octane publicly soon once we’re ready :)
020
Dominic Gannaway @trueadm.dev · 24/07/2026
We’re currently in stealth mode. :) we’ll be announcing Octane soon
010
Dominic Gannaway @trueadm.dev · 14/07/2026
Ripple is still very much maintained by the core team. I'm just working on Octane as it fits better with my current role at OpenAI.
020
Dominic Gannaway @trueadm.dev · 10/06/2026
The TSRX team has been hard at work listening to feedback, criticism, and ideas. TSRX is now nearly fully backward-compatible with JSX. Instead of being statement-based, it’s expression-based, just like JSX. tsrx.dev/blog/rethink...
tsrx.dev
TSRX | TypeScript Language Extension for Declarative UI
TSRX is a TypeScript language extension for building declarative UIs with readable, co-located authoring and framework-specific output targets.
0324
Dominic Gannaway @trueadm.dev · 05/06/2026
If you’re interested in joining me, OpenAI are hiring: openai.com/careers/fron...
openai.com
Frontend Engineer, ChatGPT Engineering
Applied AI Engineering · 3 locations · FullTime
020
Dominic Gannaway @trueadm.dev · 05/06/2026
I'm excited to share that I’ll be joining OpenAI next month as a Member of Technical Staff. 🎉 I'll be joining the ChatGPT Web Infrastructure team in London.
6581
Dominic Gannaway @trueadm.dev · 31/05/2026
Let me think about it
010
Dominic Gannaway @trueadm.dev · 31/05/2026
At the end of the day you still need to create classes for the underlying styles and that means debugging and precedence play a role. You can’t use actual inline styles because it doesn’t support pseudo selectors
110
Dominic Gannaway @trueadm.dev · 31/05/2026
You can already do that using the style prop or Tailwind if you want. The docs don’t state one way is better than another.
100
Dominic Gannaway @trueadm.dev · 31/05/2026
You can use styles declaratively too using a declaration on the style element. Then referencing styles like a map/object lookup
130
Dominic Gannaway @trueadm.dev · 30/05/2026
The TSRX team have listened to feedback and have made some important design changes to TSRX. We’ve removed the component keyword, and other parts that felt too magical and aligned TSRX more closely with JSX in how it’s consumed. tsrx.dev/blog/simplif...
3574
Dominic Gannaway @trueadm.dev · 01/05/2026
Thanks for trying it out already, given how early into development it is. Much appreciated.
110
Reposted by Dominic Gannaway
Ryan Carniato @ryansolid.bsky.social · 29/04/2026
I'm very excited to have @trueadm.dev back on the stream this Friday to talk about TSRX and Ripple at 12pm PT (stream starts at 11am PT). www.youtube.com/watch?v=xulU...
youtube.com
Exploring TSRX w/ Dominic Gannaway
YouTube video by Ryan Carniato
0396
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 · 28/04/2026
Much of it was transferable in reality. Assumptions are changing today mainly due to the role AI is playing, so it seemed a perfect time to optimize for things given how humans are now reading more code, vs writing code. Runtime models will come, go and evolve independently.
110
Dominic Gannaway @trueadm.dev · 27/04/2026
I mean, factually, in our testing TSRX provided better output compared to TS an TSX modules. We're planning on providing benchmarks soon that show this. Given the the announcement, we've undated with requests and feedback that obviously takes priority.
020
Dominic Gannaway @trueadm.dev · 26/04/2026
In my experience, TSRX performs much better in modern LLM models at the limits than UI-as-value. We plan on providing some very LLM friendly internal dev tooling, around the bundler level that can pump context to your agent and it can even further.
110
Dominic Gannaway @trueadm.dev · 23/04/2026
Feel free to create a Github issue, and we can look into this :)
000
Dominic Gannaway @trueadm.dev · 23/04/2026
I added a spec yesterday tsrx.dev/specification, let me know if there's anything missing
000
Dominic Gannaway @trueadm.dev · 22/04/2026
It's immediate mode in design, rather than implicit return. If you find any bugs, please let us know.
010
Dominic Gannaway @trueadm.dev · 22/04/2026
It's a combination of all things really. In the early React days I worked on Prepack – and that really informed my compiler journey to see what was possible. Svelte taught me that you can ship your own extension and have it work.
120
Dominic Gannaway @trueadm.dev · 22/04/2026
You can use early returns too. It's covered in the features page
000
Dominic Gannaway @trueadm.dev · 22/04/2026
Play around with the playground for yourself to see tsrx.dev/playground
tsrx.dev
TSRX | TypeScript Language Extension for Declarative UI
TSRX is a TypeScript language extension for building declarative UIs with readable, co-located authoring and framework-specific output targets.
000
Dominic Gannaway @trueadm.dev · 22/04/2026
If you read the website sections, it captures why. Much of it is co-location of concerns. For example React code tends to be fragile when you have hooks that all have to be unconditional, and the logic for the hooks doesn't sit side-by-side the code that is using it. Humans and agents struggle
100
Dominic Gannaway @trueadm.dev · 22/04/2026
Yes the `component` block allows us to handle parsing differently. We are aiming to handle all the edge cases as you portrayed too.
050
Dominic Gannaway @trueadm.dev · 22/04/2026
If there's any chance you could help with the spec, it would be much appreciated. We have a Discord if that helps? discord.com/invite/JBF2y...
discord.com
Join the Ripple TS Discord Server!
The official Discord for RippleTS | 919 members
120
Dominic Gannaway @trueadm.dev · 22/04/2026
LLMs can do most of the work using the other plugin targets as a starting point :)
000
Dominic Gannaway @trueadm.dev · 22/04/2026
The `component` keywords gives us the luxury of changing the semantics of the control flow though, that's why we can stay backwards compatible. You can think of components as being immediate mode for templating. There is no return value per say.
150
Dominic Gannaway @trueadm.dev · 22/04/2026
Actually, I haven't really used Rust and have never touched Zig. It was extracted from Ripple, and I guess the previous art came from my experiences working on the React team and Svelte team – which both shared similar ideas about.
230
Dominic Gannaway @trueadm.dev · 22/04/2026
We need to write one up :)
040
Dominic Gannaway @trueadm.dev · 22/04/2026
TC39 are more keen on keeping this at a build-tool level rather than entering the spec. That's why JSX won't ever be part of the spec. It makes sense in many ways – we already have tooling, so what's the benefit? We still don't have TS as comments, so if that can't land then this will never land.
250
Dominic Gannaway @trueadm.dev · 21/04/2026
It provides the `component` keywords, JS control flow, JSX as statements (and expressions too), lazy destructuring and scoped styling via `<style>` It even allows for condition React Hook usage. Contributions and bug reports are welcome!
0170
Dominic Gannaway @trueadm.dev · 21/04/2026
It's a TypeScript superset language, with a parser, compiler and a selection of plugins for editors + Prettier + ESlint, etc It's early alpha but we thought people might be interested in it.
1180