Skip to content

Latest commit

 

History

64 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Retree

Retree is a lightweight and simple state management library, designed primarily for React. If you know how to work with objects in JavaScript or TypeScript, you pretty much already know how to use Retree.

import { Retree } from "@retreejs/core";
import { useNode } from "@retreejs/react";

const project = Retree.root({
    tasks: [{ title: "Write docs", done: false }],
});

function TaskRow({ task }: { task: { title: string; done: boolean } }) {
    const state = useNode(task); // re-renders only when this task changes
    return (
        <label>
            <input
                type="checkbox"
                checked={state.done}
                onChange={() => (state.done = !state.done)}
            />
            {state.title}
        </label>
    );
}

Full documentation, live playgrounds, and guides live at retree.dev.

Quick start

Add Retree to an existing project with the interactive installer:

npm create @retreejs@latest

It detects React and Convex in your project, preselects the matching integrations, and can install the Retree AI skill for coding agents. In React + ESLint + TypeScript projects it also offers the Retree observation rule and can update eslint.config.mjs for you. pnpm create @retreejs and yarn create @retreejs work too. Then start with the Quickstart guide.

Decorators are optional

Retree needs zero build configuration — Retree.root, the React hooks, ReactiveNode with its dependencies getter, and this.memo(...) all work out of the box. Only authoring the @-prefixed decorators (@memo, @fnMemo, @select, @ignore, @link) in your own code requires standard (TC39 2023-11) decorator support:

  • TypeScript 5+: works with no config, as long as experimentalDecorators is not set. Legacy decorator semantics are incompatible — Retree's decorators detect them and throw an error explaining the fix.
  • Babel toolchains: add @babel/plugin-proposal-decorators with { "version": "2023-11" }.

Each decorator has a non-decorator equivalent (this.memo(...), the dependencies getter with this.dependency(...), Retree.link(...)). Full guide: Setup & decorators.

Packages

  • @retreejs/core provides Retree's proxy, event, memo, ReactiveNode, effect, and undo-history primitives.
  • @retreejs/react provides React hooks for rendering Retree nodes, a provider for per-request SSR roots, and testing utilities.
  • @retreejs/query is the backend-agnostic async-query layer: QueryNode, fetch adapters, optimistic updates, and reconciliation over any subscription source.
  • @retreejs/convex connects Convex queries, paginated queries, actions, mutations, auth, and connection state to Retree nodes.
  • @retreejs/react-convex adapts Convex's ConvexReactClient for React apps that want one client instance for both Convex React and Retree, plus a Next.js RSC preload helper.
  • @retreejs/devtools bridges Retree to the Redux DevTools Extension and exposes a structured change-log tap.
  • @retreejs/react-eslint-plugin catches React render reads that go beyond the Retree node a component observes.

Feature glossary

Core:

  • Retree.root makes one object the root of a Retree-managed tree. Use it once where plain state enters Retree.
  • Retree.on subscribes to nodeChanged, treeChanged, or nodeRemoved. Use it outside React and inside integrations.
  • Retree.select is the non-React version of useSelect. Use it to narrow notifications; it is not a cache.
  • Retree.effect runs a function immediately and re-runs it whenever a tracked dependency changes — the third subscription primitive next to on and select.
  • createUndoHistory records every change under a root into undo/redo steps; Retree.applyInverse / Retree.applyChanges are the underlying primitives.
  • Retree.parent returns the structural parent of a node. Use it for tree-local operations like deleting yourself from a list.
  • Retree.move, Retree.link / @link, and Retree.clone make ownership explicit: transfer, point without reparenting, or copy.
  • Retree.isNode checks whether a value is a Retree-managed node. Use it to guard Retree.raw when a value may be managed or plain.
  • Retree.raw, Retree.managed, Retree.peekInto, and Retree.untracked enable native-speed, proxy-free reads. Raw subtrees are guaranteed proxy-free.
  • Retree.runTransaction batches synchronous writes into one listener flush per changed node.
  • Retree.runSilent performs writes without emitting listeners.
  • Retree.registerRootName names a root for tooling — debug taps and devtools label trees with it.
  • ReactiveNode lets nodes emit from declared dependencies, with @select getters, memo / @memo / @fnMemo caching, @ignore opt-outs, lifecycle hooks, and prepareTree.

React:

  • useRoot creates one Retree root for a React component lifetime.
  • useNode re-renders a component for direct nodeChanged events on one node. Use it for rows, panels, forms, and focused child components.
  • useTree re-renders for treeChanged events from a node or any descendant. Use it sparingly for small subtrees.
  • useSelect re-renders only when a selected value or ordered dependency list changes.
  • useRaw subscribes like useNode but returns [raw, toManaged] for native-speed, proxy-free render reads.
  • RetreeProvider / createRetreeContext provide per-request roots for SSR apps and per-render roots for tests, instead of module singletons.
  • @retreejs/react/testing ships createTestRoot (auto listener cleanup) and actOnRetree (act-wrapped writes) for component tests.
  • @retreejs/react-eslint-plugin provides a typed ESLint preset that catches provably unobserved Retree reads in React components.

Data:

Agent docs and skill

Published Retree npm packages include their package README.md and the root llms.txt file so sandboxed agents can read the high-signal Retree guide directly from an installed package. The website serves every guide as raw markdown too (see retree.dev/llms.txt).

This repository also exposes a Retree agent skill at skills/retree/SKILL.md, with full markdown references generated from the docs sources into skills/retree/references/. npm run docs refreshes those references after the TypeDoc site builds. Agents that support the open skills CLI can install or use it with:

npx skills add ryanbliss/retree --skill retree
npx skills use ryanbliss/retree@retree

API docs

The primary API reference is generated from source on every deploy at retree.dev/api. To generate the TypeDoc site locally instead:

npm run docs

The generated static site is written to docs/ and ignored by Git.

Docs

Docs are hosted at https://www.retree.dev.

Licensing & Copyright

Copyright (c) Ryan Bliss. All rights reserved. Licensed under MIT license.

Credit to Fluid Framework's new SharedTree feature, which has served as a major inspiration for this project. If you want to use collaborative objects, I recommend checking out Fluid Framework!

About

Simple state framework for precise, lighting-fast reactive rendering.

Topics

Resources

Contributing

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages