Causl Essentials Tutorial
Welcome to the Causl Essentials Tutorial. This eight-part walkthrough builds a small but realistic application from an empty folder up to a fully wired, statically checked, persisted, and reactive UI. Every concept is introduced step-by-step, with motivation before mechanics and a working code example at every stage.
If you have already worked through the
Getting Started guide and want a guided path through
Causl's full surface area — the seven canonical methods on Graph, the
React bindings, the async lifecycle helpers, the persistence adapters, and the static
checker — this tutorial is the place to start. It is the recommended on-ramp for new
adopters and is the closest analogue to Redux's "Essentials" tutorial in style and
pacing.
What you will build
The running example is a small incident-tracking dashboard: a list
of open incidents, derived counts of severities, a filtered view that depends on
both the raw rows and a user-controlled filter, an async loader that fetches the
initial rows from a server, and a persistence layer that snapshots the local state
to localStorage between visits. The example is deliberately tangled —
it has the kind of "if A changes, B and C also have to change, but B's new value
then feeds D" graph that motivated Causl in the first place. By the end you will
have built and shipped an app where every piece of state in the UI is a
pure function of inputs you can name, and where the engine — not your reducers —
decides what to recompute and in what order.
Prerequisites
- Working knowledge of TypeScript and modern JavaScript modules.
- Familiarity with React function components and hooks for Parts 5–6. (The core engine works without React; if you are using Causl outside of React you can skim those parts.)
- A package manager — the examples assume pnpm, but
npmandyarnwork identically. - Node.js 18.18 or later.
You do not need to have read the SPEC.md first. The tutorial introduces the concepts you need as it goes; we cite the SPEC where the underlying contract is precise enough to matter (atomicity, dependency tracking, observer ordering, the Phase A–H pipeline).
Table of contents
-
Part 1Setting Up Your Project
Scaffold a Vite project, install
@causl/core, lay out thesrc/tree, and write your firstcreateCausl()call with a single input, a single derivation, and a commit you can read back. -
Part 2Building Your First Graph
Coming soon. Turn the incident-tracker domain
into a set of inputs, derivations, and identifiers. Cover the
information-model namespace, when to split a node vs. nest a value, and the
NodeIdrules. -
Part 3Derived Nodes and Dependency Tracking
Coming soon. How
graph.derived()infers its dependency set from the trackedgetaccessor, how re-wiring works across branches, and whatgraph.explain()tells you when a derivation behaves unexpectedly. -
Part 4Statecharts
Coming soon.
graph.commit(), atomic-or-nothing semantics,simulate()for dry runs, and the errors you can catch —CycleError,NotAnInputNodeError,StaleTxError. -
Part 5React Integration
Coming soon.
@causl/react,useCauslNode, theCauslProviderpattern, and how subscriptions in Phase G drive React renders. -
Part 6Saving & Loading
Coming soon.
@causl/syncfor async resource lifecycles —idle→loading→ready— and avoiding the race classes the engine catches for you. -
Part 7Testing Causl Code
Coming soon.
graph.snapshot()/graph.hydrate(),@causl/persistenceadapters, and the'hydrate'commit-intent convention. -
Part 8A Real-World Application
Coming soon. Run the bounded model checker
against your
exportModel()IR, surface race-class violations before they ship, and integrate the checker into CI.
How to use this tutorial
Each part stands on its own enough that you can skim to the section that maps to a problem you are solving today, but the example carries through linearly — Part 5 assumes you have the graph from Part 3, Part 7 assumes the loader from Part 6, and so on. If you want to jump in mid-stream, every part includes a "starting point" gist link at the top.
Where Causl is not the right tool. Causl shines on tangled,
derivation-heavy state. If your app's state is a flat list of independent values
with no relationships, plain useState is simpler. If your data graph
is huge and mostly read-only, a query cache like TanStack Query is closer to what
you want. The home page's
"Where causl is the right tool — and where it isn't"
section spells out the boundary in more detail.