Skip to content

Rimitive

Type-safe reactive primitives, atomic tooling, and compositional patterns you can use anywhere

Rimitive grows with you:

  • from your most simple state management use cases
  • to your UI
  • to routing
  • to SSR with streaming and beyond

…without forcing you commit to any framework, build, or transpilation. Everything is opt-in, swappable, and fully customizable 🛠️.

Everything in Rimitive starts with a reactive service:

const { signal, computed, effect } = compose(
SignalModule,
ComputedModule,
EffectModule
);
const you = signal('🫸');
const rimitive = signal('🫷');
const highFive = computed(() => `${you()}💥${rimitive()}`);
effect(() => console.log(highFive())); // 🫸💥🫷

The service composes all the modules you want to use from Rimitive, using dependency injection under the hood:

const { signal, computed, el, mount } = compose(
SignalModule,
ComputedModule,
EffectModule,
// Add these 👇
createElModule(createDOMAdapter()),
MountModule
);
const App = () => {
const together = signal(false);
return el('div')(
el('p').props({
textContent: computed(() => (together() ? '🫸💥🫷' : '🫸 🫷')),
}),
el('button').props({ onclick: () => together(!together()) })('High five!')
);
};
document.body.appendChild(mount(App()).element!);
const { router, el, match } = compose(
// ... signal modules, view modules, and 👇
createRouterModule([
{ id: 'ready', path: '' },
{ id: 'high-five', path: 'high-five' },
{ id: 'celebrate', path: 'celebrate/:style' },
])
);
// Routes are reactive and pair nicely with `match`
match(router.matches, (routes) => {
const route = routes[0];
switch (route?.id) {
case 'ready': return Ready(); // 🫸 🫷
case 'high-five': return HighFive(); // 🫸💥🫷
case 'celebrate': return Celebrate({ style: route.params.style }); // 🎉
default: return Lost(); // 🤷
}
});
// Navigate programmatically
router.navigate('/celebrate/reactively');

Routing, async resources, SSR, streaming—building off the same primitives.

Reactivity lives in the primitives, not in components. No component-level re-renders, reconciliation, rules, builds, transpilation, or magical closures. They return a spec of a reactive UI that can be mounted and unmounted. That’s it!

Portable Components and Behaviors. Your reactive logic isn’t tied to a component model. Write a disclosure behavior once, use it in Rimitive views, React, or anything else that speaks signals.

Transparent architecture. Every layer is swappable: the reactive graph, the scheduler, the renderer. Rimitive’s own modules are built with defineModule()—the same tool you have.