Skip to content

Commit 53d7902

Browse files
committed
feat: adjust docs
1 parent 7be0595 commit 53d7902

8 files changed

Lines changed: 167 additions & 76 deletions

File tree

README.md

Lines changed: 118 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,27 @@
44
55
React observes your system. React doesn't own it.
66

7+
**Braided** is a minimal, type-safe library for declarative system composition with dependency-aware lifecycle management. **Braided React** provides the bridge to use those systems seamlessly in React applications.
8+
9+
## What is Braided?
10+
11+
[**Braided**](https://github.com/RegiByte/braided) is a minimal (~300 lines), type-safe library for declarative system composition with dependency-aware lifecycle management. It lets you define stateful resources (databases, WebSockets, caches, etc.) with explicit dependencies, and handles starting/stopping them in the correct order.
12+
13+
Think of it as **dependency injection + lifecycle management** for JavaScript, inspired by Clojure's Integrant.
14+
715
## Why Braided React?
816

9-
Modern React apps often need to manage complex, long-lived resources that don't fit neatly into the react component lifecycle:
17+
Modern React apps often need to manage complex, long-lived resources that don't fit neatly into the React component lifecycle:
1018

1119
- **WebSockets & Real-time Feeds** (Chat, Multiplayer Games)
1220
- **Audio/Video Contexts** (WebRTC, Music Apps)
1321
- **Complex API Clients** (Authentication, Retries, Caching)
1422
- **Game Loops & Simulations**
23+
- **Background Tasks** (Sync, Polling, Timers)
1524

1625
Managing these inside `useEffect` often leads to "dependency hell," double-initialization in StrictMode, and race conditions.
1726

18-
**Braided React** solves this by letting you define your system *outside* React, and then bridging it *into* React as a fully-typed dependency injection layer.
27+
**Braided React** solves this by letting you define your system _outside_ React using Braided, and then bridging it _into_ React as a fully-typed dependency injection layer. Your resources outlive React's mount/unmount cycles and you decide when/how to stop them.
1928

2029
## Features
2130

@@ -31,157 +40,183 @@ Managing these inside `useEffect` often leads to "dependency hell," double-initi
3140
npm install braided-react braided
3241
```
3342

34-
Peer dependencies: `react >= 18.0.0` and `braided >= 0.0.4`
43+
**Requirements:**
44+
45+
- `react >= 18.0.0` (peer dependency)
46+
- `braided >= 0.0.4` (peer dependency)
47+
48+
**Note:** You need both libraries. [Braided](https://github.com/RegiByte/braided) defines your system, Braided React bridges it to React.
3549

3650
## Quick Start
3751

3852
### 1. Define Your System (outside React)
3953

4054
```typescript
4155
// system.ts
42-
import { defineResource } from 'braided'
43-
import { createSystemHooks } from 'braided-react'
56+
import { defineResource } from "braided";
57+
import { createSystemHooks } from "braided-react";
4458

4559
// A simple logger resource
46-
const logger = defineResource({
60+
const loggerResource = defineResource({
4761
start: () => ({
48-
log: (msg: string) => console.log(`[Log]: ${msg}`)
49-
})
50-
})
62+
log: (msg: string) => console.log(`[Log]: ${msg}`),
63+
}),
64+
});
5165

5266
// An API client resource that depends on logger
5367
const apiClient = defineResource({
54-
dependencies: ['logger'],
55-
start: ({ logger }) => ({
68+
dependencies: ["logger"],
69+
start: ({ logger }: { logger: StartedResource<typeof loggerResource> }) => ({
5670
fetchUser: async (id: string) => {
57-
logger.log(`Fetching user: ${id}`)
58-
return fetch(`/api/users/${id}`).then(r => r.json())
59-
}
60-
})
61-
})
71+
logger.log(`Fetching user: ${id}`);
72+
return fetch(`/api/users/${id}`).then((r) => r.json());
73+
},
74+
}),
75+
});
6276

63-
export const systemConfig = { logger, apiClient }
77+
export const systemConfig = { logger: loggerResource, api: apiClient };
6478

6579
// Create your typed hooks!
66-
export const { SystemBridge, useResource } = createSystemHooks<typeof systemConfig>()
80+
export const { SystemBridge, useResource } =
81+
createSystemHooks<typeof systemConfig>();
6782
```
6883

6984
### 2. Initialize & Bridge
7085

7186
```typescript
7287
// main.tsx
73-
import { startSystem } from 'braided'
74-
import { SystemBridge, systemConfig } from './system'
88+
import { startSystem } from "braided";
89+
import { SystemBridge, systemConfig } from "./system";
7590

76-
// Start the system *before* React mounts
77-
const { system } = await startSystem(systemConfig)
91+
// Start (or just kick off) the system *before* React mounts
92+
const { system } = await startSystem(systemConfig);
7893

79-
ReactDOM.createRoot(document.getElementById('root')!).render(
94+
ReactDOM.createRoot(document.getElementById("root")!).render(
8095
<SystemBridge system={system}>
8196
<App />
8297
</SystemBridge>
83-
)
98+
);
8499
```
85100

86101
### 3. Use in Components
87102

88103
```typescript
89104
// App.tsx
90-
import { useResource } from './system'
105+
import { useResource } from "./system";
91106

92107
function UserProfile({ id }) {
93108
// Fully typed! TypeScript knows 'apiClient' has a fetchUser method.
94-
const api = useResource('apiClient')
109+
const api = useResource("apiClient");
95110

96111
const handleLoad = async () => {
97-
const user = await api.fetchUser(id)
98-
console.log(user)
99-
}
112+
const user = await api.fetchUser(id);
113+
console.log(user);
114+
};
100115

101-
return <button onClick={handleLoad}>Load User</button>
116+
return <button onClick={handleLoad}>Load User</button>;
102117
}
103118
```
104119

105120
---
106121

107122
## Examples
108123

109-
### Basic Example
110-
[`examples/basic/`](./examples/basic/)
124+
We provide **4 complete examples** demonstrating different integration patterns. Each solves different use cases:
125+
126+
### 1. [Basic - useSyncExternalStore](./examples/basic/)**Start Here**
111127

112-
Pre-started system with counter and logger. Shows the recommended pattern.
128+
Modern React 18 integration using `useSyncExternalStore` API for automatic reactivity.
113129

114130
```bash
115131
cd examples/basic
116132
npm install && npm run dev
117133
```
118134

119-
### Singleton Manager Example
120-
[`examples/singleton-manager/`](./examples/singleton-manager/)
135+
**Best for:** Modern React apps, learning the recommended pattern
136+
137+
### 2. [Lazy Start - Zustand Integration](./examples/lazy-start/)
138+
139+
Zustand stores managed as Braided resources for centralized state management.
140+
141+
```bash
142+
cd examples/lazy-start
143+
npm install && npm run dev
144+
```
145+
146+
**Best for:** Apps with complex state management, multiple coordinated stores
121147

122-
Role-based systems (host vs player) with lazy initialization.
148+
### 3. [Singleton Manager - Event Bus](./examples/singleton-manager/)
149+
150+
Resources communicating through an event bus for loose coupling.
123151

124152
```bash
125153
cd examples/singleton-manager
126154
npm install && npm run dev
127155
```
128156

129-
### Lazy Start Example
130-
[`examples/lazy-start/`](./examples/lazy-start/)
157+
**Best for:** Complex systems, event-driven architectures, microservices/microfrontend-style apps
158+
159+
### 4. [Outliving React](./examples/outliving-react/) 🔥
131160

132-
System starts on mount with loading states and async resources.
161+
Simple example that demonstrates the core functionality of the library: your system running even when React is unmounted. It's up to you how to compose this powerful pattern into your app.
133162

134163
```bash
135-
cd examples/lazy-start
164+
cd examples/outliving-react
136165
npm install && npm run dev
137166
```
138167

168+
**Best for:** Music players, WebSocket apps, background sync, game engines, scheduled tasks, etc.
169+
170+
See [examples/README.md](./examples/README.md) for detailed comparison and learning path.
171+
139172
## Reactivity & State Management
140173

141-
**Important:** `braided-react` is a Dependency Injection (DI) library, **not** a state management library.
174+
**Important:** `braided-react` is a Lifecycle management and Dependency Injection (DI) library, **not** a state management library.
142175

143-
When you call `useResource('counter')`, you get the *instance* of the counter. If properties on that instance change, your component **will not re-render** automatically.
176+
When you call `useResource('counter')`, you get the _instance_ of the counter. If properties on that instance change, your component **will not re-render** automatically.
144177

145-
### Recommended Pattern: Zustand Integration
178+
### Recommended Pattern: Zustand Integration or your preferred state management library
146179

147-
To make your UI reactive, we recommend using a state manager like [Zustand](https://github.com/pmndrs/zustand) alongside your Braided resources.
180+
To make your UI reactive, we recommend using a state manager like [Zustand](https://github.com/pmndrs/zustand) alongside your system resources or as one of them if you'd like.
148181

149-
1. **Resource:** Holds the *business logic* and *connections* (e.g., WebSocket).
150-
2. **Store:** Holds the *reactive state* (e.g., current messages).
182+
1. **Resource:** Holds the _business logic_ and _connections_ (e.g., WebSocket).
183+
2. **Store:** Holds the _reactive state_ (e.g., current messages).
151184
3. **Component:** Subscribes to the store and calls methods on the resource.
152185

153186
```typescript
154187
// 1. Define Store
155188
const useChatStore = create((set) => ({
156189
messages: [],
157-
addMessage: (msg) => set((state) => ({ messages: [...state.messages, msg] }))
158-
}))
190+
addMessage: (msg) => set((state) => ({ messages: [...state.messages, msg] })),
191+
}));
159192

160193
// 2. Define Resource (connects to store)
161194
const chatClient = defineResource({
162195
start: () => {
163-
const socket = new WebSocket('wss://api.chat.com')
196+
const socket = new WebSocket("wss://api.chat.com");
164197
socket.onmessage = (event) => {
165198
// Update the store directly!
166-
useChatStore.getState().addMessage(event.data)
167-
}
199+
useChatStore.getState().addMessage(event.data);
200+
};
168201
return {
169-
sendMessage: (msg) => socket.send(msg)
170-
}
171-
}
172-
})
202+
sendMessage: (msg) => socket.send(msg),
203+
};
204+
},
205+
});
173206

174207
// 3. Component
175208
function ChatRoom() {
176-
const chat = useResource('chatClient') // Get the imperative resource
177-
const messages = useChatStore((state) => state.messages) // Get the reactive state
209+
const chat = useResource("chatClient"); // Get the imperative resource
210+
const messages = useChatStore((state) => state.messages); // Get the reactive state
178211

179212
return (
180213
<div>
181-
{messages.map(m => <div key={m}>{m}</div>)}
182-
<button onClick={() => chat.sendMessage('Hello!')}>Send</button>
214+
{messages.map((m) => (
215+
<div key={m}>{m}</div>
216+
))}
217+
<button onClick={() => chat.sendMessage("Hello!")}>Send</button>
183218
</div>
184-
)
219+
);
185220
}
186221
```
187222
@@ -194,21 +229,21 @@ This separation of concerns (imperative logic vs. reactive state) is extremely p
194229
If you don't want to block your app startup, use `createSystemManager` and `LazySystemBridge`.
195230
196231
```typescript
197-
import { createSystemManager, LazySystemBridge } from 'braided-react'
232+
import { createSystemManager, LazySystemBridge } from "braided-react";
198233

199234
// Create a manager singleton
200-
const apiManager = createSystemManager(apiConfig)
235+
const apiManager = createSystemManager(apiConfig);
201236

202237
function App() {
203238
return (
204-
<LazySystemBridge
205-
manager={apiManager}
239+
<LazySystemBridge
240+
manager={apiManager}
206241
SystemBridge={SystemBridge}
207242
fallback={<div>Connecting to API...</div>}
208243
>
209244
<Dashboard />
210245
</LazySystemBridge>
211-
)
246+
);
212247
}
213248
```
214249
@@ -218,6 +253,24 @@ function App() {
218253
- **Manager:** `createSystemManager()`. System starts on first demand, persists across remounts.
219254
- **Lazy Bridge:** `LazySystemBridge` with `onUnmount`. System starts on mount, halts on unmount (optional).
220255
256+
## Related Projects
257+
258+
- **[Braided](https://github.com/RegiByte/braided)** - The core system composition library
259+
- **[Braided React](https://github.com/RegiByte/braided-react)** - React integration (this library)
260+
261+
## Philosophy
262+
263+
**Braided React** follows the same philosophy as Braided:
264+
265+
1. **Simple over easy** - Minimal API that composes well
266+
2. **Explicit over implicit** - No magic, no scanning, just data
267+
3. **Data over code** - Systems are declared as data structures
268+
4. **Testable by default** - No global state, easy to mock
269+
5. **Type-safe** - Full TypeScript support with inference
270+
6. **React observes, doesn't own** - System lifecycle is independent
271+
272+
For more on the philosophy, see the [Braided README](https://github.com/RegiByte/braided#philosophy).
273+
221274
## License
222275
223276
ISC

examples/README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# 🧶 Braided React Examples
22

3-
Four complete examples demonstrating modern patterns for integrating Braided systems with React.
3+
Four complete examples demonstrating modern patterns for integrating [Braided](https://github.com/RegiByte/braided) systems with React.
4+
5+
**What is Braided?** A minimal, type-safe library for declarative system composition with dependency-aware lifecycle management. Think dependency injection + lifecycle management for JavaScript.
6+
7+
**What is Braided React?** The bridge that lets you use Braided systems in React applications without giving up lifecycle control.
48

59
## Examples Overview
610

@@ -237,4 +241,9 @@ All examples follow these principles:
237241

238242
**Untangle your code. Compose your systems. Let React observe.** 🧶
239243

240-
[Main Docs](../README.md)[npm](https://www.npmjs.com/package/braided-react)[GitHub](https://github.com/RegiByte/braided-react)
244+
## Learn More
245+
246+
- **[Braided](https://github.com/RegiByte/braided)** - The core system composition library
247+
- **[Braided React](https://github.com/RegiByte/braided-react)** - React integration (Main Docs)
248+
- **[npm: braided](https://www.npmjs.com/package/braided)** - Core library on npm
249+
- **[npm: braided-react](https://www.npmjs.com/package/braided-react)** - React integration on npm

examples/basic/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,9 @@ function Counter() {
7070
```
7171

7272
This is the **modern React way** to integrate external state sources!
73+
74+
## Learn More
75+
76+
- **[Braided](https://github.com/RegiByte/braided)** - The core system composition library
77+
- **[Braided React](https://github.com/RegiByte/braided-react)** - React integration docs
78+
- **[All Examples](../)** - See other integration patterns

examples/lazy-start/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,9 @@ function Counter() {
7474
- You want to coordinate multiple stores
7575
- Other resources need to react to state changes
7676
- You're building complex, long-lived applications
77+
78+
## Learn More
79+
80+
- **[Braided](https://github.com/RegiByte/braided)** - The core system composition library
81+
- **[Braided React](https://github.com/RegiByte/braided-react)** - React integration docs
82+
- **[All Examples](../)** - See other integration patterns

examples/outliving-react/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,9 @@ Watch the console as you unmount/remount React:
121121

122122
This is the power of Braided - **React observes, doesn't own.**
123123

124+
## Learn More
125+
126+
- **[Braided](https://github.com/RegiByte/braided)** - The core system composition library
127+
- **[Braided React](https://github.com/RegiByte/braided-react)** - React integration docs
128+
- **[All Examples](../)** - See other integration patterns
129+

0 commit comments

Comments
 (0)