Files
astrolabe/.claude/projects/-Users-oleh-code-astrolabe/memory/stack-moving-to-react.md
T

1.7 KiB

name, description, metadata
name description metadata
stack-moving-to-react Astrolabe's UI stack is React + Zustand (migrated from Preact + signals at M0)
type
project

The UI stack is React + Zustand (user decision, 2026-06-03, executed at M0 before feature work). It started as Preact + @preact/signals; a brief intermediate step migrated to React + @preact/signals-react, but the final call is React + Zustand — signals were dropped.

Why React: the Preact pain was React-ecosystem friction (real-React-only libraries not cooperating with preact/compat) — not the signals model. Real React removes that whole class of problem and makes borrowing from the reference vega-editor-reference-clone (a React app) port directly.

Why Zustand over keeping signals: signals were never the problem, but switching framework was the one cheap moment (M0, ~nothing implemented) to also pick the lowest-future-migration-risk state lib. Zustand is idiomatic React, has first-class outside-React access (getState/setState/subscribe) that fits the "logic lives in core/services, not components" architecture, and carries no build-time transform. The signals→Zustand cost was only rewriting unimplemented docs.

How to apply: Stores are create<State>() modules exporting a useXStore hook (state + actions in one object); components read via useXStore(selector) (+ useShallow for object selections); non-component code uses getState()/setState()/subscribe(); derive in selectors, never store derived fields. See docs/architecture/01-state-and-stores.md. The repo-wide Preact/signals→React/Zustand doc sweep is done — no stale "Preact"/"signals" wording should remain except where it describes the sibling project Syto, Vega's own signals, or plain English.