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 · 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 · 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
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 · 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
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 · 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 · 03/02/2026
We’re so happy to have Thomas here at Attio!
070
Dominic Gannaway @trueadm.dev · 06/01/2026
We're still looking for a web infrastructure engineer to join my team at Attio. If anyone is from the UK/EU and is interested and you love JS/TS performance, tweaking and building frameworks/libraries that enable other engineers to move faster – check out the spec: attio.com/careers/web-....
attio.com
Web Infrastructure Engineer
Help shape the web infrastructure that powers Attio’s product
1143
Dominic Gannaway @trueadm.dev · 10/11/2025
I'm not going to lie. I love monorepos, but I also hate them when things go wrong or things are slow. I'm so conflicted right now.
0131
Dominic Gannaway @trueadm.dev · 03/11/2025
RippleJS has changed name, and is now RippleTS! This addresses the issues we had with transferring the GitHub and npm orgs (long story), and also giving the project more identity compared to existing projects with a similar name
3361
Dominic Gannaway @trueadm.dev · 28/10/2025
@anthonyshort.bsky.social hey I’m the author of RippleJS. Would you be up for a chat to help the team resolve the GitHub issue around transferring the org? Thank you!
050
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 · 19/09/2025
Innovation in open source only works when you share and collaborate. Being transparent and honest is always the best policy. It might not always feel great, you’ll get a bunch of negativity but it’s often offset by positivity.
0240
Dominic Gannaway @trueadm.dev · 17/09/2025
The team behind RippleJS has heard the feedback around the $ prefixed reactivity and we agree – the design wasn't quite there. So we've proposed an alternative. github.com/trueadm/ripp...
2151
Dominic Gannaway @trueadm.dev · 02/09/2025
I've given up with VS Code Copilot. The amount of endless cycles it does has driven me mad. Claud Code has proven far better. If anyone else is having the same issues, make the change. It's night and day compared.
2131
Dominic Gannaway @trueadm.dev · 02/09/2025
Any designers out that would like help create a great logo? github.com/trueadm/ripp... What we have now isn't great, but a great logo makes a big difference.
042
Dominic Gannaway @trueadm.dev · 02/09/2025
Ripple now has a website! www.ripplejs.com If anyone wants to contribute to fixing/improving it, be my guest – github.com/trueadm/ripple.
7719
Dominic Gannaway @trueadm.dev · 29/08/2025
If folks have questions about Ripple, come join our Discord channel: discord.gg/JBF2ySrh2W
060
Dominic Gannaway @trueadm.dev · 28/08/2025
I've open sourced Ripple! github.com/trueadm/ripple It's super early days, not much works and there's little to no documentation or guidance. Plus the codebase is raw, but I at least wanted to share my ideas with the community. :)
github.com
GitHub - trueadm/ripple: Ripple is a TypeScript UI framework for the web.
Ripple is a TypeScript UI framework for the web. Contribute to trueadm/ripple development by creating an account on GitHub.
109417
Dominic Gannaway @trueadm.dev · 28/08/2025
I've had so many folks ask now, that I had to go for it. You asked me to build that ideal Inferno X framework that I described ages ago, so I went ahead and did just that. I built something that actually works and, well, it works well. Oh, and doesn't use signals!
1252
Dominic Gannaway @trueadm.dev · 20/08/2025
I compare today's coding AI agents to my 3 year old toddlers. Sometime they nail it and you're like "well done, great job! I'm so proud of you!".
180
Dominic Gannaway @trueadm.dev · 18/08/2025
I’m sharing the news that after nearly 2.5 years, I’ll be leaving Vercel at the end of this week. It’s been an awesome ride, and I’ve had the privilege of working with so many great folks on a bunch of different projects.
171051
Dominic Gannaway @trueadm.dev · 12/08/2025
Is it me or is Bluesky becoming more and more like Twitter?
130
Dominic Gannaway @trueadm.dev · 22/07/2025
I still think there's a missed opportunity to create a frontend framework that works really well with AI tooling.
3100
Reposted by Dominic Gannaway
Jon Kuperman @jonkuperman.com · 29/05/2025
Interested in Signals? Enjoy learning by reading code? Check out github.com/jkup/learn-s...
github.com
GitHub - jkup/learn-signals
Contribute to jkup/learn-signals development by creating an account on GitHub.
46415
Dominic Gannaway @trueadm.dev · 28/05/2025
Recently I was hacking on a new framework idea. I called it Inferno X. The big difference was that it forked JSX. Rather than being expression based, it was statement based. This meant that JavaScript control flow could be used to express the template.
3423
Dominic Gannaway @trueadm.dev · 20/04/2025
Black Mirror never disappoints
250
Dominic Gannaway @trueadm.dev · 11/04/2025
I’ve been hacking on a new idea/project that infuses AI with frontend. It’s early days but it’s looking promising
0150
Dominic Gannaway @trueadm.dev · 08/04/2025
For all the Arsenal fans that might be out there on Bsky, tonight was a night of "Bend it like Declan" for sure!
180
Dominic Gannaway @trueadm.dev · 31/03/2025
Mixture of up and down feelings over the past week. The company off-site was great but being away from the family hit hard.
0120
Dominic Gannaway @trueadm.dev · 11/03/2025
I wish there was a platform like LinkedIn, that worked a bit like UberEats etc where you could rate the person who messaged you with a job offer. It would instantly make all the spam far less common. It even force recruiters to read your resume too?!?
1190
Dominic Gannaway @trueadm.dev · 10/03/2025
I’m curious, what do people think is React’s primary reason why it became the de-facto frontend framework it is today?
1231
Reposted by Dominic Gannaway
rich harris @rich-harris.dev · 07/03/2025
PSA for @svelte.dev users: we're planning to change how effect teardowns work to eliminate a common gotcha that affects signal-based frameworks. If the new behaviour would create problems for you, please let us know! github.com/sveltejs/sve...
github.com
fix: on teardown, use the last known value for the signal before the set by trueadm · Pull Request #15469 · sveltejs/svelte
PSA: we are changing how effect teardowns work! Today, if you read some state inside a teardown function, you get the latest state: $effect(() =&gt; { const prev = value; return () =&gt; { ...
818922
Reposted by Dominic Gannaway
GitHub @github.com · 28/02/2025
"Incoming transmission!" 📡 Classic Command and Conquer games are now open source—ready for modding, preservation, and innovation! Read more: ea.com/games/comman... Dive into the code: github.com/electronicarts
Screenshot from the Command & Conquer Remastered CollectionScreenshot from the Command & Conquer Remastered CollectionScreenshot from the Command & Conquer Remastered Collection
461655251
Dominic Gannaway @trueadm.dev · 19/02/2025
I’m often asked - what is the best frontend framework? The truth is there isn’t one. SvelteKit and SolidStart get you almost there without the bells and whistles, but the performance is good. Nuxt and Next get you there quicker, because of the bells and whistles, but the performance is still lacking
3381
Dominic Gannaway @trueadm.dev · 09/02/2025
I’m struggling with Severance. Whilst appreciate the plot, 7 episodes in on season 1 and I’m still as bored as episode 1. The Silo was fantastic. I just find this show boring?! Will it get better? I mean the narrative is interesting. It just feels terribly slow.
350
Dominic Gannaway @trueadm.dev · 05/01/2025
Is it me, or has engagement on BlueSky dipped quite a bit a in the last week or two? I've noticed a significant drop off in activity to responses and my feed is also far less active than it used to be. It also looks like everyone is cross-posting to X again. :(
9251
Dominic Gannaway @trueadm.dev · 31/12/2024
Happy New Year everyone! Hope 2025 is your year! 🎉
0170
Reposted by Dominic Gannaway
Svelte @svelte.dev · 24/12/2024
Day 24 — Svelte now handles `class` attributes with github.com/lukeed/clsx. Much more powerful than the `class:` directive, but since this is Svelte you still get dead code elimination of unused styles! 🎁 docs svelte.dev/docs/svelte/... 🎁 demo svelte.dev/playground/6...
screenshot of svelte.dev/playground showing the new `class` attribute handling
61329
Reposted by Dominic Gannaway
Svelte @svelte.dev · 23/12/2024
Day 23 — you can now download your playground creations as SvelteKit apps! It'll even include any dependencies you've imported 🎁 svelte.dev/playground
screenshot of svelte.dev/playground showing the new 'download app' option
1655
Reposted by Dominic Gannaway
Svelte @svelte.dev · 15/12/2024
Day 15 — the new `$inspect.trace(...)` rune gives you debugging superpowers. Add it to a function that runs inside a derived or effect, and you'll see detailed information about what caused it to re-run 🎁 docs svelte.dev/docs/svelte/... 🎁 demo svelte.dev/playground/d...
screenshot of svelte.dev/playground showing the new $inspect.trace(...) debugging superpowers
4787
Dominic Gannaway @trueadm.dev · 15/12/2024
The one downside of AI prompts is that it’ll make it far easier for kids to ask “is Santa real?”. When you explain he is real, they’ll just ask the AI if our answer was real. :/
440
Reposted by Dominic Gannaway
Svelte @svelte.dev · 14/12/2024
Day 14 — if you need to programmatically mount and unmount a component, you can now pass an `outro: true` option to `unmount` to play transitions before it is removed from the DOM 🎁 docs svelte.dev/docs/svelte/... 🎁 demo svelte.dev/playground/a...
2948
Reposted by Dominic Gannaway
Svelte @svelte.dev · 12/12/2024
Day 12 — send custom types across the network boundary in SvelteKit, whether it's a class containing reactive state, a class used by your database ORM library, or whatever. Just export a `transport` object from your `hooks.js` 🎁 docs svelte.dev/docs/kit/hoo... 🎁 demo stackblitz.com/edit/sveltej...
screenshot of a stackblitz app showing the new custom type transport feature in sveltekit
48810
Reposted by Dominic Gannaway
Svelte @svelte.dev · 08/12/2024
Day 8 — we're calling this 'function bindings'. You know how you can do `bind:value={value}`? You can now do this... bind:value={getValue, setValue} ...which lets you transform and validate data 🎁 docs svelte.dev/docs/svelte/... 🎁 demo svelte.dev/playground/1...
screenshot of svelte.dev/playground showing the new function bindings feature
812114
Dominic Gannaway @trueadm.dev · 06/12/2024
I really wish modern cars had a way of disabling lane departure avoidance permanently. In the UK and the EU they turn back on after starting the car again. They’re more dangerous than anything else. I’ve had so many near-misses because of them. Don’t get me started on speed warnings too…
140
Reposted by Dominic Gannaway
Svelte @svelte.dev · 05/12/2024
Day 5 — it's a three-in-one kind of day! `new MediaQuery(...)` lets you use media queries reactively. prefersReducedMotion is an instance of MediaQuery that makes it easier to respect users' accessibility preferences - docs svelte.dev/docs/svelte/... - demo svelte.dev/playground/8... there's more!
210515