What is Ripple? Currently, this project is still in early development, and should not be used in production. Ripple is a TypeScript UI framework that takes the best parts of React, Solid and Svelte and combined them into one package. I wrote Ripple as a love letter for frontend web – and this is largely a project that I built in less than a week, so it's very raw. Personally, I (@trueadm) have been involved in some truly amazing frontend frameworks along their journeys – from Inferno, where it all began, to React and the journey of React Hooks, to creating Lexical, to Svelte 5 and its new compiler and signal-based reactivity runtime. Along that journey, I collected ideas, and intriguing thoughts that may or may not pay off. Given my time between roles, I decided it was the best opportunity to try them out, and for open source to see what I was cooking. Ripple was designed to be a JS/TS-first framework, rather than HTML-first. Ripple modules have their own .ripple extension and these modules fully support TypeScript. By introducing a new extension, it affords Ripple to invent its own superset language, that plays really nicely with TypeScript and JSX, but with a few interesting touches. In my experience, this has led to better DX not only for humans, but also for LLMs. Right now, there will be plenty of bugs, things just won't work either and you'll find TODOs everywhere. At this stage, Ripple is more of an early alpha version of something that might be, rather than something you should try and adopt. If anything, maybe some of the ideas can be shared and incubated back into other frameworks. There's also a lot of similarities with Svelte 5, and that's not by accident, that's because of my recent time working on Svelte 5. If you'd like to know more, join the Ripple Discord. Features Reactive State Management : Built-in reactivity with $ prefixed variables and object properties : Built-in reactivity with prefixed variables and object properties Component-Based Architecture : Clean, reusable components with props and children : Clean, reusable components with props and children JSX-like Syntax : Familiar templating with Ripple-specific enhancements : Familiar templating with Ripple-specific enhancements Performance : Fine-grain rendering, with industry leading performance and memory usage : Fine-grain rendering, with industry leading performance and memory usage TypeScript Support : Full TypeScript integration with type checking : Full TypeScript integration with type checking VSCode Integration : Rich editor support with diagnostics, syntax highlighting, and IntelliSense : Rich editor support with diagnostics, syntax highlighting, and IntelliSense Prettier Support: Full Prettier formatting support for .ripple modules Missing Features SSR : Ripple is currently an SPA only, this is because I haven't gotten around to it : Ripple is currently an SPA only, this is because I haven't gotten around to it Testing & Types: The codebase is very raw with limited types (I've opted for JavaScript only to avoid build problems). There aren't any tests either – I've been using the playground directory to manually test things as I go Quick Start Try Ripple We're working hard on getting an online playground available. Watch this space! You can try Ripple now by using our basic Vite template either via StackBlitz, or by running these commands in your terminal: npx degit trueadm/ripple/templates/basic my-app cd my-app npm i # or yarn or pnpm npm run dev # or yarn or pnpm Mounting your app You can use the mount API from the ripple package to render your Ripple component, using the target option to specify what DOM element you want to render the component. // index.ts import { mount } from 'ripple' ; import { App } from '/App.ripple' ; mount ( App , { props : { title : 'Hello world!' , } , target : document . getElementById ( 'root' ) , } ) ; Key Concepts Components Define reusable components with the component keyword. These are similar to functions in that they have props , but crucially, they allow for a JSX-like syntax to be defined alongside standard TypeScript. That means you do not return JSX like in other frameworks, but you instead use it like a JavaScript statement, as shown: component Button(props: { text: string, onClick: () => void }) { } // Usage component App() { } Control flow The JSX-like syntax might take some time to get used to if you're coming from another framework. For one, templating in Ripple can only occur inside a component body – you can't create JSX inside functions, or assign it to variables as an expression.
// you can create variables inside the template! const str = "hello world"; console.log(str); // and function calls too! debugger; // you can put breakpoints anywhere to help debugging! {str}
Note that strings inside the template need to be inside {"string"} , you can't do
hello
as Ripple has no idea if hello is a string or maybe some JavaScript code that needs evaluating, so just ensure you wrap them in curly braces. This shouldn't be an issue in the real-world anyway, as you'll likely use an i18n library that means using JavaScript expressions regardless. If statements If blocks work seamlessly with Ripple's templating language, you can put them inside the JSX-like statements, making control-flow far easier to read and reason with. component Truthy({ x }) {
if (x) { {'x is truthy'} } else { {'x is falsy'} }
} For statements You can render collections using a for...of block, and you don't need to specify a key prop like other frameworks. component ListView({ title, items }) {

{title}

    for (const item of items) {
  • {item.text}
  • }
} You can use Ripple's reactive arrays to easily compose contents of an array. import { array } from 'ripple'; component Numbers() { const items = array(1, 2, 3); for (const item of items) { {item}