All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.1.0 - 2025-12-13
This release represents a fundamental redesign of braided-react based on lessons learned from building real-world applications. The new design embraces the Observer Pattern and direct closure access, while integrating seamlessly with React's primitives (Suspense, ErrorBoundary).
- Direct Closure Access: Manager is now passed to
createSystemHooks(), enabling direct access without Context indirection - Automatic Suspense Integration:
useSystem()anduseResource()now suspend (throw Promise) while system is starting - Automatic ErrorBoundary Integration: Hooks throw errors when system startup fails, triggering ErrorBoundary
- Manual Control Hook: New
useSystemStatus()hook for explicit startup control (welcome screens, deferred startup) - Config Exposure:
manager.confignow exposed for inspection and testing - SystemProvider: Renamed from
SystemBridgefor clarity (Context override for testing/DI)
- BREAKING:
createSystemHooks()now requires a manager parameter- Before:
createSystemHooks<typeof config>() - After:
createSystemHooks(manager)
- Before:
- BREAKING:
SystemBridgerenamed toSystemProvider- More accurately reflects its purpose (Context injection for testing)
- Resolution Order: Hooks now check Context first (DI override), then fall back to manager (production)
- BREAKING:
LazySystemBridgecomponent removed- Replaced by:
<Suspense>+useSystem()(automatic) - Or:
useSystemStatus()(manual control)
- Replaced by:
Before (v0.0.2):
const { SystemBridge, useSystem } = createSystemHooks<typeof config>()
const manager = createSystemManager(config)
<LazySystemBridge manager={manager} SystemBridge={SystemBridge}>
<App />
</LazySystemBridge>After (v0.1.0):
const manager = createSystemManager(config)
const { useSystem } = createSystemHooks(manager)
<Suspense fallback={<Loading />}>
<ErrorBoundary FallbackComponent={ErrorScreen}>
<App />
</ErrorBoundary>
</Suspense>Before (v0.0.2):
// Had to manage state manually outside LazySystemBridge
const [started, setStarted] = useState(false)
if (!started) {
return <WelcomeScreen onStart={() => setStarted(true)} />
}
return (
<LazySystemBridge manager={manager} SystemBridge={SystemBridge}>
<App />
</LazySystemBridge>
)After (v0.1.0):
const { useSystemStatus } = createSystemHooks(manager)
function App() {
const { isIdle, isLoading, startSystem } = useSystemStatus()
if (isIdle) return <WelcomeScreen onStart={startSystem} />
if (isLoading) return <LoadingScreen />
return <ChatRoom />
}Testing with Context injection still works the same way:
const { SystemProvider } = createSystemHooks(manager)
test('component works', async () => {
const { system } = await startSystem(mockConfig)
render(
<SystemProvider system={system}>
<Component />
</SystemProvider>
)
})Problem: Context was used to pass system reference to React, but the system already lives in closure space (Z-axis). React can observe it directly through hooks.
Solution: Pass manager to createSystemHooks(). Hooks access the manager directly from closure.
Benefits:
- ✅ Simpler mental model (one source of truth)
- ✅ Less boilerplate (no wrapper component needed)
- ✅ Faster (no context lookup)
- ✅ Aligns with Observer Pattern (React observes closure space)
Problem: Loading states were managed via callbacks (fallback prop) instead of React's built-in primitives.
Solution: useSystem() throws Promise when system is starting, triggering Suspense.
Benefits:
- ✅ Standard React pattern (developers already know this)
- ✅ Composable (multiple Suspense boundaries)
- ✅ Works with concurrent rendering
- ✅ Less code (no manual loading state)
Problem: Error handling was callback-based (onError prop), not composable.
Solution: useSystem() throws Error when startup fails, triggering ErrorBoundary.
Benefits:
- ✅ Standard React pattern
- ✅ Composable error boundaries
- ✅ Centralized error handling
- ✅ User-friendly fallbacks
Problem: Testing needs dependency injection.
Solution: Context as optional override, not requirement. Check Context first, then manager.
Benefits:
- ✅ Flexible testing (mock entire system)
- ✅ Multi-tenancy support
- ✅ Runtime config changes
- ✅ Backward compatible (testing pattern unchanged)
Problem: Some apps need explicit startup timing (welcome screens, deferred startup).
Solution: useSystemStatus() hook that doesn't suspend, returns status and manual trigger.
Benefits:
- ✅ Welcome screens before startup
- ✅ Deferred startup until user action
- ✅ Custom loading/error UI
- ✅ Not prescriptive (use when needed)
This redesign fully embraces the dimensional model:
- Z-axis (Closure Space): Where systems live independently
- X-Y Plane (React Tree): Where components render
- Hooks: Windows between these dimensions
Systems are module singletons in closure space. React components observe them through hooks. This separation gives you:
- Lifecycle independence - System outlives React mounts/unmounts
- No prop drilling - Direct access from any component
- Testing flexibility - Context override for dependency injection
- Performance - System lives outside React's render cycle
React components are observers of your system. They watch for changes and re-render when needed. But they don't control the system's lifecycle.
Before: Context made it seem like React "owned" the system After: Direct closure access makes it clear React is just observing
This is the same pattern used by:
- React Query (for server state)
- Zustand (for client state)
- Jotai (for atomic state)
This redesign achieves:
- ✅ Less boilerplate - Fewer concepts, simpler setup
- ✅ Better integration - Works with Suspense, ErrorBoundary, DevTools
- ✅ More flexible - Context still available for DI when needed
- ✅ Type-safe - Full inference preserved
- ✅ Testable - Multiple testing patterns supported
- ✅ Performant - Direct closure access, no context overhead
This redesign was informed by building real-world examples, particularly a WebSocket chat application. The patterns that emerged from that work revealed the true nature of the library: React observes systems in closure space.
0.0.2 - 2024-12-XX
- Initial release
createSystemHooks()for typed React hookscreateSystemManager()for singleton system managementLazySystemBridgecomponent for lazy initializationSystemBridgecontext provider- Full TypeScript support with type inference
- Basic examples
- README with usage patterns
- API documentation
0.0.1 - 2024-12-XX
- Initial prototype
- Core concepts established