Solid store
Global dependency graph. Read = subscribe. get is lazy + cached. Component functions mount once; JSX sinks re-read. No useMemo lies.
The Rust of frontend
Poi is a language where store is solid (leaf updates, not tree re-renders), ADTs are exhaustive (missing UI state = compile error), and fine-grained sinks keep runtime cost flat as the app grows. Constraints are the product — convenience is a side-effect.
Global dependency graph. Read = subscribe. get is lazy + cached. Component functions mount once; JSX sinks re-read. No useMemo lies.
Option · Result · Async · View sums. Missing empty / error / loading is a compile error — not a blank screen at 3am.
Fine-grained by default. One cell write → one leaf. List of 10 or 10,000: the write budget does not become O(N) re-renders.
React re-renders the component (and often its children) on every setState.
Poi tracks which cells each leaf reads. Write count → only count sinks fire.
Sibling state stays cold.
Left: typical React tree blast · Right: Poi graph + leaf sinks
Click an action. Watch React light up the whole tree while Poi pulses only the dependency cone.
Fold loading / empty / error / rows into one View sum. The component only matches.
Drop an arm — the program does not compile. No “blank panel until a user finds it.”
Current tag: Loading
Scale the list. Tick a single cell write. React-style work units climb with N. Poi updates one leaf — always. That is not a clever memo trick you might forget; it is the language default.
Work units per write · cumulative after ticks
Scale N, then tick. Orange flash = whole-tree simulation. Mint cell = the single Poi leaf that actually updates.
Mount once. Track what you read. Never pay for what you did not touch.
Signals exist in JS. ADTs exist in TS. The difference is enforcement: Poi makes the solid path the only path that compiles.
as → runtime crash laterunknown until match| You reach for | Poi | Why it stays solid |
|---|---|---|
useState / zustand field |
store({ n: 0 }) |
Cell graph · read = subscribe |
useMemo([deps]) |
get x() { … } |
Auto deps · lazy · cached · pure |
| Component re-render | Leaf sinks / mapList | Mount once · O(1) text updates |
| Scattered UI ifs | View sum + match |
Missing arm = compile error |
JSON.parse + cast |
parseJson + field match |
No as wash on unknown |
Shape the terrain so humans and AI both flow toward low entropy.