@powerhousedao/academy 5.1.0-dev.1 → 5.1.0-dev.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +74 -0
- package/blog/BeyondCommunication-ABlueprintForDevelopment.md +2 -1
- package/blog/TheChallengeOfChange.md +1 -0
- package/docs/academy/01-GetStarted/00-ExploreDemoPackage.mdx +24 -27
- package/docs/academy/01-GetStarted/01-CreateNewPowerhouseProject.md +118 -9
- package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +110 -28
- package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +191 -145
- package/docs/academy/01-GetStarted/04-WriteDocumentModelTests.md +378 -0
- package/docs/academy/01-GetStarted/05-BuildToDoListEditor.md +560 -0
- package/docs/academy/01-GetStarted/_04-BuildToDoListEditor +1 -1
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/03-BuilderTools.md +2 -2
- package/docs/academy/{01-GetStarted → 02-MasteryTrack/01-BuilderEnvironment}/05-VetraStudio.md +48 -6
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/02-SpecifyTheStateSchema.md +75 -44
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/03-SpecifyDocumentOperations.md +28 -22
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/04-UseTheDocumentModelGenerator.md +28 -31
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/05-ImplementDocumentReducers.md +211 -206
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/06-ImplementDocumentModelTests.md +176 -62
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/07-ExampleToDoListRepository.md +21 -0
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/01-BuildingDocumentEditors.md +309 -319
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/00-DocumentToolbar.mdx +4 -0
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/01-OperationHistory.md +4 -0
- package/docs/academy/02-MasteryTrack/05-Launch/04-ConfigureEnvironment.md +1 -1
- package/docs/academy/03-ExampleUsecases/Chatroom/02-CreateNewPowerhouseProject.md +111 -35
- package/docs/academy/03-ExampleUsecases/Chatroom/03-DefineChatroomDocumentModel.md +255 -76
- package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +281 -160
- package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +188 -35
- package/docs/academy/03-ExampleUsecases/Chatroom/06-LaunchALocalReactor.md +95 -7
- package/docs/academy/03-ExampleUsecases/Chatroom/_category_.json +1 -1
- package/docs/academy/03-ExampleUsecases/TodoList/00-GetTheStarterCode.md +24 -0
- package/docs/academy/03-ExampleUsecases/TodoList/01-GenerateTodoListDocumentModel.md +211 -0
- package/docs/academy/03-ExampleUsecases/TodoList/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +171 -0
- package/docs/academy/03-ExampleUsecases/TodoList/03-AddTestsForTodoListActions.md +462 -0
- package/docs/academy/03-ExampleUsecases/TodoList/04-GenerateTodoListDocumentEditor.md +45 -0
- package/docs/academy/03-ExampleUsecases/TodoList/05-ImplementTodoListDocumentEditorUIComponents.md +422 -0
- package/docs/academy/03-ExampleUsecases/TodoList/06-GenerateTodoDriveExplorer.md +61 -0
- package/docs/academy/03-ExampleUsecases/TodoList/07-AddSharedComponentForShowingTodoListStats.md +384 -0
- package/docs/academy/03-ExampleUsecases/TodoList/_category_.json +8 -0
- package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/VetraPackageLibrary.md +7 -0
- package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/_category_.json +9 -0
- package/docs/academy/04-APIReferences/00-PowerhouseCLI.md +6 -2
- package/docs/academy/04-APIReferences/01-ReactHooks.md +2 -2
- package/docs/academy/04-APIReferences/06-VetraRemoteDrive.md +160 -0
- package/docs/academy/04-APIReferences/renown-sdk/00-Overview.md +316 -0
- package/docs/academy/04-APIReferences/renown-sdk/01-Authentication.md +672 -0
- package/docs/academy/04-APIReferences/renown-sdk/02-APIReference.md +957 -0
- package/docs/academy/04-APIReferences/renown-sdk/_category_.json +8 -0
- package/docs/academy/05-Architecture/00-PowerhouseArchitecture.md +7 -39
- package/docs/academy/06-ComponentLibrary/00-DocumentEngineering.md +72 -24
- package/docs/academy/08-Glossary.md +7 -0
- package/docs/academy/10-TodoListTutorial/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +171 -0
- package/docs/academy/10-TodoListTutorial/03-AddTestsForTodoListActions.md +462 -0
- package/docs/academy/10-TodoListTutorial/05-ImplementTodoListDocumentEditorUIComponents.md +422 -0
- package/docs/academy/10-TodoListTutorial/07-AddSharedComponentForShowingTodoListStats.md +370 -0
- package/docusaurus.config.ts +28 -3
- package/package.json +1 -1
- package/sidebars.ts +49 -12
- package/src/css/custom.css +26 -18
- package/static/img/Vetra-logo-dark.svg +11 -0
- package/static/img/vetra-logo-light.svg +11 -0
- package/docs/academy/00-EthereumArgentinaHackathon.md +0 -207
- package/docs/academy/01-GetStarted/04-BuildToDoListEditor.md +0 -218
- package/docs/academy/01-GetStarted/06-ReactorMCP.md +0 -58
- package/docs/academy/05-Architecture/02-ReferencingMonorepoPackages +0 -65
- package/docs/academy/05-Architecture/04-MovingBeyondCRUD +0 -61
- /package/docs/academy/{01-GetStarted → 02-MasteryTrack/01-BuilderEnvironment}/images/Modules.png +0 -0
- /package/docs/academy/{01-GetStarted → 02-MasteryTrack/01-BuilderEnvironment}/images/VetraStudioDrive.png +0 -0
- /package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/{02-RevisionHistoryTimeline → 02-RevisionHistoryTimeline/360/237/232/247"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{01-WhatIsADocumentModel → 360/237/232/247 /01-WhatIsADocumentModel"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{02-DAOandDocumentsModelsQ+A → 360/237/232/247 /02-DAOandDocumentsModelsQ+A"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{02-domain-modeling → 360/237/232/247 /02-domain-modeling"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{03-BenefitsOfDocumentModels → 360/237/232/247 /03-BenefitsOfDocumentModels"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{04-UtilitiesAndTips → 360/237/232/247 /04-UtilitiesAndTips"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{05-best-practices → 360/237/232/247 /05-best-practices"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{_category_.json → 360/237/232/247 /_category_.json"} +0 -0
- /package/docs/academy/05-Architecture/05-DocumentModelTheory/{three-data-layers.png → 360/237/232/247 /three-data-layers.png"} +0 -0
|
@@ -1,40 +1,122 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Build the ChatRoom editor
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
:::tip Tutorial Repository
|
|
4
|
+
📦 **Reference Code**: [chatroom-demo](https://github.com/powerhouse-inc/chatroom-demo)
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
This tutorial covers building the ChatRoom editor:
|
|
7
|
+
1. **Editor Scaffolding**: Generating the editor template with `ph generate --editor`
|
|
8
|
+
2. **Component Implementation**: Building a complete, interactive chat UI with components
|
|
9
|
+
|
|
10
|
+
Explore the complete implementation in the `editors/chat-room-editor/` directory.
|
|
11
|
+
:::
|
|
12
|
+
|
|
13
|
+
<details>
|
|
14
|
+
<summary>📖 How to use this tutorial</summary>
|
|
15
|
+
|
|
16
|
+
This tutorial shows building from **generated scaffolding** to a **complete chat UI**.
|
|
6
17
|
|
|
7
|
-
|
|
18
|
+
### Compare your generated editor
|
|
8
19
|
|
|
9
|
-
|
|
20
|
+
After running `pnpm generate --editor`:
|
|
10
21
|
|
|
11
22
|
```bash
|
|
12
|
-
|
|
23
|
+
# Compare generated scaffolding with the reference
|
|
24
|
+
git diff tutorial/main -- editors/chat-room-editor/
|
|
25
|
+
|
|
26
|
+
# View the generated editor template
|
|
27
|
+
git show tutorial/main:editors/chat-room-editor/editor.tsx
|
|
13
28
|
```
|
|
14
29
|
|
|
15
|
-
|
|
30
|
+
### Browse the complete implementation
|
|
16
31
|
|
|
17
|
-
|
|
32
|
+
Explore the production-ready component structure:
|
|
18
33
|
|
|
19
|
-
|
|
34
|
+
```bash
|
|
35
|
+
# List all components in the reference
|
|
36
|
+
git ls-tree -r --name-only tutorial/main editors/chat-room-editor/components/
|
|
20
37
|
|
|
21
|
-
|
|
22
|
-
|
|
38
|
+
# View a specific component
|
|
39
|
+
git show tutorial/main:editors/chat-room-editor/components/ChatRoom.tsx
|
|
40
|
+
```
|
|
23
41
|
|
|
24
|
-
|
|
42
|
+
### Visual comparison with GitHub Desktop
|
|
25
43
|
|
|
26
|
-
|
|
44
|
+
After committing your editor code:
|
|
45
|
+
1. **Branch** menu → **"Compare to Branch..."**
|
|
46
|
+
2. Select `tutorial/main`
|
|
47
|
+
3. See all your custom components vs. the reference implementation
|
|
48
|
+
|
|
49
|
+
See step 1 for detailed GitHub Desktop instructions.
|
|
50
|
+
|
|
51
|
+
</details>
|
|
52
|
+
|
|
53
|
+
In this chapter we will continue with the interface or editor implementation of the **ChatRoom** document model. This means you will create a user interface for the **ChatRoom** document model which will be used inside the Connect app to visualize your chatroom, send messages, and react with emojis.
|
|
54
|
+
|
|
55
|
+
## Generate the editor template
|
|
56
|
+
|
|
57
|
+
Run the command below to generate the editor template for the **ChatRoom** document model.
|
|
58
|
+
This command reads the **ChatRoom** document model definition from the `document-models` folder and generates the editor template in the `editors/chat-room-editor` folder.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pnpm generate --editor chat-room-editor --document-types powerhouse/chat-room
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Notice the `--editor` flag which specifies the editor name, and the `--document-types` flag defines the document type `powerhouse/chat-room`.
|
|
65
|
+
|
|
66
|
+
Once complete, you'll have a new directory structure:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
editors/chat-room-editor/
|
|
70
|
+
├── components/
|
|
71
|
+
│ └── EditName.tsx # Auto-generated component for editing document name
|
|
72
|
+
├── editor.tsx # Main editor component (to be customized)
|
|
73
|
+
└── module.ts # Editor module configuration
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Navigate to the `editors/chat-room-editor/editor.tsx` file and open it in your editor. You'll see a basic template ready for customization.
|
|
77
|
+
|
|
78
|
+
### Editor implementation options
|
|
79
|
+
|
|
80
|
+
When building your editor component within the Powerhouse ecosystem, you have several options for styling:
|
|
81
|
+
|
|
82
|
+
1. **Default HTML Styling:** Standard HTML tags will render with default styles offered through the boilerplate.
|
|
83
|
+
2. **Tailwind CSS:** Connect Studio comes with Tailwind CSS integrated. You can directly use Tailwind utility classes.
|
|
84
|
+
3. **Custom CSS Files:** You can import traditional CSS files to apply custom styles.
|
|
85
|
+
|
|
86
|
+
Connect Studio provides a dynamic local environment. By running `ph connect`, you can visualize your components instantly as you build them.
|
|
87
|
+
|
|
88
|
+
## Build the editor with components
|
|
89
|
+
|
|
90
|
+
We'll build the editor using a component-based approach for better organization and reusability.
|
|
91
|
+
|
|
92
|
+
### Component-based architecture
|
|
93
|
+
|
|
94
|
+
The ChatRoom editor structure includes several components that you can either build yourself or copy from the reference repository:
|
|
27
95
|
|
|
28
|
-
-
|
|
96
|
+
- `editor.tsx` - Main editor wrapper (imports ChatRoom)
|
|
97
|
+
- `ChatRoom.tsx` - Main container component that orchestrates all other components
|
|
98
|
+
- `Message.tsx` - Individual message component with reactions
|
|
99
|
+
- `EmojiReaction.tsx` - Emoji reaction UI component
|
|
100
|
+
- `TextInput.tsx` - Input component for sending messages
|
|
101
|
+
- `Avatar.tsx` - User avatar component
|
|
102
|
+
|
|
103
|
+
### Option 1: Copy components from the reference
|
|
104
|
+
|
|
105
|
+
Download the repository of the chatroom-demo as a zip file from https://github.com/powerhouse-inc/chatroom-demo and navigate to `editors/chat-room-editor` to copy both the `components` folder and `utils.ts` file.
|
|
106
|
+
|
|
107
|
+
In this folder you'll find:
|
|
108
|
+
- An avatar component for chat room participants
|
|
29
109
|
- The chatroom environment itself
|
|
30
110
|
- A header for the chatroom
|
|
31
|
-
- The UI for rendering
|
|
111
|
+
- The UI for rendering messages, usernames, and reaction popups
|
|
32
112
|
- The emoji reaction interface
|
|
33
|
-
- A
|
|
113
|
+
- A text input field component
|
|
34
114
|
|
|
35
|
-
The utils function will help you with mapping information from the document model to your chatroom components
|
|
115
|
+
The utils function will help you with mapping information from the document model to your chatroom components, such as mapping emoji values to the relevant emoji to be displayed.
|
|
36
116
|
|
|
37
|
-
|
|
117
|
+
### Option 2: Build the main editor file
|
|
118
|
+
|
|
119
|
+
If you want to understand how everything connects, here's the main `editor.tsx` implementation:
|
|
38
120
|
|
|
39
121
|
```typescript
|
|
40
122
|
import { generateId } from "document-model/core";
|
|
@@ -64,6 +146,7 @@ export default function Editor() {
|
|
|
64
146
|
return <div>Loading...</div>;
|
|
65
147
|
}
|
|
66
148
|
|
|
149
|
+
// Map document messages to component props
|
|
67
150
|
const messages: ChatRoomProps["messages"] =
|
|
68
151
|
document.state.global.messages.map((message) => ({
|
|
69
152
|
id: message.id,
|
|
@@ -75,10 +158,9 @@ export default function Editor() {
|
|
|
75
158
|
reactions: mapReactions(message.reactions),
|
|
76
159
|
}));
|
|
77
160
|
|
|
161
|
+
// Handler for sending messages
|
|
78
162
|
const onSendMessage: ChatRoomProps["onSendMessage"] = (message) => {
|
|
79
|
-
if (!message)
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
163
|
+
if (!message) return;
|
|
82
164
|
|
|
83
165
|
dispatch(
|
|
84
166
|
addMessage({
|
|
@@ -94,6 +176,7 @@ export default function Editor() {
|
|
|
94
176
|
);
|
|
95
177
|
};
|
|
96
178
|
|
|
179
|
+
// Handler for adding reactions
|
|
97
180
|
const addReaction = (
|
|
98
181
|
messageId: string,
|
|
99
182
|
userId: string,
|
|
@@ -108,6 +191,7 @@ export default function Editor() {
|
|
|
108
191
|
);
|
|
109
192
|
};
|
|
110
193
|
|
|
194
|
+
// Handler for removing reactions
|
|
111
195
|
const removeReaction = (
|
|
112
196
|
messageId: string,
|
|
113
197
|
userId: string,
|
|
@@ -122,14 +206,13 @@ export default function Editor() {
|
|
|
122
206
|
);
|
|
123
207
|
};
|
|
124
208
|
|
|
209
|
+
// Handler for clicking on reactions (toggle behavior)
|
|
125
210
|
const onClickReaction: MessageProps["onClickReaction"] = (reaction) => {
|
|
126
211
|
const message = messages.find(
|
|
127
212
|
(message) => message.id === reaction.messageId,
|
|
128
213
|
);
|
|
129
214
|
|
|
130
|
-
if (!message)
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
215
|
+
if (!message) return;
|
|
133
216
|
|
|
134
217
|
const messageId = reaction.messageId;
|
|
135
218
|
const reactionType = reactionKeyToReactionType(reaction.type);
|
|
@@ -150,6 +233,7 @@ export default function Editor() {
|
|
|
150
233
|
}
|
|
151
234
|
};
|
|
152
235
|
|
|
236
|
+
// Handlers for editing chat metadata
|
|
153
237
|
const onSubmitTitle: ChatRoomProps["onSubmitTitle"] = (title) => {
|
|
154
238
|
dispatch(editChatName({ name: title }));
|
|
155
239
|
};
|
|
@@ -161,11 +245,7 @@ export default function Editor() {
|
|
|
161
245
|
};
|
|
162
246
|
|
|
163
247
|
return (
|
|
164
|
-
<div
|
|
165
|
-
style={{
|
|
166
|
-
height: "calc(100vh - 140px)",
|
|
167
|
-
}}
|
|
168
|
-
>
|
|
248
|
+
<div style={{ height: "calc(100vh - 140px)" }}>
|
|
169
249
|
<ChatRoom
|
|
170
250
|
description={
|
|
171
251
|
document.state.global.description || "This is a chat room demo"
|
|
@@ -183,18 +263,91 @@ export default function Editor() {
|
|
|
183
263
|
}
|
|
184
264
|
```
|
|
185
265
|
|
|
186
|
-
|
|
266
|
+
**What's happening here:**
|
|
267
|
+
|
|
268
|
+
- We use `useSelectedChatRoomDocument` hook to get the document state and dispatch function
|
|
269
|
+
- We use `useUser` to get the current user information (for authentication)
|
|
270
|
+
- We map the document's messages to props that our ChatRoom component expects
|
|
271
|
+
- We create handlers for sending messages, adding/removing reactions, and editing metadata
|
|
272
|
+
- We dispatch operations (`addMessage`, `addEmojiReaction`, etc.) from our generated creators
|
|
273
|
+
|
|
274
|
+
:::info Key Concept: useSelectedChatRoomDocument hook
|
|
275
|
+
The `useSelectedChatRoomDocument` hook is generated by the Powerhouse CLI. It provides:
|
|
276
|
+
1. The current document state (`document`)
|
|
277
|
+
2. A dispatch function to send actions to the reducer
|
|
278
|
+
|
|
279
|
+
This hook connects your React components to the document model's state and operations.
|
|
280
|
+
:::
|
|
281
|
+
|
|
282
|
+
## Test your editor
|
|
283
|
+
|
|
284
|
+
Now you can run the Connect app and see the **ChatRoom** editor in action:
|
|
187
285
|
|
|
188
286
|
```bash
|
|
189
287
|
ph connect
|
|
190
288
|
```
|
|
191
289
|
|
|
192
|
-
In
|
|
290
|
+
In Connect, in the bottom right corner you'll find a new Document Model that you can create: **ChatRoom**. Click on it to create a new ChatRoom document.
|
|
193
291
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
292
|
+
:::warning Authentication Required
|
|
293
|
+
A warning will prompt you to login before you can send messages. Login with an Ethereum address via Renown to start sending messages.
|
|
294
|
+
:::
|
|
197
295
|
|
|
198
296
|

|
|
199
297
|
|
|
200
|
-
|
|
298
|
+
**Try it out:**
|
|
299
|
+
1. Create a new ChatRoom document
|
|
300
|
+
2. Login with your Ethereum wallet
|
|
301
|
+
3. Send messages using the input field
|
|
302
|
+
4. React to messages with emoji reactions
|
|
303
|
+
5. Click the chat name or description to edit them
|
|
304
|
+
|
|
305
|
+
Congratulations! 🎉
|
|
306
|
+
If you managed to follow this tutorial until this point, you have successfully implemented the **ChatRoom** document model with its reducer operations and editor.
|
|
307
|
+
|
|
308
|
+
## Compare with the reference implementation
|
|
309
|
+
|
|
310
|
+
The tutorial repository includes the complete ChatRoom editor with all components:
|
|
311
|
+
|
|
312
|
+
```
|
|
313
|
+
editors/chat-room-editor/
|
|
314
|
+
├── components/
|
|
315
|
+
│ ├── Avatar.tsx # User avatar display
|
|
316
|
+
│ ├── ChatRoom.tsx # Main chat container
|
|
317
|
+
│ ├── Header.tsx # Chat header with title/description
|
|
318
|
+
│ ├── Message.tsx # Individual message display
|
|
319
|
+
│ ├── EmojiReaction.tsx # Reaction UI
|
|
320
|
+
│ ├── TextInput.tsx # Message input field
|
|
321
|
+
│ └── index.ts # Component exports
|
|
322
|
+
├── editor.tsx # Main editor component
|
|
323
|
+
├── utils.ts # Utility functions for data mapping
|
|
324
|
+
└── module.ts # Editor module configuration
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**View individual components from the reference:**
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
# See the ChatRoom component implementation
|
|
331
|
+
git show tutorial/main:editors/chat-room-editor/components/ChatRoom.tsx
|
|
332
|
+
|
|
333
|
+
# Explore the Message component
|
|
334
|
+
git show tutorial/main:editors/chat-room-editor/components/Message.tsx
|
|
335
|
+
|
|
336
|
+
# Compare your implementation with the reference
|
|
337
|
+
git diff tutorial/main -- editors/chat-room-editor/
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## Key concepts learned
|
|
341
|
+
|
|
342
|
+
In this tutorial you've learned:
|
|
343
|
+
|
|
344
|
+
✅ **Component-based architecture** - Breaking down complex UIs into reusable components
|
|
345
|
+
✅ **Document model hooks** - Using `useSelectedChatRoomDocument` to connect React to your document state
|
|
346
|
+
✅ **User authentication** - Using `useUser` hook for wallet-based authentication
|
|
347
|
+
✅ **Action dispatching** - How to dispatch operations from your UI
|
|
348
|
+
✅ **Type-safe development** - Leveraging TypeScript with generated types from your SDL
|
|
349
|
+
✅ **Real-time collaboration** - Building features that work across multiple users
|
|
350
|
+
|
|
351
|
+
## Up next: Local Reactor
|
|
352
|
+
|
|
353
|
+
In the next section, you'll learn how to run a local Reactor to test real-time synchronization between multiple users.
|
|
@@ -1,15 +1,103 @@
|
|
|
1
1
|
# Launch a local Reactor
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
:::tip Tutorial Repository
|
|
4
|
+
📦 **Reference Code**: [chatroom-demo](https://github.com/powerhouse-inc/chatroom-demo)
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
This final step demonstrates real-time collaboration by running a local Reactor instance.
|
|
7
|
+
:::
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
In this final section, we'll create a local Reactor instance to test the real-time synchronization capabilities of your ChatRoom. This simulates how messages would sync between multiple users in a production environment.
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
## What is a Reactor?
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
A Reactor is a node in the Powerhouse network that:
|
|
14
|
+
- Hosts and synchronizes documents across multiple clients
|
|
15
|
+
- Manages document state and operations
|
|
16
|
+
- Enables real-time collaboration between users
|
|
12
17
|
|
|
13
|
-
|
|
18
|
+
In production, Reactors are typically hosted as remote servers. For development and testing, we can run a local Reactor.
|
|
14
19
|
|
|
15
|
-
|
|
20
|
+
## Start the local Reactor
|
|
21
|
+
|
|
22
|
+
First, stop the Connect application if it's running. Then start the Reactor:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
ph reactor
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This spins up a Reactor that:
|
|
29
|
+
- Runs locally on your machine
|
|
30
|
+
- Creates a public drive accessible from your Connect sidebar
|
|
31
|
+
- Enables synchronization between multiple browser sessions
|
|
32
|
+
|
|
33
|
+
## Test real-time collaboration
|
|
34
|
+
|
|
35
|
+
To validate the real-time functionality of your ChatRoom:
|
|
36
|
+
|
|
37
|
+
1. **Open two browser windows** with the Connect application
|
|
38
|
+
2. **Navigate to the Reactor drive** in the left sidebar (it will appear as a public drive)
|
|
39
|
+
3. **Login with different Ethereum addresses** in each window
|
|
40
|
+
4. **Create a ChatRoom document** in one window
|
|
41
|
+
5. **Open the same document** in the other window
|
|
42
|
+
|
|
43
|
+
Now you can:
|
|
44
|
+
- Send messages from one window and see them appear in the other
|
|
45
|
+
- React to messages with emojis and watch the reactions sync
|
|
46
|
+
- Edit the chat name or description and see updates propagate
|
|
47
|
+
|
|
48
|
+
:::info Real-time Sync
|
|
49
|
+
The Reactor ensures that all operations are synchronized across connected clients. Each message and reaction is recorded as an operation, maintaining a complete history that can be replayed to reconstruct the document state.
|
|
50
|
+
:::
|
|
51
|
+
|
|
52
|
+
## Additional features to explore
|
|
53
|
+
|
|
54
|
+
While testing your ChatRoom, try these features:
|
|
55
|
+
|
|
56
|
+
1. **Operation History**: Click on the revision history in the top right corner to see all operations performed on the document
|
|
57
|
+
|
|
58
|
+
2. **ENS Integration**: If you login with an Ethereum address that has an ENS name, your name and avatar will appear in your messages
|
|
59
|
+
|
|
60
|
+
3. **Reaction Toggling**: Click on an existing reaction to toggle it on/off for your user
|
|
61
|
+
|
|
62
|
+
## Running Connect alongside Reactor
|
|
63
|
+
|
|
64
|
+
You can also run Connect and Reactor together. In separate terminal windows:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Terminal 1: Start the Reactor
|
|
68
|
+
ph reactor
|
|
69
|
+
|
|
70
|
+
# Terminal 2: Start Connect (in a separate terminal)
|
|
71
|
+
ph connect
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This allows you to:
|
|
75
|
+
- Use Connect's local drive for development
|
|
76
|
+
- Access the Reactor's public drive for collaboration testing
|
|
77
|
+
- Switch between local and synchronized documents
|
|
78
|
+
|
|
79
|
+
## What you've accomplished
|
|
80
|
+
|
|
81
|
+
Congratulations! 🎉 You've now completed the ChatRoom tutorial and learned how to:
|
|
82
|
+
|
|
83
|
+
✅ **Create a Powerhouse project** - Initialize and configure a new project
|
|
84
|
+
✅ **Define a document model** - Design schemas using GraphQL SDL
|
|
85
|
+
✅ **Implement reducers** - Write the business logic for state transitions
|
|
86
|
+
✅ **Build an editor** - Create a React-based UI for your document
|
|
87
|
+
✅ **Test with a Reactor** - Validate real-time collaboration features
|
|
88
|
+
|
|
89
|
+
## Next steps
|
|
90
|
+
|
|
91
|
+
Now that you've completed this tutorial, you can:
|
|
92
|
+
|
|
93
|
+
1. **Explore the Mastery Track** - Dive deeper into [Document Model Creation](/academy/MasteryTrack/DocumentModelCreation/WhatIsADocumentModel) for advanced concepts
|
|
94
|
+
|
|
95
|
+
2. **Try Vetra Studio** - Use AI-assisted development with [Vetra Studio](/academy/GetStarted/VetraStudio) for faster iteration
|
|
96
|
+
|
|
97
|
+
3. **Build your own project** - Apply what you've learned to create your own document models and editors
|
|
98
|
+
|
|
99
|
+
4. **Join the community** - Connect with other Powerhouse builders and share your creations
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
*This tutorial demonstrated one of the many ways to use document models within the Powerhouse ecosystem. The patterns you've learned here apply to any collaborative application you want to build.*
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
"position": 2,
|
|
4
4
|
"link": {
|
|
5
5
|
"type": "generated-index",
|
|
6
|
-
"description": "
|
|
6
|
+
"description": "Build a real-time ChatRoom application with Powerhouse. This tutorial guides you through creating a document model for a chat application where users can post messages and react with emojis. You'll learn to define schemas, implement reducers, build a React editor, and test real-time synchronization using a local Reactor."
|
|
7
7
|
}
|
|
8
8
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Step 0 - get the starter code
|
|
2
|
+
|
|
3
|
+
Normally you would initialize a new powerhouse project by running `ph init` with your project name. But since this is a tutorial, we want to provide branches with the final code for each step.
|
|
4
|
+
|
|
5
|
+
Just for the tutorial, please instead make a fork of [this repository](https://github.com/powerhouse-inc/todo-tutorial).
|
|
6
|
+
|
|
7
|
+
*NOTE:* please _uncheck_ the checkbox that says "copy the main branch only" when making your fork — we want to keep the other branches for each step.
|
|
8
|
+
|
|
9
|
+
Once you have your fork, clone it to your machine with `git clone`, the GitHub desktop app or the GitHub cli.
|
|
10
|
+
|
|
11
|
+
The starter branch of this tutorial is: `step-1-generate-todo-list-document-model`.
|
|
12
|
+
|
|
13
|
+
Checkout that branch, and then create your own branch from it with whatever name you want, something like `do-the-tutorial` will work nicely.
|
|
14
|
+
|
|
15
|
+
The code at the step 1 branch of this repository is exactly the same as what you would get if you ran `ph init todo-tutorial`.
|
|
16
|
+
|
|
17
|
+
Each step in this tutorial has two branches associated with it. One is the starting point and the other is the final code after the step is complete. They each have names like `step-1-` for the starting point and `step-1-complete-` for the complete code. You can use the starting point branches if you want to start at a later step or skip a step, and you can use the complete code to compare with your branch if you get stuck.
|
|
18
|
+
|
|
19
|
+
To compare your branch, either do `git diff my-branch step-complete-branch` or use the "compare with branch" option in the GitHub desktop app.
|
|
20
|
+
|
|
21
|
+
Finally, run `pnpm install` to install the project dependencies.
|
|
22
|
+
|
|
23
|
+
Now we're ready to get started.
|
|
24
|
+
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# Step 1 - Generate the `TodoList` document model
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This tutorial guides you through creating a simplified version of a 'Powerhouse project' for a **To-do List**.
|
|
6
|
+
A Powerhouse project primarily consists of a document model and its editor.
|
|
7
|
+
As your projects use-case expands you can add data-integrations or a specific drive-app as seen in the demo package.
|
|
8
|
+
|
|
9
|
+
For todays purpose, you'll be using Connect, our user-centric collaboration tool and Vetra Studio, the builder tooling through which developers can access and manage specifications of your project.
|
|
10
|
+
|
|
11
|
+
## Develop a single document model in Connect
|
|
12
|
+
|
|
13
|
+
Once in the project directory, run the `pnpm connect` command to start a local instance of the Connect application. This allows you to start your document model specification document.
|
|
14
|
+
Run the following command to start the Connect application:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm connect
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The Connect application will start and you will see the following output:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
➜ Local: http://localhost:3000/
|
|
24
|
+
➜ Network: http://192.168.5.110:3000/
|
|
25
|
+
➜ press h + enter to show help
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
A new browser window will open and you will see the Connect application. If it doesn't open automatically, you can open it manually by navigating to `http://localhost:3000/` in your browser. You will see your local drive and a button to create a new drive.
|
|
29
|
+
|
|
30
|
+
:::tip
|
|
31
|
+
If you local drive is not present navigate into Settings in the bottom left corner. Settings > Danger Zone > Clear Storage.
|
|
32
|
+
Clear the storage of your localhost application as it might has an old session cached.
|
|
33
|
+
:::
|
|
34
|
+
|
|
35
|
+
4. Move into your local drive.
|
|
36
|
+
Create a new document model by clicking the `DocumentModel` button, found in the 'New Document' section at the bottom of the page. Name your document `Todo List`.
|
|
37
|
+
|
|
38
|
+
If you've followed the steps correctly, you'll have an empty `TodoList` document where you can define the **'Document Specifications'**.
|
|
39
|
+
|
|
40
|
+
## TodoList document specification
|
|
41
|
+
|
|
42
|
+
To start, fill in the following details for your new document model:
|
|
43
|
+
|
|
44
|
+
Name: `Todo List`
|
|
45
|
+
Document type: `powerhouse/todo-list`
|
|
46
|
+
Author name: Powerhouse
|
|
47
|
+
Website URL: https://powerhouse.inc
|
|
48
|
+
|
|
49
|
+
It's important that you use these exact details so that your generated code matches the generated code in the tutorial repository.
|
|
50
|
+
|
|
51
|
+
We'll continue with this project to teach you how to create a document model specification and later an editor for your document model. We use the **GraphQL Schema Definition Language** (SDL) to define the schema for the document model.
|
|
52
|
+
Below, you can see the SDL for the `TodoList` document model.
|
|
53
|
+
|
|
54
|
+
:::info
|
|
55
|
+
This schema defines the **data structure** of the document model and the types involved in its operations, which are detailed further as input types.
|
|
56
|
+
Documents in Powerhouse leverage **event sourcing principles**, where every state transition is represented by an operation. GraphQL input types describe operations, ensuring that user intents are captured effectively. These operations detail the parameters needed for state transitions. The use of GraphQL aligns these transitions with explicit, validated, and reproducible commands.
|
|
57
|
+
:::
|
|
58
|
+
|
|
59
|
+
## The document model state schema
|
|
60
|
+
|
|
61
|
+
First, let's add a graphql type that represents an individual item in a todo list document. A todo item has an ID, text, and can be either checked or unchecked.
|
|
62
|
+
|
|
63
|
+
Add this underneath the boilerplate `TodoListState` type you see in the Global State Schema text editor.
|
|
64
|
+
|
|
65
|
+
```graphql
|
|
66
|
+
# Defines a GraphQL type for a single to-do item
|
|
67
|
+
type TodoItem {
|
|
68
|
+
id: OID! # Unique identifier for each to-do item
|
|
69
|
+
text: String! # The text description of the to-do item
|
|
70
|
+
checked: Boolean! # Status of the to-do item (checked/unchecked)
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Now update the `TodoListState` type to use our new type by replacing the boilerplate with this:
|
|
75
|
+
|
|
76
|
+
```graphql
|
|
77
|
+
type TodoListState {
|
|
78
|
+
items: [TodoItem!]!
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The final result in your editor should look like this:
|
|
83
|
+
|
|
84
|
+
```graphql
|
|
85
|
+
type TodoListState {
|
|
86
|
+
items: [TodoItem!]!
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
# Defines a GraphQL type for a single to-do item
|
|
90
|
+
type TodoItem {
|
|
91
|
+
id: OID! # Unique identifier for each to-do item
|
|
92
|
+
text: String! # The text description of the to-do item
|
|
93
|
+
checked: Boolean! # Status of the to-do item (checked/unchecked)
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
With our state schema defined, go ahead and click the "Sync with schema" button underneath "Global State Initial Value". This will set the initial state for the documents you create with this model based on the schema you defined.
|
|
98
|
+
|
|
99
|
+
Your initial value field should now look like this:
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"items": []
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Operation inputs and their schemas
|
|
108
|
+
|
|
109
|
+
We've defined the shape for the state of our `TodoList` documents, but we also need to be able to update them.
|
|
110
|
+
|
|
111
|
+
Documents are updated by dispatching actions, which are applied to documents as operations.
|
|
112
|
+
|
|
113
|
+
We define modules to group sets of operations together. In this simple case, we will only need one module.
|
|
114
|
+
|
|
115
|
+
Add a new module for our `todos` operations by typing `todos` in the "Add new module" input and pressing enter.
|
|
116
|
+
|
|
117
|
+
We need to add three different operations to this module:
|
|
118
|
+
|
|
119
|
+
1. add todo item
|
|
120
|
+
2. update todo item
|
|
121
|
+
3. delete todo item
|
|
122
|
+
|
|
123
|
+
Let's start with adding todos.
|
|
124
|
+
|
|
125
|
+
When we add a new todo, the only input we need to provide is the text. Creating the ID will be handled later in our reducer code, and todos always start as unchecked by default.
|
|
126
|
+
|
|
127
|
+
type `add todo item` in the "Add new operation" input and press enter.
|
|
128
|
+
|
|
129
|
+
You will see your new operation with the name `ADD_TODO_ITEM` (we automatically handle changing the casing to the required CONSTANT_CASE).
|
|
130
|
+
|
|
131
|
+
You will also see a boilerplate placeholder graphql input.
|
|
132
|
+
|
|
133
|
+
Update the graphql input like so:
|
|
134
|
+
|
|
135
|
+
```graphql
|
|
136
|
+
input AddTodoItemInput {
|
|
137
|
+
text: String!
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Next let's handle updating todo items.
|
|
142
|
+
|
|
143
|
+
Type `update todo item` in the "Add new operation" input and press enter.
|
|
144
|
+
|
|
145
|
+
For updating items, we will need to provide an `id` so we know which one to update. We can use the same operation to update the text or the checked state, so both of these fields are optional (no ! on the field).
|
|
146
|
+
|
|
147
|
+
Update the `UpdateTodoItemInput` to be like so:
|
|
148
|
+
|
|
149
|
+
```graphql
|
|
150
|
+
input UpdateTodoItemInput {
|
|
151
|
+
id: OID!
|
|
152
|
+
text: String
|
|
153
|
+
checked: Boolean
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Finally, we can handle the delete item operation.
|
|
158
|
+
|
|
159
|
+
type `delete todo item` in the "Add new operation" input.
|
|
160
|
+
|
|
161
|
+
For deleting items, all we need is an `id`.
|
|
162
|
+
|
|
163
|
+
Update your `DeleteTodoItemInput` to be like this:
|
|
164
|
+
|
|
165
|
+
```graphql
|
|
166
|
+
input DeleteTodoItemInput {
|
|
167
|
+
id: OID!
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Once you have added all the input operations, click the `Export` button at the top right of the editor to save the document model specification document to your local machine. Ideally, you should save your file in the root of your repository with the name `todo-list.phd`
|
|
172
|
+
|
|
173
|
+
## Generating your document model code
|
|
174
|
+
|
|
175
|
+
With our newly created document model, we can run the codegen to generate the rest of the code for it.
|
|
176
|
+
|
|
177
|
+
To run the codegen, you use the `generate` command with a path to the file you just exported.
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
pnpm generate ./todo-list.phd
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**NOTE:** this generated code contains values that will always be different for each generated document model, like module ids for example. For the purposes of this tutorial, we recommend that you instead use the reference example that we have already included in the repo for you — this will make your generated code look exactly the same as the generated code in the branches in the repo, and your diffs will match exactly.
|
|
184
|
+
|
|
185
|
+
To use our reference example, run:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
pnpm generate ./todo-list.phdm.phd
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
This will overwrite your generated code with code that is identical to the branches in this repository.
|
|
192
|
+
|
|
193
|
+
## Check your work
|
|
194
|
+
|
|
195
|
+
To make sure all works as expected, we should:
|
|
196
|
+
|
|
197
|
+
- check types
|
|
198
|
+
run: `pnpm tsc`
|
|
199
|
+
|
|
200
|
+
- check linting
|
|
201
|
+
run: `pnpm lint`
|
|
202
|
+
|
|
203
|
+
- check tests
|
|
204
|
+
run: `pnpm test`
|
|
205
|
+
|
|
206
|
+
- make sure your code matches the code in the completed step branch
|
|
207
|
+
run: `git diff your-branch-name step-1-complete-generated-todo-list-document-model`
|
|
208
|
+
|
|
209
|
+
### Up next: reducers and operations
|
|
210
|
+
|
|
211
|
+
Up next, you'll learn how to implement the runtime logic and components that will use the `TodoList` document model specification you've just created and exported.
|